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