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

Side by Side Diff: assets/js/start.js

Issue 8482109: ABP/Android JavaScript code (Closed)
Patch Set: ABP/Android JavaScript code Created Nov. 12, 2012, 9:32 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
« assets/js/XMLHttpRequest.jsm ('K') | « assets/js/punycode.js ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 function removeTrailingDots(string)
8 {
9 return string.replace(/\.+$/, "");
10 }
11
12 /**
13 * Checks whether a request is third party for the given document, uses
14 * information from the public suffix list to determine the effective domain
15 * name for the document.
16 */
17 function isThirdParty(requestHost, documentHost)
18 {
19 requestHost = removeTrailingDots(requestHost);
20 documentHost = removeTrailingDots(documentHost);
21
22 // Extract domain name - leave IP addresses unchanged, otherwise leave only ba se domain
23 var documentDomain = getBaseDomain(documentHost);
24 if (requestHost.length > documentDomain.length)
25 return (requestHost.substr(requestHost.length - documentDomain.length - 1) ! = "." + documentDomain);
26 else
27 return (requestHost != documentDomain);
28 }
29
30 function reportError(exp)
31 {
32 Android.print("Error: " + exp);
33 if (typeof exp == "string")
34 {
35 Android.showToast(exp);
36 }
37 Android.print(exp.stack);
38 }
39
40 function MatcherPatch()
41 {
42 // Very ugly - we need to rewrite _checkEntryMatch() function to make sure
43 // it calls Filter.fromText() instead of assuming that the filter exists.
44 var origFunction = Matcher.prototype._checkEntryMatch.toString();
45 var newFunction = origFunction.replace(/\bFilter\.knownFilters\[(.*?)\];/g, "F ilter.fromText($1);");
46 eval("Matcher.prototype._checkEntryMatch = " + newFunction);
47 }
48
49 var window = this;
50
51 var Components =
52 {
53 interfaces:
54 {
55 nsIFile: {DIRECTORY_TYPE: 0},
56 nsIFileURL: function() {},
57 nsIFileInputStream: null,
58 nsIFileOutputStream: null,
59 nsIHttpChannel: function() {},
60 nsIConverterInputStream: {DEFAULT_REPLACEMENT_CHARACTER: null},
61 nsIConverterOutputStream: null,
62 nsIUnicharLineInputStream: null,
63 nsISafeOutputStream: null,
64 nsITimer: {TYPE_REPEATING_SLACK: 0},
65 nsIInterfaceRequestor: null,
66 nsIChannelEventSink: null
67 },
68 classes:
69 {
70 "@mozilla.org/network/file-input-stream;1":
71 {
72 createInstance: function()
73 {
74 return new FakeInputStream();
75 }
76 },
77 "@mozilla.org/network/file-output-stream;1":
78 {
79 createInstance: function()
80 {
81 return new FakeOutputStream();
82 }
83 },
84 "@mozilla.org/dom/json;1":
85 {
86 createInstance: function() {
87 return {
88 decodeFromStream: function(stream, encoding)
89 {
90 var line = {};
91 var haveMore = true;
92 var s = new String();
93 while (true)
94 {
95 if (haveMore)
96 haveMore = stream.readLine(line);
97 else
98 break;
99 s += line.value;
100 }
101 return JSON.parse(s);
102 },
103 encodeToStream: function(stream, encoding, something, obj)
104 {
105 var s = JSON.stringify(obj);
106 stream.writeString(s);
107 }
108 }
109 }
110 },
111 "@mozilla.org/timer;1":
112 {
113 createInstance: function()
114 {
115 return new FakeTimer();
116 }
117 }
118 },
119 results: {},
120 utils: {
121 reportError: reportError
122 },
123 manager: null,
124 ID: function()
125 {
126 return null;
127 },
128 Constructor: function()
129 {
130 // This method is only used to get XMLHttpRequest constructor
131 return XMLHttpRequest;
132 }
133 };
134 const Cc = Components.classes;
135 const Ci = Components.interfaces;
136 const Cr = Components.results;
137 const Cu = Components.utils;
138
139 Cc["@mozilla.org/intl/converter-input-stream;1"] = Cc["@mozilla.org/network/file -input-stream;1"];
140 Cc["@mozilla.org/network/safe-file-output-stream;1"] = Cc["@mozilla.org/intl/con verter-output-stream;1"] = Cc["@mozilla.org/network/file-output-stream;1"];
141
142 var Prefs =
143 {
144 patternsbackups: 5,
145 patternsbackupinterval: 24,
146 data_directory: _datapath,
147 savestats: false,
148 privateBrowsing: false,
149 get subscriptions_autoupdate() { return Android.canAutoupdate() },
150 subscriptions_fallbackerrors: 5,
151 subscriptions_fallbackurl: "https://adblockplus.org/getSubscription?version=%V ERSION%&url=%SUBSCRIPTION%&downloadURL=%URL%&error=%ERROR%&channelStatus=%CHANNE LSTATUS%&responseStatus=%RESPONSESTATUS%",
152 addListener: function() {}
153 };
154
155 var Utils =
156 {
157 systemPrincipal: null,
158 getString: function(id)
159 {
160 return id;
161 },
162 getLineBreak: function()
163 {
164 return "\n";
165 },
166 resolveFilePath: function(path)
167 {
168 return new FakeFile(path);
169 },
170 ioService:
171 {
172 newURI: function(uri)
173 {
174 if (!uri.length || uri[0] == "~")
175 throw new Error("Invalid URI");
176
177 /^([^:\/]*)/.test(uri);
178 var scheme = RegExp.$1.toLowerCase();
179
180 return {scheme: scheme, spec: uri};
181 }
182 },
183 observerService:
184 {
185 addObserver: function() {},
186 removeObserver: function() {}
187 },
188 chromeRegistry:
189 {
190 convertChromeURL: function() {}
191 },
192 runAsync: function(callback, thisPtr)
193 {
194 var params = Array.prototype.slice.call(arguments, 2);
195 Android.setTimeout(function()
196 {
197 callback.apply(thisPtr, params);
198 }, 0);
199 },
200 addonVersion: _version,
201 platformVersion: "10.0",
202 get appLocale()
203 {
204 Android.getLocale();
205 },
206 generateChecksum: function(lines)
207 {
208 // We cannot calculate MD5 checksums yet :-(
209 return null;
210 },
211 makeURI: function(url)
212 {
213 return Utils.ioService.newURI(url);
214 },
215 checkLocalePrefixMatch: function(prefixes)
216 {
217 if (!prefixes)
218 return null;
219
220 var list = prefixes.split(",");
221 for (var i = 0; i < list.length; i++)
222 if (new RegExp("^" + list[i] + "\\b").test(Utils.appLocale))
223 return list[i];
224
225 return null;
226 },
227 versionComparator:
228 {
229 compare: function(v1, v2)
230 {
231 var parts1 = v1.split(".");
232 var parts2 = v2.split(".");
233 for (var i = 0; i < Math.max(parts1.length, parts2.length); i++)
234 {
235 // TODO: Handle non-integer version parts properly
236 var part1 = parseInt(i < parts1.length ? parts1[i] : "0");
237 var part2 = parseInt(i < parts2.length ? parts2[i] : "0");
238 if (part1 != part2)
239 return part1 - part2;
240 }
241 return 0;
242 }
243 }
244 };
245
246 var XPCOMUtils =
247 {
248 generateQI: function() {}
249 };
250
251 function FakeFile(path)
252 {
253 this.path = path;
254 }
255 FakeFile.prototype =
256 {
257 get leafName()
258 {
259 return this.path;
260 },
261 set leafName(value)
262 {
263 this.path = value;
264 },
265 append: function(path)
266 {
267 this.path += _separator + path;
268 },
269 clone: function()
270 {
271 return new FakeFile(this.path);
272 },
273 exists: function()
274 {
275 return Android.fileExists(this.path);
276 },
277 remove: function()
278 {
279 Android.fileRemove(this.path);
280 },
281 moveTo: function(parent, newPath)
282 {
283 Android.fileRename(this.path, newPath);
284 },
285 get lastModifiedTime()
286 {
287 return Android.fileLastModified(this.path);
288 },
289 get parent()
290 {
291 return {create: function() {}};
292 },
293 normalize: function() {}
294 };
295
296 function FakeInputStream()
297 {
298 }
299 FakeInputStream.prototype =
300 {
301 lines: null,
302 currentIndex: 0,
303
304 init: function(file)
305 {
306 if (file instanceof FakeInputStream)
307 this.lines = file.lines;
308 else
309 this.lines = Android.fileRead(file.path).split(/\n/);
310 },
311 readLine: function(line)
312 {
313 if (this.currentIndex < this.lines.length)
314 line.value = this.lines[this.currentIndex];
315 this.currentIndex++;
316 return (this.currentIndex < this.lines.length);
317 },
318 close: function() {},
319 QueryInterface: function()
320 {
321 return this;
322 }
323 };
324
325 function FakeOutputStream()
326 {
327 }
328 FakeOutputStream.prototype =
329 {
330 file: null,
331 buffer: null,
332
333 init: function(file)
334 {
335 if (file instanceof FakeOutputStream)
336 {
337 this.file = file.file;
338 this.buffer = file.buffer;
339 }
340 else
341 {
342 this.file = file;
343 this.buffer = [];
344 }
345 },
346 writeString: function(string)
347 {
348 this.buffer.push(string);
349 },
350 close: function()
351 {
352 Android.fileWrite(this.file.path, this.buffer.join(""));
353 },
354 finish: function()
355 {
356 this.close();
357 },
358 flush: function() {},
359 QueryInterface: function()
360 {
361 return this;
362 }
363 };
364
365 function FakeTimer()
366 {
367 }
368 FakeTimer.prototype =
369 {
370 delay: 0,
371 callback: null,
372 initWithCallback: function(callback, delay)
373 {
374 this.callback = callback;
375 this.delay = delay;
376 this.scheduleTimeout();
377 },
378 scheduleTimeout: function()
379 {
380 var me = this;
381 Android.setTimeout(function()
382 {
383 try
384 {
385 me.callback();
386 }
387 catch(e)
388 {
389 reportError(e);
390 }
391 me.scheduleTimeout();
392 }, this.delay);
393 }
394 };
395
396 function ElemHidePatch()
397 {
398 /**
399 * Returns a list of selectors to be applied on a particular domain. With
400 * specificOnly parameter set to true only the rules listing specific domains
401 * will be considered.
402 */
403 ElemHide.getSelectorsForDomain = function(/**String*/ domain, /**Boolean*/ spe cificOnly)
404 {
405 var result = [];
406 for (var key in filterByKey)
407 {
408 var filter = Filter.knownFilters[filterByKey[key]];
409 if (specificOnly && (!filter.domains || filter.domains[""]))
410 continue;
411
412 if (filter.isActiveOnDomain(domain))
413 result.push(filter.selector);
414 }
415 if (result.length)
416 return "<style type=\"text/css\">" + result.join() + " { display: none !im portant }</style>";
417 else
418 return null;
419 };
420
421 ElemHide.init = function() {};
422 }
423
424 /**
425 * Removes all subscriptions from storage.
426 */
427 function clearSubscriptions()
428 {
429 while (FilterStorage.subscriptions.length)
430 FilterStorage.removeSubscription(FilterStorage.subscriptions[0]);
431 }
432
433 /**
434 * Adds selected subscription to storage.
435 */
436 function addSubscription(jsonSub)
437 {
438 var newSub = JSON.parse(jsonSub);
439
440 var subscription = Subscription.fromURL(newSub["url"]);
441 if (subscription)
442 {
443 subscription.disabled = false;
444 subscription.title = newSub["title"];
445 subscription.homepage = newSub["homepage"];
446 if (subscription instanceof DownloadableSubscription && !subscription.lastDo wnload)
447 {
448 Synchronizer.execute(subscription);
449 }
450 FilterStorage.addSubscription(subscription);
451 FilterStorage.saveToDisk();
452 }
453 }
454
455 /**
456 * Forces subscriptions refresh.
457 */
458 function refreshSubscriptions()
459 {
460 for (var i = 0; i < FilterStorage.subscriptions.length; i++)
461 {
462 var subscription = FilterStorage.subscriptions[i];
463 if (subscription instanceof DownloadableSubscription)
464 Synchronizer.execute(subscription, true, true);
465 }
466 }
467
468 /**
469 * Verifies that subscriptions are loaded and returns flag of subscription prese nce.
470 */
471 function verifySubscriptions()
472 {
473 var hasSubscriptions = false;
474 for (var i = 0; i < FilterStorage.subscriptions.length; i++)
475 {
476 var subscription = FilterStorage.subscriptions[i];
477 if (subscription instanceof DownloadableSubscription)
478 {
479 hasSubscriptions = true;
480 updateSubscriptionStatus(subscription);
481 if (!subscription.lastDownload)
482 {
483 Synchronizer.execute(subscription);
484 }
485 }
486 }
487 return hasSubscriptions;
488 }
489
490 /**
491 * Callback for subscription status updates.
492 */
493 function updateSubscriptionStatus(subscription)
494 {
495 var status = "";
496 var time = 0;
497 if (Synchronizer.isExecuting(subscription.url))
498 status = "synchronize_in_progress";
499 else if (subscription.downloadStatus && subscription.downloadStatus != "synchr onize_ok")
500 status = subscription.downloadStatus;
501 else if (subscription.lastDownload > 0)
502 {
503 time = subscription.lastDownload * 1000;
504 status = "synchronize_last_at";
505 }
506 else
507 status = "synchronize_never";
508
509 Android.setStatus(status, time);
510 }
511
512 function onFilterChange(action, subscription, param1, param2)
513 {
514 switch (action)
515 {
516 case "subscription.lastDownload":
517 case "subscription.downloadStatus":
518 updateSubscriptionStatus(subscription);
519 break;
520 }
521 }
522
523 function startInteractive()
524 {
525 FilterNotifier.addListener(onFilterChange);
526 }
527
528 function stopInteractive()
529 {
530 FilterNotifier.removeListener(onFilterChange);
531 }
532
533 function matchesAny(url, query, reqHost, refHost, accept)
534 {
535 var contentType = null;
536 var thirdParty = true;
537
538 if (accept != "")
539 {
540 if (accept.indexOf("text/css") != -1)
541 contentType = "STYLESHEET";
542 else if (accept.indexOf("image/*" != -1))
543 contentType = "IMAGE";
544 }
545
546 if (contentType == null)
547 {
548 var lurl = url.toLowerCase();
549 if (/\.js$/.test(lurl))
550 contentType = "SCRIPT";
551 else if (/\.css$/.test(lurl))
552 contentType = "STYLESHEET";
553 else if (/\.(?:gif|png|jpe?g|bmp|ico)$/.test(lurl))
554 contentType = "IMAGE";
555 else if (/\.(?:ttf|woff)$/.test(lurl))
556 contentType = "FONT";
557 }
558 if (contentType == null)
559 contentType = "OTHER";
560
561 if (refHost != "")
562 {
563 thirdParty = isThirdParty(reqHost, refHost);
564 }
565
566 if (query != "")
567 url = url + "?" + query;
568
569 var filter = defaultMatcher.matchesAny(url, contentType, null, thirdParty);
570
571 return (filter != null && !(filter instanceof WhitelistFilter));
572 }
573
574 Android.load("XMLHttpRequest.jsm");
575 Android.load("FilterNotifier.jsm");
576 Android.load("FilterClasses.jsm");
577 Android.load("SubscriptionClasses.jsm");
578 Android.load("FilterStorage.jsm");
579 Android.load("FilterListener.jsm");
580 Android.load("Matcher.jsm");
581 Android.load("ElemHide.jsm");
582 Android.load("Synchronizer.jsm");
583
584 FilterListener.startup();
585 Synchronizer.startup();
586
587 Android.load("publicSuffixList.js");
588 Android.load("punycode.js");
589 Android.load("basedomain.js");
OLDNEW
« assets/js/XMLHttpRequest.jsm ('K') | « assets/js/punycode.js ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld