| LEFT | RIGHT | 
|---|
| 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-2015 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.isPageWhitelisted = isPageWhitelisted; | 
| 33   this.isFrameWhitelisted = isFrameWhitelisted; | 34   this.isFrameWhitelisted = isFrameWhitelisted; | 
| 34   this.processKey = processKey; | 35   this.processKey = processKey; | 
| 35   this.getKey = getKey; | 36   this.getKey = getKey; | 
| 36 } | 37 } | 
| 37 with(require("url")) | 38 with(require("url")) | 
| 38 { | 39 { | 
| 39   this.stringifyURL = stringifyURL; | 40   this.stringifyURL = stringifyURL; | 
| 40   this.isThirdParty = isThirdParty; | 41   this.isThirdParty = isThirdParty; | 
| 41   this.extractHostFromFrame = extractHostFromFrame; | 42   this.extractHostFromFrame = extractHostFromFrame; | 
| 42 } | 43 } | 
| 43 with(require("icon")) |  | 
| 44 { |  | 
| 45   this.updateIcon = updateIcon; |  | 
| 46   this.startIconAnimation = startIconAnimation; |  | 
| 47   this.stopIconAnimation = stopIconAnimation; |  | 
| 48 } |  | 
| 49 var FilterStorage = require("filterStorage").FilterStorage; | 44 var FilterStorage = require("filterStorage").FilterStorage; | 
|  | 45 var FilterNotifier = require("filterNotifier").FilterNotifier; | 
| 50 var ElemHide = require("elemHide").ElemHide; | 46 var ElemHide = require("elemHide").ElemHide; | 
| 51 var defaultMatcher = require("matcher").defaultMatcher; | 47 var defaultMatcher = require("matcher").defaultMatcher; | 
| 52 var Prefs = require("prefs").Prefs; | 48 var Prefs = require("prefs").Prefs; | 
| 53 var Synchronizer = require("synchronizer").Synchronizer; | 49 var Synchronizer = require("synchronizer").Synchronizer; | 
| 54 var Utils = require("utils").Utils; | 50 var Utils = require("utils").Utils; | 
| 55 var NotificationStorage = require("notification").Notification; |  | 
| 56 var initAntiAdblockNotification = require("antiadblockInit").initAntiAdblockNoti
     fication; |  | 
| 57 var parseFilters = require("filterValidation").parseFilters; | 51 var parseFilters = require("filterValidation").parseFilters; | 
| 58 var composeFilters = require("filterComposer").composeFilters; | 52 var composeFilters = require("filterComposer").composeFilters; | 
| 59 | 53 var updateIcon = require("icon").updateIcon; | 
| 60 // Chrome on Linux does not fully support chrome.notifications until version 35 | 54 var initNotifications = require("notificationHelper").initNotifications; | 
| 61 // https://code.google.com/p/chromium/issues/detail?id=291485 |  | 
| 62 var canUseChromeNotifications = require("info").platform == "chromium" |  | 
| 63   && "notifications" in chrome |  | 
| 64   && (navigator.platform.indexOf("Linux") == -1 || parseInt(require("info").appl
     icationVersion, 10) > 34); |  | 
| 65 | 55 | 
| 66 var seenDataCorruption = false; | 56 var seenDataCorruption = false; | 
| 67 var filterlistsReinitialized = false; | 57 var filterlistsReinitialized = false; | 
| 68 require("filterNotifier").FilterNotifier.addListener(function(action) | 58 | 
| 69 { | 59 function init() | 
| 70   if (action == "load") | 60 { | 
| 71   { | 61   var filtersLoaded = false; | 
| 72     var addonVersion = require("info").addonVersion; | 62   var prefsLoaded = false; | 
| 73     var prevVersion = ext.storage.currentVersion; | 63 | 
|  | 64   var checkLoaded = function() | 
|  | 65   { | 
|  | 66     if (!filtersLoaded || !prefsLoaded) | 
|  | 67       return; | 
|  | 68 | 
|  | 69     var info = require("info"); | 
|  | 70     var previousVersion = Prefs.currentVersion; | 
| 74 | 71 | 
| 75     // There are no filters stored so we need to reinitialize all filterlists | 72     // There are no filters stored so we need to reinitialize all filterlists | 
| 76     if (!FilterStorage.firstRun && FilterStorage.subscriptions.length === 0) | 73     if (!FilterStorage.firstRun && FilterStorage.subscriptions.length === 0) | 
| 77     { | 74     { | 
| 78       filterlistsReinitialized = true; | 75       filterlistsReinitialized = true; | 
| 79       prevVersion = null; | 76       previousVersion = null; | 
| 80     } | 77     } | 
| 81 | 78 | 
| 82     if (prevVersion != addonVersion || FilterStorage.firstRun) | 79     if (previousVersion != info.addonVersion || FilterStorage.firstRun) | 
| 83     { | 80     { | 
| 84       seenDataCorruption = prevVersion && FilterStorage.firstRun; | 81       seenDataCorruption = previousVersion && FilterStorage.firstRun; | 
| 85       ext.storage.currentVersion = addonVersion; | 82       Prefs.currentVersion = info.addonVersion; | 
| 86       addSubscription(prevVersion); | 83       addSubscription(previousVersion); | 
| 87     } | 84     } | 
| 88 |  | 
| 89     if (canUseChromeNotifications) |  | 
| 90       initChromeNotifications(); |  | 
| 91     initAntiAdblockNotification(); |  | 
| 92 | 85 | 
| 93     // The "Hide placeholders" option has been removed from the UI in 1.8.8.1285 | 86     // The "Hide placeholders" option has been removed from the UI in 1.8.8.1285 | 
| 94     // So we reset the option for users updating from older versions. | 87     // So we reset the option for users updating from older versions. | 
| 95     if (prevVersion && Services.vc.compare(prevVersion, "1.8.8.1285") < 0) | 88     if (previousVersion && Services.vc.compare(previousVersion, "1.8.8.1285") < 
     0) | 
| 96       Prefs.hidePlaceholders = true; | 89       Prefs.hidePlaceholders = true; | 
| 97   } | 90 | 
| 98 | 91     initNotifications(); | 
| 99   // update browser actions when whitelisting might have changed, | 92 | 
| 100   // due to loading filters or saving filter changes | 93     // Update browser actions and context menus when whitelisting might have | 
| 101   if (action == "load" || action == "save") | 94     // changed. That is now when initally loading the filters and later when | 
|  | 95     // importing backups or saving filter changes. | 
|  | 96     FilterNotifier.addListener(function(action) | 
|  | 97     { | 
|  | 98       if (action == "load" || action == "save") | 
|  | 99         refreshIconAndContextMenuForAllPages(); | 
|  | 100     }); | 
| 102     refreshIconAndContextMenuForAllPages(); | 101     refreshIconAndContextMenuForAllPages(); | 
| 103 }); | 102   }; | 
|  | 103 | 
|  | 104   var onFilterAction = function(action) | 
|  | 105   { | 
|  | 106     if (action == "load") | 
|  | 107     { | 
|  | 108       FilterNotifier.removeListener(onFilterAction); | 
|  | 109       filtersLoaded = true; | 
|  | 110       checkLoaded(); | 
|  | 111     } | 
|  | 112   }; | 
|  | 113 | 
|  | 114   var onPrefsLoaded = function() | 
|  | 115   { | 
|  | 116     Prefs.onLoaded.removeListener(onPrefsLoaded); | 
|  | 117     prefsLoaded = true; | 
|  | 118     checkLoaded(); | 
|  | 119   }; | 
|  | 120 | 
|  | 121   FilterNotifier.addListener(onFilterAction); | 
|  | 122   Prefs.onLoaded.addListener(onPrefsLoaded); | 
|  | 123 } | 
|  | 124 init(); | 
| 104 | 125 | 
| 105 // Special-case domains for which we cannot use style-based hiding rules. | 126 // Special-case domains for which we cannot use style-based hiding rules. | 
| 106 // See http://crbug.com/68705. | 127 // See http://crbug.com/68705. | 
| 107 var noStyleRulesHosts = ["mail.google.com", "mail.yahoo.com", "www.google.com"]; | 128 var noStyleRulesHosts = ["mail.google.com", "mail.yahoo.com", "www.google.com"]; | 
| 108 | 129 | 
| 109 var htmlPages = new ext.PageMap(); | 130 var htmlPages = new ext.PageMap(); | 
| 110 |  | 
| 111 function removeDeprecatedOptions() |  | 
| 112 { |  | 
| 113   var deprecatedOptions = ["specialCaseYouTube", "experimental", "disableInlineT
     extAds"]; |  | 
| 114   deprecatedOptions.forEach(function(option) |  | 
| 115   { |  | 
| 116     if (option in ext.storage) |  | 
| 117       delete ext.storage[option]; |  | 
| 118   }); |  | 
| 119 } |  | 
| 120 |  | 
| 121 // Remove deprecated options before we do anything else. |  | 
| 122 removeDeprecatedOptions(); |  | 
| 123 |  | 
| 124 var activeNotification = null; |  | 
| 125 | 131 | 
| 126 var contextMenuItem = { | 132 var contextMenuItem = { | 
| 127   title: ext.i18n.getMessage("block_element"), | 133   title: ext.i18n.getMessage("block_element"), | 
| 128   contexts: ["image", "video", "audio"], | 134   contexts: ["image", "video", "audio"], | 
| 129   onclick: function(page) | 135   onclick: function(page) | 
| 130   { | 136   { | 
| 131     page.sendMessage({type: "clickhide-new-filter"}); | 137     page.sendMessage({type: "clickhide-new-filter"}); | 
| 132   } | 138   } | 
| 133 }; | 139 }; | 
| 134 | 140 | 
| (...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 217       if (subscription instanceof DownloadableSubscription && !subscription.last
     Download) | 223       if (subscription instanceof DownloadableSubscription && !subscription.last
     Download) | 
| 218         Synchronizer.execute(subscription); | 224         Synchronizer.execute(subscription); | 
| 219     } | 225     } | 
| 220   } | 226   } | 
| 221 | 227 | 
| 222   if (!addSubscription && !addAcceptable) | 228   if (!addSubscription && !addAcceptable) | 
| 223     return; | 229     return; | 
| 224 | 230 | 
| 225   function notifyUser() | 231   function notifyUser() | 
| 226   { | 232   { | 
| 227     ext.pages.open(ext.getURL("firstRun.html")); | 233     if (!Prefs.suppress_first_run_page) | 
|  | 234       ext.pages.open(ext.getURL("firstRun.html")); | 
| 228   } | 235   } | 
| 229 | 236 | 
| 230   if (addSubscription) | 237   if (addSubscription) | 
| 231   { | 238   { | 
| 232     // Load subscriptions data | 239     // Load subscriptions data | 
| 233     var request = new XMLHttpRequest(); | 240     var request = new XMLHttpRequest(); | 
| 234     request.open("GET", "subscriptions.xml"); | 241     request.open("GET", "subscriptions.xml"); | 
| 235     request.addEventListener("load", function() | 242     request.addEventListener("load", function() | 
| 236     { | 243     { | 
| 237       var node = Utils.chooseFilterSubscription(request.responseXML.getElementsB
     yTagName("subscription")); | 244       var node = Utils.chooseFilterSubscription(request.responseXML.getElementsB
     yTagName("subscription")); | 
| 238       var subscription = (node ? Subscription.fromURL(node.getAttribute("url")) 
     : null); | 245       var subscription = (node ? Subscription.fromURL(node.getAttribute("url")) 
     : null); | 
| 239       if (subscription) | 246       if (subscription) | 
| 240       { | 247       { | 
| 241         FilterStorage.addSubscription(subscription); | 248         FilterStorage.addSubscription(subscription); | 
| 242         subscription.disabled = false; | 249         subscription.disabled = false; | 
| 243         subscription.title = node.getAttribute("title"); | 250         subscription.title = node.getAttribute("title"); | 
| 244         subscription.homepage = node.getAttribute("homepage"); | 251         subscription.homepage = node.getAttribute("homepage"); | 
| 245         if (subscription instanceof DownloadableSubscription && !subscription.la
     stDownload) | 252         if (subscription instanceof DownloadableSubscription && !subscription.la
     stDownload) | 
| 246           Synchronizer.execute(subscription); | 253           Synchronizer.execute(subscription); | 
| 247 | 254 | 
| 248           notifyUser(); | 255           notifyUser(); | 
| 249       } | 256       } | 
| 250     }, false); | 257     }, false); | 
| 251     request.send(null); | 258     request.send(null); | 
| 252   } | 259   } | 
| 253   else | 260   else | 
| 254     notifyUser(); | 261     notifyUser(); | 
| 255 } | 262 } | 
| 256 | 263 | 
| 257 Prefs.addListener(function(name) | 264 Prefs.onChanged.addListener(function(name) | 
| 258 { | 265 { | 
| 259   if (name == "shouldShowBlockElementMenu") | 266   if (name == "shouldShowBlockElementMenu") | 
| 260     refreshIconAndContextMenuForAllPages(); | 267     refreshIconAndContextMenuForAllPages(); | 
| 261 }); | 268 }); | 
| 262 |  | 
| 263 function prepareNotificationIconAndPopup() |  | 
| 264 { |  | 
| 265   var animateIcon = (activeNotification.type !== "question"); |  | 
| 266   activeNotification.onClicked = function() |  | 
| 267   { |  | 
| 268     if (animateIcon) |  | 
| 269       stopIconAnimation(); |  | 
| 270     notificationClosed(); |  | 
| 271   }; |  | 
| 272   if (animateIcon) |  | 
| 273     startIconAnimation(activeNotification.type); |  | 
| 274 } |  | 
| 275 |  | 
| 276 function openNotificationLinks() |  | 
| 277 { |  | 
| 278   if (activeNotification.links) |  | 
| 279   { |  | 
| 280     activeNotification.links.forEach(function(link) |  | 
| 281     { |  | 
| 282       ext.windows.getLastFocused(function(win) |  | 
| 283       { |  | 
| 284         win.openTab(Utils.getDocLink(link)); |  | 
| 285       }); |  | 
| 286     }); |  | 
| 287   } |  | 
| 288 } |  | 
| 289 |  | 
| 290 function notificationButtonClick(buttonIndex) |  | 
| 291 { |  | 
| 292   if (activeNotification.type === "question") |  | 
| 293   { |  | 
| 294     NotificationStorage.triggerQuestionListeners(activeNotification.id, buttonIn
     dex === 0); |  | 
| 295     NotificationStorage.markAsShown(activeNotification.id); |  | 
| 296     activeNotification.onClicked(); |  | 
| 297   } |  | 
| 298   else if (activeNotification.links && activeNotification.links[buttonIndex]) |  | 
| 299   { |  | 
| 300     ext.windows.getLastFocused(function(win) |  | 
| 301     { |  | 
| 302       win.openTab(Utils.getDocLink(activeNotification.links[buttonIndex])); |  | 
| 303     }); |  | 
| 304   } |  | 
| 305 } |  | 
| 306 |  | 
| 307 function notificationClosed() |  | 
| 308 { |  | 
| 309   activeNotification = null; |  | 
| 310 } |  | 
| 311 |  | 
| 312 function imgToBase64(url, callback) |  | 
| 313 { |  | 
| 314   var canvas = document.createElement("canvas"), |  | 
| 315   ctx = canvas.getContext("2d"), |  | 
| 316   img = new Image; |  | 
| 317   img.src = url; |  | 
| 318   img.onload = function() |  | 
| 319   { |  | 
| 320     canvas.height = img.height; |  | 
| 321     canvas.width = img.width; |  | 
| 322     ctx.drawImage(img, 0, 0); |  | 
| 323     callback(canvas.toDataURL("image/png")); |  | 
| 324     canvas = null; |  | 
| 325   }; |  | 
| 326 } |  | 
| 327 |  | 
| 328 function initChromeNotifications() |  | 
| 329 { |  | 
| 330   // Chrome hides notifications in notification center when clicked so we need t
     o clear them |  | 
| 331   function clearActiveNotification(notificationId) |  | 
| 332   { |  | 
| 333     if (activeNotification && activeNotification.type != "question" && !("links"
      in activeNotification)) |  | 
| 334       return; |  | 
| 335 |  | 
| 336     chrome.notifications.clear(notificationId, function(wasCleared) |  | 
| 337     { |  | 
| 338       if (wasCleared) |  | 
| 339         notificationClosed(); |  | 
| 340     }); |  | 
| 341   } |  | 
| 342 |  | 
| 343   chrome.notifications.onButtonClicked.addListener(function(notificationId, butt
     onIndex) |  | 
| 344   { |  | 
| 345     notificationButtonClick(buttonIndex); |  | 
| 346     clearActiveNotification(notificationId); |  | 
| 347   }); |  | 
| 348   chrome.notifications.onClicked.addListener(clearActiveNotification); |  | 
| 349   chrome.notifications.onClosed.addListener(notificationClosed); |  | 
| 350 } |  | 
| 351 |  | 
| 352 function showNotification(notification) |  | 
| 353 { |  | 
| 354   if (activeNotification && activeNotification.id === notification.id) |  | 
| 355     return; |  | 
| 356 |  | 
| 357   activeNotification = notification; |  | 
| 358   if (activeNotification.type === "critical" || activeNotification.type === "que
     stion") |  | 
| 359   { |  | 
| 360     var texts = NotificationStorage.getLocalizedTexts(notification); |  | 
| 361     var title = texts.title || ""; |  | 
| 362     var message = texts.message ? texts.message.replace(/<\/?(a|strong)>/g, "") 
     : ""; |  | 
| 363     var iconUrl = ext.getURL("icons/detailed/abp-128.png"); |  | 
| 364     var hasLinks = activeNotification.links && activeNotification.links.length >
      0; |  | 
| 365 |  | 
| 366     if (canUseChromeNotifications) |  | 
| 367     { |  | 
| 368       var opts = { |  | 
| 369         type: "basic", |  | 
| 370         title: title, |  | 
| 371         message: message, |  | 
| 372         buttons: [], |  | 
| 373         priority: 2 // We use the highest priority to prevent the notification f
     rom closing automatically |  | 
| 374       }; |  | 
| 375       if (activeNotification.type === "question") |  | 
| 376       { |  | 
| 377         opts.buttons.push({title: ext.i18n.getMessage("overlay_notification_butt
     on_yes")}); |  | 
| 378         opts.buttons.push({title: ext.i18n.getMessage("overlay_notification_butt
     on_no")}); |  | 
| 379       } |  | 
| 380       else |  | 
| 381       { |  | 
| 382         var regex = /<a>(.*?)<\/a>/g; |  | 
| 383         var plainMessage = texts.message || ""; |  | 
| 384         var match; |  | 
| 385         while (match = regex.exec(plainMessage)) |  | 
| 386           opts.buttons.push({title: match[1]}); |  | 
| 387       } |  | 
| 388 |  | 
| 389       imgToBase64(iconUrl, function(iconData) |  | 
| 390       { |  | 
| 391         opts["iconUrl"] = iconData; |  | 
| 392         chrome.notifications.create("", opts, function() {}); |  | 
| 393       }); |  | 
| 394     } |  | 
| 395     else if ("Notification" in window && activeNotification.type !== "question") |  | 
| 396     { |  | 
| 397       if (hasLinks) |  | 
| 398         message += " " + ext.i18n.getMessage("notification_without_buttons"); |  | 
| 399 |  | 
| 400       imgToBase64(iconUrl, function(iconData) |  | 
| 401       { |  | 
| 402         var notification = new Notification( |  | 
| 403           title, |  | 
| 404           { |  | 
| 405             lang: Utils.appLocale, |  | 
| 406             dir: ext.i18n.getMessage("@@bidi_dir"), |  | 
| 407             body: message, |  | 
| 408             icon: iconData |  | 
| 409           } |  | 
| 410         ); |  | 
| 411 |  | 
| 412         notification.addEventListener("click", openNotificationLinks); |  | 
| 413         notification.addEventListener("close", notificationClosed); |  | 
| 414       }); |  | 
| 415     } |  | 
| 416     else |  | 
| 417     { |  | 
| 418       var message = title + "\n" + message; |  | 
| 419       if (hasLinks) |  | 
| 420         message += "\n\n" + ext.i18n.getMessage("notification_with_buttons"); |  | 
| 421 |  | 
| 422       var approved = confirm(message); |  | 
| 423       if (activeNotification.type === "question") |  | 
| 424         notificationButtonClick(approved ? 0 : 1); |  | 
| 425       else if (approved) |  | 
| 426         openNotificationLinks(); |  | 
| 427     } |  | 
| 428   } |  | 
| 429   prepareNotificationIconAndPopup(); |  | 
| 430 } |  | 
| 431 | 269 | 
| 432 // This is a hack to speedup loading of the options page on Safari. | 270 // This is a hack to speedup loading of the options page on Safari. | 
| 433 // Once we replaced the background page proxy with message passing | 271 // Once we replaced the background page proxy with message passing | 
| 434 // this global function should removed. | 272 // this global function should removed. | 
| 435 function getUserFilters() | 273 function getUserFilters() | 
| 436 { | 274 { | 
| 437   var filters = []; | 275   var filters = []; | 
| 438   var exceptions = []; | 276   var exceptions = []; | 
| 439 | 277 | 
| 440   for (var i = 0; i < FilterStorage.subscriptions.length; i++) | 278   for (var i = 0; i < FilterStorage.subscriptions.length; i++) | 
| (...skipping 15 matching lines...) Expand all  Loading... | 
| 456   return {filters: filters, exceptions: exceptions}; | 294   return {filters: filters, exceptions: exceptions}; | 
| 457 } | 295 } | 
| 458 | 296 | 
| 459 ext.onMessage.addListener(function (msg, sender, sendResponse) | 297 ext.onMessage.addListener(function (msg, sender, sendResponse) | 
| 460 { | 298 { | 
| 461   switch (msg.type) | 299   switch (msg.type) | 
| 462   { | 300   { | 
| 463     case "get-selectors": | 301     case "get-selectors": | 
| 464       var selectors = []; | 302       var selectors = []; | 
| 465 | 303 | 
| 466       if (!isFrameWhitelisted(sender.page, sender.frame, "DOCUMENT") && | 304       if (!isFrameWhitelisted(sender.page, sender.frame, | 
| 467           !isFrameWhitelisted(sender.page, sender.frame, "ELEMHIDE")) | 305                               RegExpFilter.typeMap.DOCUMENT | RegExpFilter.typeM
     ap.ELEMHIDE)) | 
| 468       { | 306       { | 
| 469         var noStyleRules = false; | 307         var noStyleRules = false; | 
| 470         var specificOnly = isFrameWhitelisted(sender.page, sender.frame, "GENERI
     CHIDE"); | 308         var specificOnly = isFrameWhitelisted(sender.page, sender.frame, | 
|  | 309                                               RegExpFilter.typeMap.GENERICHIDE); | 
| 471         var host = extractHostFromFrame(sender.frame); | 310         var host = extractHostFromFrame(sender.frame); | 
| 472 | 311 | 
| 473         for (var i = 0; i < noStyleRulesHosts.length; i++) | 312         for (var i = 0; i < noStyleRulesHosts.length; i++) | 
| 474         { | 313         { | 
| 475           var noStyleHost = noStyleRulesHosts[i]; | 314           var noStyleHost = noStyleRulesHosts[i]; | 
| 476           if (host == noStyleHost || (host.length > noStyleHost.length && | 315           if (host == noStyleHost || (host.length > noStyleHost.length && | 
| 477                                       host.substr(host.length - noStyleHost.leng
     th - 1) == "." + noStyleHost)) | 316                                       host.substr(host.length - noStyleHost.leng
     th - 1) == "." + noStyleHost)) | 
| 478           { | 317           { | 
| 479             noStyleRules = true; | 318             noStyleRules = true; | 
| 480           } | 319           } | 
| 481         } | 320         } | 
| 482         selectors = ElemHide.getSelectorsForDomain(host, specificOnly); | 321         selectors = ElemHide.getSelectorsForDomain(host, specificOnly); | 
| 483         if (noStyleRules) | 322         if (noStyleRules) | 
| 484         { | 323         { | 
| 485           selectors = selectors.filter(function(s) | 324           selectors = selectors.filter(function(s) | 
| 486           { | 325           { | 
| 487             return !/\[style[\^\$]?=/.test(s); | 326             return !/\[style[\^\$]?=/.test(s); | 
| 488           }); | 327           }); | 
| 489         } | 328         } | 
| 490       } | 329       } | 
| 491 | 330 | 
| 492       sendResponse(selectors); | 331       sendResponse(selectors); | 
| 493       break; | 332       break; | 
| 494     case "should-collapse": | 333     case "should-collapse": | 
| 495       if (isFrameWhitelisted(sender.page, sender.frame, "DOCUMENT")) | 334       if (isFrameWhitelisted(sender.page, sender.frame, RegExpFilter.typeMap.DOC
     UMENT)) | 
| 496       { | 335       { | 
| 497         sendResponse(false); | 336         sendResponse(false); | 
| 498         break; | 337         break; | 
| 499       } | 338       } | 
| 500 | 339 | 
| 501       var url = new URL(msg.url); | 340       var typeMask = RegExpFilter.typeMap[msg.mediatype]; | 
| 502       var documentHost = extractHostFromFrame(sender.frame); | 341       var documentHost = extractHostFromFrame(sender.frame); | 
| 503       var filter = defaultMatcher.matchesAny( | 342       var blocked = false; | 
| 504         stringifyURL(url), msg.mediatype, | 343 | 
| 505         documentHost, isThirdParty(url, documentHost) | 344       for (var i = 0; i < msg.urls.length; i++) | 
| 506       ); | 345       { | 
| 507 | 346         var url = new URL(msg.urls[i], msg.baseURL); | 
| 508       if (filter instanceof BlockingFilter) | 347         var filter = defaultMatcher.matchesAny( | 
| 509       { | 348           stringifyURL(url), typeMask, | 
| 510         var collapse = filter.collapse; | 349           documentHost, isThirdParty(url, documentHost) | 
| 511         if (collapse == null) | 350         ); | 
| 512           collapse = Prefs.hidePlaceholders; | 351 | 
| 513         sendResponse(collapse); | 352         if (filter instanceof BlockingFilter) | 
| 514       } | 353         { | 
| 515       else | 354           if (filter.collapse != null) | 
| 516         sendResponse(false); | 355           { | 
|  | 356             sendResponse(filter.collapse); | 
|  | 357             return; | 
|  | 358           } | 
|  | 359 | 
|  | 360           blocked = true; | 
|  | 361         } | 
|  | 362       } | 
|  | 363 | 
|  | 364       sendResponse(blocked && Prefs.hidePlaceholders); | 
| 517       break; | 365       break; | 
| 518     case "get-domain-enabled-state": | 366     case "get-domain-enabled-state": | 
| 519       // Returns whether this domain is in the exclusion list. | 367       // Returns whether this domain is in the exclusion list. | 
| 520       // The browser action popup asks us this. | 368       // The browser action popup asks us this. | 
| 521       if(sender.page) | 369       if(sender.page) | 
| 522       { | 370       { | 
| 523         sendResponse({enabled: !isPageWhitelisted(sender.page)}); | 371         sendResponse({enabled: !isPageWhitelisted(sender.page)}); | 
| 524         return; | 372         return; | 
| 525       } | 373       } | 
| 526       break; | 374       break; | 
| 527     case "add-filters": | 375     case "add-filters": | 
| 528       var filters; | 376       var result = parseFilters(msg.text); | 
| 529       try | 377 | 
| 530       { | 378       if (result.errors.length > 0) | 
| 531         filters = parseFilters(msg.text); | 379       { | 
| 532       } | 380         sendResponse({status: "invalid", error: result.errors.join("\n")}); | 
| 533       catch (error) |  | 
| 534       { |  | 
| 535         sendResponse({status: "invalid", error: error}); |  | 
| 536         break; | 381         break; | 
| 537       } | 382       } | 
| 538 | 383 | 
| 539       for (var i = 0; i < filters.length; i++) | 384       for (var i = 0; i < result.filters.length; i++) | 
| 540         FilterStorage.addFilter(filters[i]); | 385         FilterStorage.addFilter(result.filters[i]); | 
| 541 | 386 | 
| 542       sendResponse({status: "ok"}); | 387       sendResponse({status: "ok"}); | 
| 543       break; | 388       break; | 
| 544     case "add-subscription": | 389     case "add-subscription": | 
| 545       ext.showOptions(function(page) | 390       ext.showOptions(function(page) | 
| 546       { | 391       { | 
| 547         page.sendMessage(msg); | 392         page.sendMessage(msg); | 
| 548       }); | 393       }); | 
| 549       break; | 394       break; | 
| 550     case "add-sitekey": | 395     case "add-sitekey": | 
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 582       break; | 427       break; | 
| 583   } | 428   } | 
| 584 }); | 429 }); | 
| 585 | 430 | 
| 586 // update icon when page changes location | 431 // update icon when page changes location | 
| 587 ext.pages.onLoading.addListener(function(page) | 432 ext.pages.onLoading.addListener(function(page) | 
| 588 { | 433 { | 
| 589   page.sendMessage({type: "clickhide-deactivate"}); | 434   page.sendMessage({type: "clickhide-deactivate"}); | 
| 590   refreshIconAndContextMenu(page); | 435   refreshIconAndContextMenu(page); | 
| 591 }); | 436 }); | 
| 592 |  | 
| 593 setTimeout(function() |  | 
| 594 { |  | 
| 595   var notificationToShow = NotificationStorage.getNextToShow(); |  | 
| 596   if (notificationToShow) |  | 
| 597     showNotification(notificationToShow); |  | 
| 598 }, 3 * 60 * 1000); |  | 
| LEFT | RIGHT | 
|---|