Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code

Side by Side Diff: lib/adblockplus_compat.js

Issue 8483154: Adding ABP core modules to ABP/Opera (Closed)
Patch Set: Created Oct. 11, 2012, 9:35 a.m.
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 /*
2 * This Source Code is subject to the terms of the Mozilla Public License
3 * version 2.0 (the "License"). You can obtain a copy of the License at
4 * http://mozilla.org/MPL/2.0/.
5 */
6
7 // TODO: Parts of this file are identical to ABP/Chrome, these should be split
8 // away into a separate file.
9
10 //
11 // Module framework stuff
12 //
13
14 function require(module)
15 {
16 return require.scopes[module];
17 }
18 require.scopes = {__proto__: null};
19
20 function importAll(module, globalObj)
21 {
22 var exports = require(module);
23 for (var key in exports)
24 globalObj[key] = exports[key];
25 }
26
27 onShutdown = {
28 done: false,
29 add: function() {},
30 remove: function() {}
31 };
32
33 //
34 // XPCOM emulation
35 //
36
37 var Components =
38 {
39 interfaces:
40 {
41 nsIFile: {DIRECTORY_TYPE: 0},
42 nsIFileURL: function() {},
43 nsIHttpChannel: function() {},
44 nsITimer: {TYPE_REPEATING_SLACK: 0},
45 nsIInterfaceRequestor: null,
46 nsIChannelEventSink: null
47 },
48 classes:
49 {
50 "@mozilla.org/timer;1":
51 {
52 createInstance: function()
53 {
54 return new FakeTimer();
55 }
56 },
57 "@mozilla.org/xmlextras/xmlhttprequest;1":
58 {
59 createInstance: function()
60 {
61 return new XMLHttpRequest();
62 }
63 }
64 },
65 results: {},
66 utils: {
67 reportError: function(e)
68 {
69 opera.postError(e + "\n" + (typeof e == "object" ? e.stack : new Error().s tack));
70 }
71 },
72 manager: null,
73 ID: function()
74 {
75 return null;
76 }
77 };
78 const Cc = Components.classes;
79 const Ci = Components.interfaces;
80 const Cr = Components.results;
81 const Cu = Components.utils;
82
83 var XPCOMUtils =
84 {
85 generateQI: function() {}
86 };
87
88 //
89 // Info pseudo-module
90 //
91
92 require.scopes.info =
93 {
94 get addonID()
95 {
96 return widget.id;
97 },
98 addonVersion: "2.0.3", // Hardcoded for now
99 addonRoot: "",
100 get addonName()
101 {
102 return widget.name;
103 },
104 application: "opera"
105 };
106
107 //
108 // IO module: no direct file system access, using FileSystem API
109 //
110
111 require.scopes.io =
112 {
113 IO: {
114 _getFilePath: function(file)
115 {
116 if (file instanceof FakeFile)
117 return file.path;
118 else if ("spec" in file)
119 return file.spec;
120
121 throw new Error("Unexpected file type");
122 },
123
124 _setFileContents: function(path, contents, lastModified)
125 {
126 window.localStorage[path] = contents;
127 window.localStorage[path + "/lastModified"] = lastModified || 0;
128 },
129
130 lineBreak: "\n",
131
132 resolveFilePath: function(path)
133 {
134 return new FakeFile(path);
135 },
136
137 readFromFile: function(file, decode, listener, callback, timeLineID)
138 {
139 // Fake asynchronous execution
140 setTimeout(function()
141 {
142 if ("spec" in file && /^defaults\b/.test(file.spec))
143 {
144 // Code attempts to read the default patterns.ini, we don't have that.
145 // Make sure to execute first-run actions instead.
146 callback(null);
147 executeFirstRunActions();
Felix Dahlke 2012/10/11 13:10:02 This function cannot be called from here.
148 return;
149 }
150
151 var path = this._getFilePath(file);
152 if (!(path in window.localStorage))
153 {
154 callback(new Error("File doesn't exist"))
155 return;
156 }
157
158 var lines = window.localStorage[path].split(/[\r\n]+/);
159 for (var i = 0; i < lines.length; i++)
160 listener.process(lines[i]);
161 listener.process(null);
162 callback(null);
163 }.bind(this), 0);
164 },
165
166 writeToFile: function(file, encode, data, callback, timeLineID)
167 {
168 var path = this._getFilePath(file);
169 this._setFileContents(path, data.join(this.lineBreak) + this.lineBreak, Da te.now());
170
171 // Fake asynchronous execution
172 setTimeout(callback.bind(null, null), 0);
173 },
174
175 copyFile: function(fromFile, toFile, callback)
176 {
177 // Simply combine read and write operations
178 var data = [];
179 this.readFromFile(fromFile, false, {
180 process: function(line)
181 {
182 if (line !== null)
183 data.push(line);
184 }
185 }, function(e)
186 {
187 if (e)
188 callback(e);
189 else
190 this.writeToFile(toFile, false, data, callback);
191 }.bind(this));
192 },
193
194 renameFile: function(fromFile, newName, callback)
195 {
196 var path = this._getFilePath(fromFile);
197 if (!(path in window.localStorage))
198 {
199 callback(new Error("File doesn't exist"))
200 return;
201 }
202
203 this._setFileContents(newName, window.localStorage[path], window.localStor age[path + "/lastModified"]);
204 this.removeFile(fromFile, callback);
205 },
206
207 removeFile: function(file, callback)
208 {
209 var path = this._getFilePath(file);
210 delete window.localStorage[path];
211 delete window.localStorage[path + "/lastModified"];
212 callback(null);
213 },
214
215 statFile: function(file, callback)
216 {
217 var path = this._getFilePath(file);
218 callback(null, {
219 exists: path in window.localStorage,
220 isDirectory: false,
221 isFile: true,
222 lastModified: parseInt(window.localStorage[path + "/lastModified"], 10) || 0
223 });
224 }
225 }
226 };
227
228 //
229 // Fake nsIFile implementation for our I/O
230 //
231
232 function FakeFile(path)
233 {
234 this.path = path;
235 }
236 FakeFile.prototype =
237 {
238 get leafName()
239 {
240 return this.path;
241 },
242 set leafName(value)
243 {
244 this.path = value;
245 },
246 append: function(path)
247 {
248 this.path += path;
249 },
250 clone: function()
251 {
252 return new FakeFile(this.path);
253 },
254 get parent()
255 {
256 return {create: function() {}};
257 },
258 normalize: function() {}
259 };
260
261 //
262 // Prefs module: the values are hardcoded for now.
263 //
264
265 require.scopes.prefs = {
266 Prefs: {
267 enabled: true,
268 patternsfile: "patterns.ini",
269 patternsbackups: 0,
270 patternsbackupinterval: 24,
271 data_directory: "",
272 savestats: false,
273 privateBrowsing: false,
274 subscriptions_fallbackerrors: 5,
275 subscriptions_fallbackurl: "https://adblockplus.org/getSubscription?version= %VERSION%&url=%SUBSCRIPTION%&downloadURL=%URL%&error=%ERROR%&channelStatus=%CHAN NELSTATUS%&responseStatus=%RESPONSESTATUS%",
276 subscriptions_autoupdate: true,
277 subscriptions_exceptionsurl: "https://easylist-downloads.adblockplus.org/exc eptionrules.txt",
278 documentation_link: "https://adblockplus.org/redirect?link=%LINK%&lang=%LANG %",
279 addListener: function() {}
280 }
281 };
282
283 //
284 // Utils module
285 //
286
287 require.scopes.utils =
288 {
289 Utils: {
290 systemPrincipal: null,
291 getString: function(id)
292 {
293 return id;
294 },
295 runAsync: function(callback, thisPtr)
296 {
297 var params = Array.prototype.slice.call(arguments, 2);
298 window.setTimeout(function()
299 {
300 callback.apply(thisPtr, params);
301 }, 0);
302 },
303 get appLocale()
304 {
305 // Note: navigator.language
306 return window.navigator.browserLanguage;
307 },
308 generateChecksum: function(lines)
309 {
310 // We cannot calculate MD5 checksums yet :-(
311 return null;
312 },
313 makeURI: function(url)
314 {
315 return Services.io.newURI(url);
316 },
317 checkLocalePrefixMatch: function(prefixes)
318 {
319 if (!prefixes)
320 return null;
321
322 var list = prefixes.split(",");
323 for (var i = 0; i < list.length; i++)
324 if (new RegExp("^" + list[i] + "\\b").test(this.appLocale))
325 return list[i];
326
327 return null;
328 }
329 }
330 };
331
332 //
333 // ElemHideHitRegistration dummy implementation
334 //
335
336 require.scopes.elemHideHitRegistration =
337 {
338 AboutHandler: {}
339 };
340
341 //
342 // Services.jsm module emulation
343 //
344
345 var Services =
346 {
347 io: {
348 newURI: function(uri)
349 {
350 if (!uri.length || uri[0] == "~")
351 throw new Error("Invalid URI");
352
353 /^([^:\/]*)/.test(uri);
354 var scheme = RegExp.$1.toLowerCase();
355
356 return {
357 scheme: scheme,
358 spec: uri,
359 QueryInterface: function()
360 {
361 return this;
362 }
363 };
364 },
365 newFileURI: function(file)
366 {
367 var result = this.newURI("file:///" + file.path);
368 result.file = file;
369 return result;
370 }
371 },
372 obs: {
373 addObserver: function() {},
374 removeObserver: function() {}
375 },
376 vc: {
377 compare: function(v1, v2)
378 {
379 function parsePart(s)
380 {
381 if (!s)
382 return parsePart("0");
383
384 var part = {
385 numA: 0,
386 strB: "",
387 numC: 0,
388 extraD: ""
389 };
390
391 if (s === "*")
392 {
393 part.numA = Number.MAX_VALUE;
394 return part;
395 }
396
397 var matches = s.match(/(\d*)(\D*)(\d*)(.*)/);
398 part.numA = parseInt(matches[1], 10) || part.numA;
399 part.strB = matches[2] || part.strB;
400 part.numC = parseInt(matches[3], 10) || part.numC;
401 part.extraD = matches[4] || part.extraD;
402
403 if (part.strB == "+")
404 {
405 part.numA++;
406 part.strB = "pre";
407 }
408
409 return part;
410 }
411
412 function comparePartElement(s1, s2)
413 {
414 if (s1 === "" && s2 !== "")
415 return 1;
416 if (s1 !== "" && s2 === "")
417 return -1;
418 return s1 === s2 ? 0 : (s1 > s2 ? 1 : -1);
419 }
420
421 function compareParts(p1, p2)
422 {
423 var result = 0;
424 var elements = ["numA", "strB", "numC", "extraD"];
425 elements.some(function(element)
426 {
427 result = comparePartElement(p1[element], p2[element]);
428 return result;
429 });
430 return result;
431 }
432
433 var parts1 = v1.split(".");
434 var parts2 = v2.split(".");
435 for (var i = 0; i < Math.max(parts1.length, parts2.length); i++)
436 {
437 var result = compareParts(parsePart(parts1[i]), parsePart(parts2[i]));
438 if (result)
439 return result;
440 }
441 return 0;
442 }
443 }
444 }
445
446 //
447 // FileUtils.jsm module emulation
448 //
449
450 var FileUtils =
451 {
452 PERMS_DIRECTORY: 0
453 };
454
455 function FakeTimer()
456 {
457 }
458 FakeTimer.prototype =
459 {
460 delay: 0,
461 callback: null,
462 initWithCallback: function(callback, delay)
463 {
464 this.callback = callback;
465 this.delay = delay;
466 this.scheduleTimeout();
467 },
468 scheduleTimeout: function()
469 {
470 var me = this;
471 window.setTimeout(function()
472 {
473 try
474 {
475 me.callback();
476 }
477 catch(e)
478 {
479 Cu.reportError(e);
480 }
481 me.scheduleTimeout();
482 }, this.delay);
483 }
484 };
485
486 //
487 // Add a channel property to XMLHttpRequest, Synchronizer needs it
488 //
489
490 XMLHttpRequest.prototype.channel =
491 {
492 status: -1,
493 notificationCallbacks: {},
494 loadFlags: 0,
495 INHIBIT_CACHING: 0,
496 VALIDATE_ALWAYS: 0,
497 QueryInterface: function()
498 {
499 return this;
500 }
501 };
OLDNEW
« background.js ('K') | « lib/adblockplus.js ('k') | lib/matcher.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld