| OLD | NEW | 
|---|
|  | (Empty) | 
| 1 /* |  | 
| 2  * This file is part of Adblock Plus <https://adblockplus.org/>, |  | 
| 3  * Copyright (C) 2006-2016 Eyeo GmbH |  | 
| 4  * |  | 
| 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 |  | 
| 7  * published by the Free Software Foundation. |  | 
| 8  * |  | 
| 9  * Adblock Plus is distributed in the hope that it will be useful, |  | 
| 10  * but WITHOUT ANY WARRANTY; without even the implied warranty of |  | 
| 11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the |  | 
| 12  * GNU General Public License for more details. |  | 
| 13  * |  | 
| 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/>. |  | 
| 16  */ |  | 
| 17 |  | 
| 18 /** @module contentBlocking */ |  | 
| 19 |  | 
| 20 "use strict"; |  | 
| 21 |  | 
| 22 let {Prefs} = require("prefs"); |  | 
| 23 let {ContentBlockerList} = require("abp2blocklist"); |  | 
| 24 let {FilterStorage} = require("filterStorage"); |  | 
| 25 let {FilterNotifier} = require("filterNotifier"); |  | 
| 26 let {port} = require("messaging"); |  | 
| 27 |  | 
| 28 let contentBlockingSupported = "setContentBlocker" in safari.extension; |  | 
| 29 let legacyAPISupported = new Promise(resolve => |  | 
| 30 { |  | 
| 31   function onLegacyAPISupported(msg, sender) |  | 
| 32   { |  | 
| 33     port.off("safari.legacyAPISupported", onLegacyAPISupported); |  | 
| 34     resolve(msg.legacyAPISupported); |  | 
| 35   } |  | 
| 36   port.on("safari.legacyAPISupported", onLegacyAPISupported); |  | 
| 37 }); |  | 
| 38 let contentBlockingActive = false; |  | 
| 39 let afterContentBlockingFinished = null; |  | 
| 40 let contentBlockListDirty = true; |  | 
| 41 let lastSetContentBlockerError; |  | 
| 42 |  | 
| 43 function clearBlockCounters() |  | 
| 44 { |  | 
| 45   ext.pages.query({}, pages => |  | 
| 46   { |  | 
| 47     for (let page of pages) |  | 
| 48       page.browserAction.setBadge(); |  | 
| 49   }); |  | 
| 50 } |  | 
| 51 |  | 
| 52 function setContentBlocker(callback) |  | 
| 53 { |  | 
| 54   // When given the same rules as last time setContentBlocker will always give |  | 
| 55   // null (success) to the callback, even when there was actually an error. We |  | 
| 56   // cache the last result therefore so that we can provide a consistent result |  | 
| 57   // and also to avoid wastefully regenerating an identical blocklist. |  | 
| 58   if (!contentBlockListDirty) |  | 
| 59   { |  | 
| 60     callback(lastSetContentBlockerError); |  | 
| 61     return; |  | 
| 62   } |  | 
| 63 |  | 
| 64   let contentBlockerList = new ContentBlockerList(); |  | 
| 65   for (let subscription of FilterStorage.subscriptions) |  | 
| 66     if (!subscription.disabled) |  | 
| 67       for (let filter of subscription.filters) |  | 
| 68         contentBlockerList.addFilter(filter); |  | 
| 69 |  | 
| 70   contentBlockListDirty = false; |  | 
| 71   safari.extension.setContentBlocker( |  | 
| 72     // There is a strange bug in setContentBlocker for Safari 9 where if both |  | 
| 73     // the callback parameter is provided and the rules aren't converted to a |  | 
| 74     // JSON string it fails. Worse still it actually performs the callback twice |  | 
| 75     // too, firstly with an empty string and then with an Error: |  | 
| 76     //   "Extension compilation failed: Failed to parse the JSON String." |  | 
| 77     // To mitigate this we convert the rules to JSON here and also ignore |  | 
| 78     // callback values of "". (Usually the callback is performed with either |  | 
| 79     // null for success or an Error on failure.) |  | 
| 80     // Bug #26322821 filed on bugreport.apple.com |  | 
| 81     JSON.stringify(contentBlockerList.generateRules()), |  | 
| 82     function(error) |  | 
| 83     { |  | 
| 84       if (error == "") |  | 
| 85         return; |  | 
| 86 |  | 
| 87       lastSetContentBlockerError = error; |  | 
| 88       callback(error); |  | 
| 89     } |  | 
| 90   ); |  | 
| 91 } |  | 
| 92 |  | 
| 93 function updateContentBlocker(isStartup, legacyAPISupported) |  | 
| 94 { |  | 
| 95   afterContentBlockingFinished = new Promise(resolve => |  | 
| 96   { |  | 
| 97     setContentBlocker(error => |  | 
| 98     { |  | 
| 99       if (error instanceof Error) |  | 
| 100       { |  | 
| 101         let suppressErrorMessage = false; |  | 
| 102 |  | 
| 103         // If the content blocking API fails the first time it's used the |  | 
| 104         // legacy blocking API (if available) won't have been disabled. |  | 
| 105         if (!contentBlockingActive && legacyAPISupported) |  | 
| 106         { |  | 
| 107           Prefs.safariContentBlocker = false; |  | 
| 108           // If content blocking failed on startup and we're switching back to |  | 
| 109           // the legacy API anyway we don't need to show an error message. |  | 
| 110           if (isStartup) |  | 
| 111             suppressErrorMessage = true; |  | 
| 112         } |  | 
| 113 |  | 
| 114         if (!suppressErrorMessage) |  | 
| 115           alert(error.message); |  | 
| 116       } |  | 
| 117       else if (!contentBlockingActive) |  | 
| 118       { |  | 
| 119         contentBlockingActive = true; |  | 
| 120         clearBlockCounters(); |  | 
| 121       } |  | 
| 122 |  | 
| 123       resolve(contentBlockingActive); |  | 
| 124       afterContentBlockingFinished = null; |  | 
| 125     }); |  | 
| 126   }); |  | 
| 127 } |  | 
| 128 |  | 
| 129 if (contentBlockingSupported) |  | 
| 130 { |  | 
| 131   Promise.all([Prefs.untilLoaded, |  | 
| 132                FilterNotifier.once("load"), |  | 
| 133                legacyAPISupported]).then(resolvedValues => |  | 
| 134   { |  | 
| 135     let legacyAPISupported = resolvedValues[2]; |  | 
| 136     if (!legacyAPISupported) |  | 
| 137       Prefs.safariContentBlocker = true; |  | 
| 138 |  | 
| 139     if (Prefs.safariContentBlocker) |  | 
| 140       updateContentBlocker(true, legacyAPISupported); |  | 
| 141 |  | 
| 142     Prefs.on("safariContentBlocker", () => |  | 
| 143     { |  | 
| 144       if (!contentBlockingActive && Prefs.safariContentBlocker) |  | 
| 145         updateContentBlocker(false, legacyAPISupported); |  | 
| 146     }); |  | 
| 147 |  | 
| 148     FilterNotifier.on("filter.behaviorChanged", () => |  | 
| 149     { |  | 
| 150       contentBlockListDirty = true; |  | 
| 151       if (contentBlockingActive) |  | 
| 152         updateContentBlocker(false, legacyAPISupported); |  | 
| 153     }); |  | 
| 154   }); |  | 
| 155 } |  | 
| 156 |  | 
| 157 port.on("safari.contentBlockingActive", (msg, sender) => |  | 
| 158 { |  | 
| 159   if (!contentBlockingActive && afterContentBlockingFinished) |  | 
| 160     return afterContentBlockingFinished; |  | 
| 161   return contentBlockingActive; |  | 
| 162 }); |  | 
| OLD | NEW | 
|---|