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

Delta Between Two Patch Sets: background.js

Issue 6393086494113792: Issue 154 - Added devtools panel showing blocked and blockable items (Closed)
Left Patch Set: Rebased and fixed documentation mistakenly indicating arguments as optional Created Feb. 28, 2015, 5:52 p.m.
Right Patch Set: Adapt for UI changes generating domain specific filters when necessary Created Feb. 3, 2016, 10:40 a.m.
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments.
Jump to:
Left: Side by side diff | Download
Right: Side by side diff | Download
« no previous file with change/comment | « no previous file | chrome/devtools.html » ('j') | no next file with change/comment »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
LEFTRIGHT
1 /* 1 /*
2 * This file is part of Adblock Plus <https://adblockplus.org/>, 2 * This file is part of Adblock Plus <https://adblockplus.org/>,
3 * Copyright (C) 2006-2015 Eyeo GmbH 3 * Copyright (C) 2006-2016 Eyeo GmbH
4 * 4 *
5 * Adblock Plus is free software: you can redistribute it and/or modify 5 * Adblock Plus is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 3 as 6 * it under the terms of the GNU General Public License version 3 as
7 * published by the Free Software Foundation. 7 * published by the Free Software Foundation.
8 * 8 *
9 * Adblock Plus is distributed in the hope that it will be useful, 9 * Adblock Plus is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details. 12 * GNU General Public License for more details.
13 * 13 *
14 * You should have received a copy of the GNU General Public License 14 * You should have received a copy of the GNU General Public License
15 * along with Adblock Plus. If not, see <http://www.gnu.org/licenses/>. 15 * along with Adblock Plus. If not, see <http://www.gnu.org/licenses/>.
16 */ 16 */
17 17
18 with(require("filterClasses")) 18 with(require("filterClasses"))
19 { 19 {
20 this.Filter = Filter; 20 this.Filter = Filter;
21 this.BlockingFilter = BlockingFilter; 21 this.BlockingFilter = BlockingFilter;
22 this.WhitelistFilter = WhitelistFilter; 22 this.WhitelistFilter = WhitelistFilter;
23 this.RegExpFilter = RegExpFilter;
23 } 24 }
24 with(require("subscriptionClasses")) 25 with(require("subscriptionClasses"))
25 { 26 {
26 this.Subscription = Subscription; 27 this.Subscription = Subscription;
27 this.DownloadableSubscription = DownloadableSubscription; 28 this.DownloadableSubscription = DownloadableSubscription;
28 this.SpecialSubscription = SpecialSubscription; 29 this.SpecialSubscription = SpecialSubscription;
29 } 30 }
30 with(require("whitelisting")) 31 with(require("whitelisting"))
31 { 32 {
32 this.isPageWhitelisted = isPageWhitelisted; 33 this.checkWhitelisted = checkWhitelisted;
33 this.isFrameWhitelisted = isFrameWhitelisted;
34 this.processKey = processKey; 34 this.processKey = processKey;
35 this.getKey = getKey; 35 this.getKey = getKey;
36 } 36 }
37 with(require("url")) 37 with(require("url"))
38 { 38 {
39 this.stringifyURL = stringifyURL; 39 this.stringifyURL = stringifyURL;
40 this.isThirdParty = isThirdParty; 40 this.isThirdParty = isThirdParty;
41 this.extractHostFromFrame = extractHostFromFrame; 41 this.extractHostFromFrame = extractHostFromFrame;
42 } 42 }
43 with(require("icon"))
44 {
45 this.updateIcon = updateIcon;
46 this.startIconAnimation = startIconAnimation;
47 this.stopIconAnimation = stopIconAnimation;
48 }
49 with(require("devtools"))
50 {
51 this.hasDevToolsPanel = hasDevToolsPanel;
52 this.logHiddenElements = logHiddenElements;
53 }
54 var FilterStorage = require("filterStorage").FilterStorage; 43 var FilterStorage = require("filterStorage").FilterStorage;
44 var FilterNotifier = require("filterNotifier").FilterNotifier;
55 var ElemHide = require("elemHide").ElemHide; 45 var ElemHide = require("elemHide").ElemHide;
56 var defaultMatcher = require("matcher").defaultMatcher; 46 var defaultMatcher = require("matcher").defaultMatcher;
57 var Prefs = require("prefs").Prefs; 47 var Prefs = require("prefs").Prefs;
58 var Synchronizer = require("synchronizer").Synchronizer; 48 var Synchronizer = require("synchronizer").Synchronizer;
59 var Utils = require("utils").Utils; 49 var Utils = require("utils").Utils;
60 var NotificationStorage = require("notification").Notification;
61 var initAntiAdblockNotification = require("antiadblockInit").initAntiAdblockNoti fication;
62 var parseFilters = require("filterValidation").parseFilters; 50 var parseFilters = require("filterValidation").parseFilters;
63 51 var composeFilters = require("filterComposer").composeFilters;
64 // Chrome on Linux does not fully support chrome.notifications until version 35 52 var updateIcon = require("icon").updateIcon;
65 // https://code.google.com/p/chromium/issues/detail?id=291485 53 var initNotifications = require("notificationHelper").initNotifications;
66 var canUseChromeNotifications = require("info").platform == "chromium" 54 var showNextNotificationForUrl = require("notificationHelper").showNextNotificat ionForUrl;
67 && "notifications" in chrome 55 var devtools = require("devtools");
68 && (navigator.platform.indexOf("Linux") == -1 || parseInt(require("info").appl icationVersion, 10) > 34);
69 56
70 var seenDataCorruption = false; 57 var seenDataCorruption = false;
71 var filterlistsReinitialized = false; 58 var filterlistsReinitialized = false;
72 require("filterNotifier").FilterNotifier.addListener(function(action) 59
73 { 60 function init()
74 if (action == "load") 61 {
75 { 62 var filtersLoaded = new Promise(function(resolve)
76 var addonVersion = require("info").addonVersion; 63 {
77 var prevVersion = ext.storage.currentVersion; 64 function onFilterAction(action)
65 {
66 if (action == "load")
67 {
68 FilterNotifier.removeListener(onFilterAction);
69 resolve();
70 }
71 }
72 FilterNotifier.addListener(onFilterAction);
73 });
74
75 function onLoaded()
76 {
77 var info = require("info");
78 var previousVersion = Prefs.currentVersion;
78 79
79 // There are no filters stored so we need to reinitialize all filterlists 80 // There are no filters stored so we need to reinitialize all filterlists
80 if (!FilterStorage.firstRun && FilterStorage.subscriptions.length === 0) 81 if (!FilterStorage.firstRun && FilterStorage.subscriptions.length === 0)
81 { 82 {
82 filterlistsReinitialized = true; 83 filterlistsReinitialized = true;
83 prevVersion = null; 84 previousVersion = null;
84 } 85 }
85 86
86 if (prevVersion != addonVersion || FilterStorage.firstRun) 87 if (previousVersion != info.addonVersion || FilterStorage.firstRun)
87 { 88 {
88 seenDataCorruption = prevVersion && FilterStorage.firstRun; 89 seenDataCorruption = previousVersion && FilterStorage.firstRun;
89 ext.storage.currentVersion = addonVersion; 90 Prefs.currentVersion = info.addonVersion;
90 addSubscription(prevVersion); 91 addSubscription(previousVersion);
91 } 92 }
92 93
93 if (canUseChromeNotifications) 94 initNotifications();
94 initChromeNotifications(); 95
95 initAntiAdblockNotification(); 96 // Update browser actions and context menus when whitelisting might have
96 97 // changed. That is now when initally loading the filters and later when
97 // The "Hide placeholders" option has been removed from the UI in 1.8.8.1285 98 // importing backups or saving filter changes.
98 // So we reset the option for users updating from older versions. 99 FilterNotifier.addListener(function(action)
99 if (prevVersion && Services.vc.compare(prevVersion, "1.8.8.1285") < 0) 100 {
100 Prefs.hidePlaceholders = true; 101 if (action == "load" || action == "save")
101 } 102 refreshIconAndContextMenuForAllPages();
102 103 });
103 // update browser actions when whitelisting might have changed,
104 // due to loading filters or saving filter changes
105 if (action == "load" || action == "save")
106 refreshIconAndContextMenuForAllPages(); 104 refreshIconAndContextMenuForAllPages();
107 }); 105 }
106
107 Promise.all([filtersLoaded, Prefs.isLoaded]).then(onLoaded);
108 }
109 init();
108 110
109 // Special-case domains for which we cannot use style-based hiding rules. 111 // Special-case domains for which we cannot use style-based hiding rules.
110 // See http://crbug.com/68705. 112 // See http://crbug.com/68705.
111 var noStyleRulesHosts = ["mail.google.com", "mail.yahoo.com", "www.google.com"]; 113 var noStyleRulesHosts = ["mail.google.com", "mail.yahoo.com", "www.google.com"];
112 114
113 var htmlPages = new ext.PageMap(); 115 var htmlPages = new ext.PageMap();
114
115 function removeDeprecatedOptions()
116 {
117 var deprecatedOptions = ["specialCaseYouTube", "experimental", "disableInlineT extAds"];
118 deprecatedOptions.forEach(function(option)
119 {
120 if (option in ext.storage)
121 delete ext.storage[option];
122 });
123 }
124
125 // Remove deprecated options before we do anything else.
126 removeDeprecatedOptions();
127
128 var activeNotification = null;
129 116
130 var contextMenuItem = { 117 var contextMenuItem = {
131 title: ext.i18n.getMessage("block_element"), 118 title: ext.i18n.getMessage("block_element"),
132 contexts: ["image", "video", "audio"], 119 contexts: ["image", "video", "audio"],
133 onclick: function(page) 120 onclick: function(page)
134 { 121 {
135 page.sendMessage({type: "clickhide-new-filter"}); 122 page.sendMessage({type: "clickhide-new-filter"});
136 } 123 }
137 }; 124 };
138 125
139 // Adds or removes browser action icon according to options. 126 // Adds or removes browser action icon according to options.
140 function refreshIconAndContextMenu(page) 127 function refreshIconAndContextMenu(page)
141 { 128 {
142 var whitelisted = isPageWhitelisted(page); 129 var whitelisted = !!checkWhitelisted(page);
143 updateIcon(page, whitelisted); 130 updateIcon(page, whitelisted);
144 131
145 // show or hide the context menu entry dependent on whether 132 // show or hide the context menu entry dependent on whether
146 // adblocking is active on that page 133 // adblocking is active on that page
147 page.contextMenus.removeAll(); 134 page.contextMenus.remove(contextMenuItem);
148 if (Prefs.shouldShowBlockElementMenu && !whitelisted && htmlPages.has(page)) 135 if (Prefs.shouldShowBlockElementMenu && !whitelisted && htmlPages.has(page))
149 page.contextMenus.create(contextMenuItem); 136 page.contextMenus.create(contextMenuItem);
150 } 137 }
151 138
152 function refreshIconAndContextMenuForAllPages() 139 function refreshIconAndContextMenuForAllPages()
153 { 140 {
154 ext.pages.query({}, function(pages) 141 ext.pages.query({}, function(pages)
155 { 142 {
156 pages.forEach(refreshIconAndContextMenu); 143 pages.forEach(refreshIconAndContextMenu);
157 }); 144 });
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
219 subscription.disabled = true; 206 subscription.disabled = true;
220 FilterStorage.addSubscription(subscription); 207 FilterStorage.addSubscription(subscription);
221 if (subscription instanceof DownloadableSubscription && !subscription.last Download) 208 if (subscription instanceof DownloadableSubscription && !subscription.last Download)
222 Synchronizer.execute(subscription); 209 Synchronizer.execute(subscription);
223 } 210 }
224 } 211 }
225 212
226 if (!addSubscription && !addAcceptable) 213 if (!addSubscription && !addAcceptable)
227 return; 214 return;
228 215
229 function notifyUser() 216 Promise.resolve(addSubscription && fetch("subscriptions.xml")
230 { 217 .then(function(response)
231 ext.pages.open(ext.getURL("firstRun.html")); 218 {
232 } 219 return response.text();
233 220 })
234 if (addSubscription) 221 .then(function(text)
235 { 222 {
236 // Load subscriptions data 223 var doc = new DOMParser().parseFromString(text, "application/xml");
237 var request = new XMLHttpRequest(); 224 var nodes = doc.getElementsByTagName("subscription");
238 request.open("GET", "subscriptions.xml"); 225 var node = Utils.chooseFilterSubscription(nodes);
239 request.addEventListener("load", function() 226 var subscription = node && Subscription.fromURL(node.getAttribute("url"));
240 { 227
241 var node = Utils.chooseFilterSubscription(request.responseXML.getElementsB yTagName("subscription"));
242 var subscription = (node ? Subscription.fromURL(node.getAttribute("url")) : null);
243 if (subscription) 228 if (subscription)
244 { 229 {
245 FilterStorage.addSubscription(subscription); 230 FilterStorage.addSubscription(subscription);
231
246 subscription.disabled = false; 232 subscription.disabled = false;
247 subscription.title = node.getAttribute("title"); 233 subscription.title = node.getAttribute("title");
248 subscription.homepage = node.getAttribute("homepage"); 234 subscription.homepage = node.getAttribute("homepage");
249 if (subscription instanceof DownloadableSubscription && !subscription.la stDownload) 235
236 if (subscription instanceof DownloadableSubscription &&
237 !subscription.lastDownload)
250 Synchronizer.execute(subscription); 238 Synchronizer.execute(subscription);
251 239 }
252 notifyUser(); 240 })
253 } 241 )
254 }, false); 242 .then(function()
255 request.send(null); 243 {
256 } 244 if (!Prefs.suppress_first_run_page)
257 else 245 ext.pages.open(ext.getURL("firstRun.html"));
258 notifyUser(); 246 });
259 } 247 }
260 248
261 Prefs.addListener(function(name) 249 Prefs.onChanged.addListener(function(name)
262 { 250 {
263 if (name == "shouldShowBlockElementMenu") 251 if (name == "shouldShowBlockElementMenu")
264 refreshIconAndContextMenuForAllPages(); 252 refreshIconAndContextMenuForAllPages();
265 }); 253 });
266
267 function prepareNotificationIconAndPopup()
268 {
269 var animateIcon = (activeNotification.type !== "question");
270 activeNotification.onClicked = function()
271 {
272 if (animateIcon)
273 stopIconAnimation();
274 notificationClosed();
275 };
276 if (animateIcon)
277 startIconAnimation(activeNotification.type);
278 }
279
280 function openNotificationLinks()
281 {
282 if (activeNotification.links)
283 {
284 activeNotification.links.forEach(function(link)
285 {
286 ext.windows.getLastFocused(function(win)
287 {
288 win.openTab(Utils.getDocLink(link));
289 });
290 });
291 }
292 }
293
294 function notificationButtonClick(buttonIndex)
295 {
296 if (activeNotification.type === "question")
297 {
298 NotificationStorage.triggerQuestionListeners(activeNotification.id, buttonIn dex === 0);
299 NotificationStorage.markAsShown(activeNotification.id);
300 activeNotification.onClicked();
301 }
302 else if (activeNotification.links && activeNotification.links[buttonIndex])
303 {
304 ext.windows.getLastFocused(function(win)
305 {
306 win.openTab(Utils.getDocLink(activeNotification.links[buttonIndex]));
307 });
308 }
309 }
310
311 function notificationClosed()
312 {
313 activeNotification = null;
314 }
315
316 function imgToBase64(url, callback)
317 {
318 var canvas = document.createElement("canvas"),
319 ctx = canvas.getContext("2d"),
320 img = new Image;
321 img.src = url;
322 img.onload = function()
323 {
324 canvas.height = img.height;
325 canvas.width = img.width;
326 ctx.drawImage(img, 0, 0);
327 callback(canvas.toDataURL("image/png"));
328 canvas = null;
329 };
330 }
331
332 function initChromeNotifications()
333 {
334 // Chrome hides notifications in notification center when clicked so we need t o clear them
335 function clearActiveNotification(notificationId)
336 {
337 if (activeNotification && activeNotification.type != "question" && !("links" in activeNotification))
338 return;
339
340 chrome.notifications.clear(notificationId, function(wasCleared)
341 {
342 if (wasCleared)
343 notificationClosed();
344 });
345 }
346
347 chrome.notifications.onButtonClicked.addListener(function(notificationId, butt onIndex)
348 {
349 notificationButtonClick(buttonIndex);
350 clearActiveNotification(notificationId);
351 });
352 chrome.notifications.onClicked.addListener(clearActiveNotification);
353 chrome.notifications.onClosed.addListener(notificationClosed);
354 }
355
356 function showNotification(notification)
357 {
358 if (activeNotification && activeNotification.id === notification.id)
359 return;
360
361 activeNotification = notification;
362 if (activeNotification.type === "critical" || activeNotification.type === "que stion")
363 {
364 var texts = NotificationStorage.getLocalizedTexts(notification);
365 var title = texts.title || "";
366 var message = texts.message ? texts.message.replace(/<\/?(a|strong)>/g, "") : "";
367 var iconUrl = ext.getURL("icons/abp-128.png");
368 var hasLinks = activeNotification.links && activeNotification.links.length > 0;
369
370 if (canUseChromeNotifications)
371 {
372 var opts = {
373 type: "basic",
374 title: title,
375 message: message,
376 buttons: [],
377 priority: 2 // We use the highest priority to prevent the notification f rom closing automatically
378 };
379 if (activeNotification.type === "question")
380 {
381 opts.buttons.push({title: ext.i18n.getMessage("overlay_notification_butt on_yes")});
382 opts.buttons.push({title: ext.i18n.getMessage("overlay_notification_butt on_no")});
383 }
384 else
385 {
386 var regex = /<a>(.*?)<\/a>/g;
387 var plainMessage = texts.message || "";
388 var match;
389 while (match = regex.exec(plainMessage))
390 opts.buttons.push({title: match[1]});
391 }
392
393 imgToBase64(iconUrl, function(iconData)
394 {
395 opts["iconUrl"] = iconData;
396 chrome.notifications.create("", opts, function() {});
397 });
398 }
399 else if ("Notification" in window && activeNotification.type !== "question")
400 {
401 if (hasLinks)
402 message += " " + ext.i18n.getMessage("notification_without_buttons");
403
404 imgToBase64(iconUrl, function(iconData)
405 {
406 var notification = new Notification(
407 title,
408 {
409 lang: Utils.appLocale,
410 dir: ext.i18n.getMessage("@@bidi_dir"),
411 body: message,
412 icon: iconData
413 }
414 );
415
416 notification.addEventListener("click", openNotificationLinks);
417 notification.addEventListener("close", notificationClosed);
418 });
419 }
420 else
421 {
422 var message = title + "\n" + message;
423 if (hasLinks)
424 message += "\n\n" + ext.i18n.getMessage("notification_with_buttons");
425
426 var approved = confirm(message);
427 if (activeNotification.type === "question")
428 notificationButtonClick(approved ? 0 : 1);
429 else if (approved)
430 openNotificationLinks();
431 }
432 }
433 prepareNotificationIconAndPopup();
434 }
435 254
436 // This is a hack to speedup loading of the options page on Safari. 255 // This is a hack to speedup loading of the options page on Safari.
437 // Once we replaced the background page proxy with message passing 256 // Once we replaced the background page proxy with message passing
438 // this global function should removed. 257 // this global function should removed.
439 function getUserFilters() 258 function getUserFilters()
440 { 259 {
441 var filters = []; 260 var filters = [];
442 var exceptions = []; 261 var exceptions = [];
443 262
444 for (var i = 0; i < FilterStorage.subscriptions.length; i++) 263 for (var i = 0; i < FilterStorage.subscriptions.length; i++)
(...skipping 14 matching lines...) Expand all
459 278
460 return {filters: filters, exceptions: exceptions}; 279 return {filters: filters, exceptions: exceptions};
461 } 280 }
462 281
463 ext.onMessage.addListener(function (msg, sender, sendResponse) 282 ext.onMessage.addListener(function (msg, sender, sendResponse)
464 { 283 {
465 switch (msg.type) 284 switch (msg.type)
466 { 285 {
467 case "get-selectors": 286 case "get-selectors":
468 var selectors = []; 287 var selectors = [];
469 288 var trace = devtools && devtools.hasPanel(sender.page);
470 if (!isFrameWhitelisted(sender.page, sender.frame, "DOCUMENT") && 289
471 !isFrameWhitelisted(sender.page, sender.frame, "ELEMHIDE")) 290 if (!checkWhitelisted(sender.page, sender.frame,
291 RegExpFilter.typeMap.DOCUMENT |
292 RegExpFilter.typeMap.ELEMHIDE))
472 { 293 {
473 var noStyleRules = false; 294 var noStyleRules = false;
295 var specificOnly = checkWhitelisted(sender.page, sender.frame,
296 RegExpFilter.typeMap.GENERICHIDE);
474 var host = extractHostFromFrame(sender.frame); 297 var host = extractHostFromFrame(sender.frame);
298
475 for (var i = 0; i < noStyleRulesHosts.length; i++) 299 for (var i = 0; i < noStyleRulesHosts.length; i++)
476 { 300 {
477 var noStyleHost = noStyleRulesHosts[i]; 301 var noStyleHost = noStyleRulesHosts[i];
478 if (host == noStyleHost || (host.length > noStyleHost.length && 302 if (host == noStyleHost || (host.length > noStyleHost.length &&
479 host.substr(host.length - noStyleHost.leng th - 1) == "." + noStyleHost)) 303 host.substr(host.length - noStyleHost.leng th - 1) == "." + noStyleHost))
480 { 304 {
481 noStyleRules = true; 305 noStyleRules = true;
482 } 306 }
483 } 307 }
484 selectors = ElemHide.getSelectorsForDomain(host, false); 308 selectors = ElemHide.getSelectorsForDomain(host, specificOnly);
485 if (noStyleRules) 309 if (noStyleRules)
486 { 310 {
487 selectors = selectors.filter(function(s) 311 selectors = selectors.filter(function(s)
488 { 312 {
489 return !/\[style[\^\$]?=/.test(s); 313 return !/\[style[\^\$]?=/.test(s);
490 }); 314 });
491 } 315 }
492 } 316 }
493 317
494 sendResponse({selectors: selectors, trace: hasDevToolsPanel(sender.page)}) ; 318 sendResponse({selectors: selectors, trace: trace});
495 break; 319 break;
496 case "should-collapse": 320 case "should-collapse":
497 if (isFrameWhitelisted(sender.page, sender.frame, "DOCUMENT")) 321 if (checkWhitelisted(sender.page, sender.frame))
498 { 322 {
499 sendResponse(false); 323 sendResponse(false);
500 break; 324 break;
501 } 325 }
502 326
503 var url = new URL(msg.url); 327 var typeMask = RegExpFilter.typeMap[msg.mediatype];
504 var documentHost = extractHostFromFrame(sender.frame); 328 var documentHost = extractHostFromFrame(sender.frame);
505 var filter = defaultMatcher.matchesAny( 329 var sitekey = getKey(sender.page, sender.frame);
506 stringifyURL(url), msg.mediatype, 330 var blocked = false;
507 documentHost, isThirdParty(url, documentHost) 331
508 ); 332 for (var i = 0; i < msg.urls.length; i++)
509 333 {
510 if (filter instanceof BlockingFilter) 334 var url = new URL(msg.urls[i], msg.baseURL);
511 { 335 var filter = defaultMatcher.matchesAny(
512 var collapse = filter.collapse; 336 stringifyURL(url), typeMask,
513 if (collapse == null) 337 documentHost, isThirdParty(url, documentHost), sitekey
514 collapse = Prefs.hidePlaceholders; 338 );
515 sendResponse(collapse); 339
516 } 340 if (filter instanceof BlockingFilter)
517 else 341 {
518 sendResponse(false); 342 if (filter.collapse != null)
343 {
344 sendResponse(filter.collapse);
345 return;
346 }
347
348 blocked = true;
349 }
350 }
351
352 sendResponse(blocked && Prefs.hidePlaceholders);
519 break; 353 break;
520 case "get-domain-enabled-state": 354 case "get-domain-enabled-state":
521 // Returns whether this domain is in the exclusion list. 355 // Returns whether this domain is in the exclusion list.
522 // The browser action popup asks us this. 356 // The browser action popup asks us this.
523 if(sender.page) 357 if(sender.page)
524 { 358 {
525 sendResponse({enabled: !isPageWhitelisted(sender.page)}); 359 sendResponse({enabled: !checkWhitelisted(sender.page)});
526 return; 360 return;
527 } 361 }
528 break; 362 break;
529 case "add-filters": 363 case "add-filters":
530 var filters; 364 var result = parseFilters(msg.text);
531 try 365
532 { 366 if (result.errors.length > 0)
533 filters = parseFilters(msg.text); 367 {
534 } 368 sendResponse({status: "invalid", error: result.errors.join("\n")});
535 catch (error)
536 {
537 sendResponse({status: "invalid", error: error});
538 break; 369 break;
539 } 370 }
540 371
541 for (var i = 0; i < filters.length; i++) 372 for (var i = 0; i < result.filters.length; i++)
542 FilterStorage.addFilter(filters[i]); 373 FilterStorage.addFilter(result.filters[i]);
543 374
544 sendResponse({status: "ok"}); 375 sendResponse({status: "ok"});
545 break;
546 case "add-subscription":
547 ext.showOptions(function(page)
548 {
549 page.sendMessage(msg);
550 });
551 break; 376 break;
552 case "add-sitekey": 377 case "add-sitekey":
553 processKey(msg.token, sender.page, sender.frame); 378 processKey(msg.token, sender.page, sender.frame);
554 break; 379 break;
555 case "report-html-page": 380 case "report-html-page":
556 htmlPages.set(sender.page, null); 381 htmlPages.set(sender.page, null);
557 refreshIconAndContextMenu(sender.page); 382 refreshIconAndContextMenu(sender.page);
558 break; 383 break;
384 case "compose-filters":
385 sendResponse(composeFilters({
386 tagName: msg.tagName,
387 id: msg.id,
388 src: msg.src,
389 style: msg.style,
390 classes: msg.classes,
391 urls: msg.urls,
392 type: msg.mediatype,
393 baseURL: msg.baseURL,
394 page: sender.page,
395 frame: sender.frame
396 }));
397 break;
559 case "trace-elemhide": 398 case "trace-elemhide":
560 logHiddenElements(sender.page, msg.selectors, extractHostFromFrame(sender. frame)); 399 devtools.logHiddenElements(
400 sender.page, msg.selectors,
401 extractHostFromFrame(sender.frame)
402 );
561 break; 403 break;
562 case "forward": 404 case "forward":
563 if (sender.page) 405 if (sender.page)
564 { 406 {
565 if (msg.expectsResponse) 407 if (msg.expectsResponse)
566 { 408 {
567 sender.page.sendMessage(msg.payload, sendResponse); 409 sender.page.sendMessage(msg.payload, sendResponse);
568 return true; 410 return true;
569 } 411 }
570 412
571 sender.page.sendMessage(msg.payload); 413 sender.page.sendMessage(msg.payload);
572 } 414 }
573 break; 415 break;
574 } 416 }
575 }); 417 });
576 418
577 // update icon when page changes location 419 // update icon when page changes location
578 ext.pages.onLoading.addListener(function(page) 420 ext.pages.onLoading.addListener(function(page)
579 { 421 {
580 page.sendMessage({type: "clickhide-deactivate"}); 422 page.sendMessage({type: "clickhide-deactivate"});
581 refreshIconAndContextMenu(page); 423 refreshIconAndContextMenu(page);
424 showNextNotificationForUrl(page.url);
582 }); 425 });
583
584 setTimeout(function()
585 {
586 var notificationToShow = NotificationStorage.getNextToShow();
587 if (notificationToShow)
588 showNotification(notificationToShow);
589 }, 3 * 60 * 1000);
LEFTRIGHT

Powered by Google App Engine
This is Rietveld