OLD | NEW |
1 /* | 1 /* |
2 * This file is part of Adblock Plus <http://adblockplus.org/>, | 2 * This file is part of Adblock Plus <http://adblockplus.org/>, |
3 * Copyright (C) 2006-2013 Eyeo GmbH | 3 * Copyright (C) 2006-2014 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.RegExpFilter = RegExpFilter; | 21 this.RegExpFilter = RegExpFilter; |
22 this.BlockingFilter = BlockingFilter; | 22 this.BlockingFilter = BlockingFilter; |
23 this.WhitelistFilter = WhitelistFilter; | 23 this.WhitelistFilter = WhitelistFilter; |
24 } | 24 } |
25 with(require("subscriptionClasses")) | 25 with(require("subscriptionClasses")) |
26 { | 26 { |
27 this.Subscription = Subscription; | 27 this.Subscription = Subscription; |
28 this.DownloadableSubscription = DownloadableSubscription; | 28 this.DownloadableSubscription = DownloadableSubscription; |
| 29 this.SpecialSubscription = SpecialSubscription; |
| 30 } |
| 31 with(require("whitelisting")) |
| 32 { |
| 33 this.isWhitelisted = isWhitelisted; |
| 34 this.isFrameWhitelisted = isFrameWhitelisted; |
| 35 this.processKeyException = processKeyException; |
29 } | 36 } |
30 var FilterStorage = require("filterStorage").FilterStorage; | 37 var FilterStorage = require("filterStorage").FilterStorage; |
31 var ElemHide = require("elemHide").ElemHide; | 38 var ElemHide = require("elemHide").ElemHide; |
32 var defaultMatcher = require("matcher").defaultMatcher; | 39 var defaultMatcher = require("matcher").defaultMatcher; |
33 var Prefs = require("prefs").Prefs; | 40 var Prefs = require("prefs").Prefs; |
34 var Synchronizer = require("synchronizer").Synchronizer; | 41 var Synchronizer = require("synchronizer").Synchronizer; |
35 var Utils = require("utils").Utils; | 42 var Utils = require("utils").Utils; |
36 var Notification = require("notification").Notification; | 43 var Notification = require("notification").Notification; |
| 44 var initAntiAdblockNotification = require("antiadblockInit").initAntiAdblockNoti
fication; |
37 | 45 |
38 // Some types cannot be distinguished | 46 // Some types cannot be distinguished |
39 RegExpFilter.typeMap.OBJECT_SUBREQUEST = RegExpFilter.typeMap.OBJECT; | 47 RegExpFilter.typeMap.OBJECT_SUBREQUEST = RegExpFilter.typeMap.OBJECT; |
40 RegExpFilter.typeMap.MEDIA = RegExpFilter.typeMap.FONT = RegExpFilter.typeMap.OT
HER; | 48 RegExpFilter.typeMap.MEDIA = RegExpFilter.typeMap.FONT = RegExpFilter.typeMap.OT
HER; |
41 | 49 |
42 var isFirstRun = false; | 50 // Chrome on Linux does not fully support chrome.notifications until version 35 |
| 51 // https://code.google.com/p/chromium/issues/detail?id=291485 |
| 52 var canUseChromeNotifications = require("info").platform == "chromium" |
| 53 && "notifications" in chrome |
| 54 && (navigator.platform.indexOf("Linux") == -1 || parseInt(require("info").appl
icationVersion) > 34); |
| 55 |
43 var seenDataCorruption = false; | 56 var seenDataCorruption = false; |
| 57 var filterlistsReinitialized = false; |
44 require("filterNotifier").FilterNotifier.addListener(function(action) | 58 require("filterNotifier").FilterNotifier.addListener(function(action) |
45 { | 59 { |
46 if (action == "load") | 60 if (action == "load") |
47 { | 61 { |
48 var importingOldData = importOldData(); | 62 var importingOldData = importOldData(); |
49 | 63 |
50 var addonVersion = require("info").addonVersion; | 64 var addonVersion = require("info").addonVersion; |
51 var prevVersion = localStorage.currentVersion; | 65 var prevVersion = ext.storage.currentVersion; |
52 if (prevVersion != addonVersion) | 66 |
| 67 // There are no filters stored so we need to reinitialize all filterlists |
| 68 if (!FilterStorage.firstRun && FilterStorage.subscriptions.length === 0) |
53 { | 69 { |
54 isFirstRun = !prevVersion; | 70 filterlistsReinitialized = true; |
55 localStorage.currentVersion = addonVersion; | 71 prevVersion = null; |
| 72 } |
| 73 |
| 74 if (prevVersion != addonVersion || FilterStorage.firstRun) |
| 75 { |
| 76 seenDataCorruption = prevVersion && FilterStorage.firstRun; |
| 77 ext.storage.currentVersion = addonVersion; |
56 if (!importingOldData) | 78 if (!importingOldData) |
57 addSubscription(prevVersion); | 79 addSubscription(prevVersion); |
58 } | 80 } |
| 81 |
| 82 if (canUseChromeNotifications) |
| 83 initChromeNotifications(); |
| 84 initAntiAdblockNotification(); |
59 } | 85 } |
| 86 |
| 87 // update browser actions when whitelisting might have changed, |
| 88 // due to loading filters or saving filter changes |
| 89 if (action == "load" || action == "save") |
| 90 refreshIconAndContextMenuForAllPages(); |
60 }); | 91 }); |
61 | 92 |
62 // Special-case domains for which we cannot use style-based hiding rules. | 93 // Special-case domains for which we cannot use style-based hiding rules. |
63 // See http://crbug.com/68705. | 94 // See http://crbug.com/68705. |
64 var noStyleRulesHosts = ["mail.google.com", "mail.yahoo.com", "www.google.com"]; | 95 var noStyleRulesHosts = ["mail.google.com", "mail.yahoo.com", "www.google.com"]; |
65 | 96 |
66 function removeDeprecatedOptions() | 97 function removeDeprecatedOptions() |
67 { | 98 { |
68 var deprecatedOptions = ["specialCaseYouTube", "experimental", "disableInlineT
extAds"]; | 99 var deprecatedOptions = ["specialCaseYouTube", "experimental", "disableInlineT
extAds"]; |
69 deprecatedOptions.forEach(function(option) | 100 deprecatedOptions.forEach(function(option) |
70 { | 101 { |
71 if (option in localStorage) | 102 if (option in ext.storage) |
72 delete localStorage[option]; | 103 delete ext.storage[option]; |
73 }); | 104 }); |
74 } | 105 } |
75 | 106 |
76 // Sets options to defaults, upgrading old options from previous versions as nec
essary | 107 // Remove deprecated options before we do anything else. |
77 function setDefaultOptions() | 108 removeDeprecatedOptions(); |
78 { | |
79 function defaultOptionValue(opt, val) | |
80 { | |
81 if(!(opt in localStorage)) | |
82 localStorage[opt] = val; | |
83 } | |
84 | |
85 defaultOptionValue("shouldShowBlockElementMenu", "true"); | |
86 | |
87 removeDeprecatedOptions(); | |
88 } | |
89 | |
90 // Upgrade options before we do anything else. | |
91 setDefaultOptions(); | |
92 | |
93 /** | |
94 * Checks whether a page is whitelisted. | |
95 * @param {String} url | |
96 * @param {String} [parentUrl] URL of the parent frame | |
97 * @param {String} [type] content type to be checked, default is "DOCUMENT" | |
98 * @return {Filter} filter that matched the URL or null if not whitelisted | |
99 */ | |
100 function isWhitelisted(url, parentUrl, type) | |
101 { | |
102 // Ignore fragment identifier | |
103 var index = url.indexOf("#"); | |
104 if (index >= 0) | |
105 url = url.substring(0, index); | |
106 | |
107 var result = defaultMatcher.matchesAny(url, type || "DOCUMENT", extractHostFro
mURL(parentUrl || url), false); | |
108 return (result instanceof WhitelistFilter ? result : null); | |
109 } | |
110 | 109 |
111 var activeNotification = null; | 110 var activeNotification = null; |
112 | 111 |
| 112 var contextMenuItem = { |
| 113 title: ext.i18n.getMessage("block_element"), |
| 114 contexts: ["image", "video", "audio"], |
| 115 onclick: function(srcUrl, page) |
| 116 { |
| 117 if (srcUrl) |
| 118 page.sendMessage({type: "clickhide-new-filter", filter: srcUrl}); |
| 119 } |
| 120 }; |
| 121 |
113 // Adds or removes browser action icon according to options. | 122 // Adds or removes browser action icon according to options. |
114 function refreshIconAndContextMenu(tab) | 123 function refreshIconAndContextMenu(page) |
115 { | 124 { |
116 if(!/^https?:/.test(tab.url)) | 125 var whitelisted = isWhitelisted(page.url); |
117 return; | |
118 | 126 |
119 var iconFilename; | 127 var iconFilename; |
120 if (require("info").platform == "safari") | 128 if (whitelisted && require("info").platform != "safari") |
121 // There is no grayscale version of the icon for whitelisted tabs | 129 // There is no grayscale version of the icon for whitelisted pages |
122 // when using Safari, because icons are grayscale already and icons | 130 // when using Safari, because icons are grayscale already and icons |
123 // aren't per tab in Safari. | 131 // aren't per page in Safari. |
124 iconFilename = "icons/abp-16.png" | 132 iconFilename = "icons/abp-$size-whitelisted.png"; |
125 else | 133 else |
| 134 iconFilename = "icons/abp-$size.png"; |
| 135 |
| 136 page.browserAction.setIcon(iconFilename); |
| 137 iconAnimation.registerPage(page, iconFilename); |
| 138 |
| 139 // show or hide the context menu entry dependent on whether |
| 140 // adblocking is active on that page |
| 141 page.contextMenus.removeAll(); |
| 142 |
| 143 if (Prefs.shouldShowBlockElementMenu && !whitelisted && /^https?:/.test(page.u
rl)) |
| 144 page.contextMenus.create(contextMenuItem); |
| 145 } |
| 146 |
| 147 function refreshIconAndContextMenuForAllPages() |
| 148 { |
| 149 ext.pages.query({}, function(pages) |
126 { | 150 { |
127 var excluded = isWhitelisted(tab.url); | 151 pages.forEach(refreshIconAndContextMenu); |
128 iconFilename = excluded ? "icons/abp-19-whitelisted.png" : "icons/abp-19.png
"; | 152 }); |
129 } | |
130 | |
131 tab.browserAction.setIcon(iconFilename); | |
132 tab.browserAction.setTitle(ext.i18n.getMessage("name")); | |
133 | |
134 iconAnimation.registerTab(tab, iconFilename); | |
135 | |
136 // Set context menu status according to whether current tab has whitelisted do
main | |
137 if (excluded) | |
138 chrome.contextMenus.removeAll(); | |
139 else | |
140 showContextMenu(); | |
141 } | 153 } |
142 | 154 |
143 /** | 155 /** |
144 * Old versions for Opera stored patterns.ini in the localStorage object, this | 156 * Old versions for Opera stored patterns.ini in the localStorage object, this |
145 * will import it into FilterStorage properly. | 157 * will import it into FilterStorage properly. |
146 * @return {Boolean} true if data import is in progress | 158 * @return {Boolean} true if data import is in progress |
147 */ | 159 */ |
148 function importOldData() | 160 function importOldData() |
149 { | 161 { |
150 if ("patterns.ini" in localStorage) | 162 if ("patterns.ini" in localStorage) |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
210 { | 222 { |
211 subscription.title = "Allow non-intrusive advertising"; | 223 subscription.title = "Allow non-intrusive advertising"; |
212 FilterStorage.addSubscription(subscription); | 224 FilterStorage.addSubscription(subscription); |
213 if (subscription instanceof DownloadableSubscription && !subscription.last
Download) | 225 if (subscription instanceof DownloadableSubscription && !subscription.last
Download) |
214 Synchronizer.execute(subscription); | 226 Synchronizer.execute(subscription); |
215 } | 227 } |
216 else | 228 else |
217 addAcceptable = false; | 229 addAcceptable = false; |
218 } | 230 } |
219 | 231 |
| 232 // Add "anti-adblock messages" subscription for new users and users updating f
rom old ABP versions |
| 233 if (!prevVersion || Services.vc.compare(prevVersion, "1.8") < 0) |
| 234 { |
| 235 var subscription = Subscription.fromURL(Prefs.subscriptions_antiadblockurl); |
| 236 if (subscription && !(subscription.url in FilterStorage.knownSubscriptions)) |
| 237 { |
| 238 subscription.disabled = true; |
| 239 FilterStorage.addSubscription(subscription); |
| 240 if (subscription instanceof DownloadableSubscription && !subscription.last
Download) |
| 241 Synchronizer.execute(subscription); |
| 242 } |
| 243 } |
| 244 |
220 if (!addSubscription && !addAcceptable) | 245 if (!addSubscription && !addAcceptable) |
221 return; | 246 return; |
222 | 247 |
223 function notifyUser() | 248 function notifyUser() |
224 { | 249 { |
225 ext.windows.getLastFocused(function(win) | 250 ext.pages.open(ext.getURL("firstRun.html")); |
226 { | |
227 win.openTab(ext.getURL("firstRun.html")); | |
228 }); | |
229 } | 251 } |
230 | 252 |
231 if (addSubscription) | 253 if (addSubscription) |
232 { | 254 { |
233 // Load subscriptions data | 255 // Load subscriptions data |
234 var request = new XMLHttpRequest(); | 256 var request = new XMLHttpRequest(); |
235 request.open("GET", "subscriptions.xml"); | 257 request.open("GET", "subscriptions.xml"); |
236 request.addEventListener("load", function() | 258 request.addEventListener("load", function() |
237 { | 259 { |
238 var node = Utils.chooseFilterSubscription(request.responseXML.getElementsB
yTagName("subscription")); | 260 var node = Utils.chooseFilterSubscription(request.responseXML.getElementsB
yTagName("subscription")); |
239 var subscription = (node ? Subscription.fromURL(node.getAttribute("url"))
: null); | 261 var subscription = (node ? Subscription.fromURL(node.getAttribute("url"))
: null); |
240 if (subscription) | 262 if (subscription) |
241 { | 263 { |
242 FilterStorage.addSubscription(subscription); | 264 FilterStorage.addSubscription(subscription); |
243 subscription.disabled = false; | 265 subscription.disabled = false; |
244 subscription.title = node.getAttribute("title"); | 266 subscription.title = node.getAttribute("title"); |
245 subscription.homepage = node.getAttribute("homepage"); | 267 subscription.homepage = node.getAttribute("homepage"); |
246 if (subscription instanceof DownloadableSubscription && !subscription.la
stDownload) | 268 if (subscription instanceof DownloadableSubscription && !subscription.la
stDownload) |
247 Synchronizer.execute(subscription); | 269 Synchronizer.execute(subscription); |
248 | 270 |
249 notifyUser(); | 271 notifyUser(); |
250 } | 272 } |
251 }, false); | 273 }, false); |
252 request.send(null); | 274 request.send(null); |
253 } | 275 } |
254 else | 276 else |
255 notifyUser(); | 277 notifyUser(); |
256 } | 278 } |
257 | 279 |
258 // Set up context menu for user selection of elements to block | 280 Prefs.addListener(function(name) |
259 function showContextMenu() | 281 { |
260 { | 282 if (name == "shouldShowBlockElementMenu") |
261 ext.contextMenus.removeAll(function() | 283 refreshIconAndContextMenuForAllPages(); |
262 { | 284 }); |
263 if(typeof localStorage["shouldShowBlockElementMenu"] == "string" && localSto
rage["shouldShowBlockElementMenu"] == "true") | |
264 { | |
265 ext.contextMenus.create(ext.i18n.getMessage("block_element"), ["image", "v
ideo", "audio"], function(srcUrl, tab) | |
266 { | |
267 if(srcUrl) | |
268 tab.sendMessage({type: "clickhide-new-filter", filter: srcUrl}); | |
269 }); | |
270 } | |
271 }); | |
272 } | |
273 | 285 |
274 /** | 286 /** |
275 * Opens options tab or focuses an existing one, within the last focused window
. | 287 * Opens options page or focuses an existing one, within the last focused windo
w. |
276 * @param {Function} callback function to be called with the | 288 * @param {Function} callback function to be called with the |
277 Tab object of the options tab | 289 Page object of the options page |
278 */ | 290 */ |
279 function openOptions(callback) | 291 function openOptions(callback) |
280 { | 292 { |
281 ext.windows.getLastFocused(function(win) | 293 ext.pages.query({lastFocusedWindow: true}, function(pages) |
282 { | 294 { |
283 win.getAllTabs(function(tabs) | 295 var optionsUrl = ext.getURL("options.html"); |
284 { | 296 |
285 var optionsUrl = ext.getURL("options.html"); | 297 for (var i = 0; i < pages.length; i++) |
286 | 298 { |
287 for (var i = 0; i < tabs.length; i++) | 299 var page = pages[i]; |
288 { | 300 if (page.url == optionsUrl) |
289 if (tabs[i].url == optionsUrl) | 301 { |
290 { | 302 page.activate(); |
291 tabs[i].activate(); | 303 if (callback) |
292 if (callback) | 304 callback(page); |
293 callback(tabs[i]); | 305 return; |
294 return; | |
295 } | |
296 } | 306 } |
297 | 307 } |
298 win.openTab(optionsUrl, callback && function(tab) | 308 |
299 { | 309 ext.pages.open(optionsUrl, callback); |
300 tab.onCompleted.addListener(callback); | 310 }); |
| 311 } |
| 312 |
| 313 function prepareNotificationIconAndPopup() |
| 314 { |
| 315 var animateIcon = (activeNotification.type !== "question"); |
| 316 activeNotification.onClicked = function() |
| 317 { |
| 318 if (animateIcon) |
| 319 iconAnimation.stop(); |
| 320 notificationClosed(); |
| 321 }; |
| 322 if (animateIcon) |
| 323 iconAnimation.update(activeNotification.type); |
| 324 } |
| 325 |
| 326 function openNotificationLinks() |
| 327 { |
| 328 if (activeNotification.links) |
| 329 { |
| 330 activeNotification.links.forEach(function(link) |
| 331 { |
| 332 ext.windows.getLastFocused(function(win) |
| 333 { |
| 334 win.openTab(Utils.getDocLink(link)); |
301 }); | 335 }); |
302 }); | 336 }); |
| 337 } |
| 338 } |
| 339 |
| 340 function notificationButtonClick(buttonIndex) |
| 341 { |
| 342 if (activeNotification.type === "question") |
| 343 { |
| 344 Notification.triggerQuestionListeners(activeNotification.id, buttonIndex ===
0); |
| 345 Notification.markAsShown(activeNotification.id); |
| 346 activeNotification.onClicked(); |
| 347 } |
| 348 else if (activeNotification.links && activeNotification.links[buttonIndex]) |
| 349 { |
| 350 ext.windows.getLastFocused(function(win) |
| 351 { |
| 352 win.openTab(Utils.getDocLink(activeNotification.links[buttonIndex])); |
| 353 }); |
| 354 } |
| 355 } |
| 356 |
| 357 function notificationClosed() |
| 358 { |
| 359 activeNotification = null; |
| 360 } |
| 361 |
| 362 function imgToBase64(url, callback) |
| 363 { |
| 364 var canvas = document.createElement("canvas"), |
| 365 ctx = canvas.getContext("2d"), |
| 366 img = new Image; |
| 367 img.src = url; |
| 368 img.onload = function() |
| 369 { |
| 370 canvas.height = img.height; |
| 371 canvas.width = img.width; |
| 372 ctx.drawImage(img, 0, 0); |
| 373 callback(canvas.toDataURL("image/png")); |
| 374 canvas = null; |
| 375 }; |
| 376 } |
| 377 |
| 378 function initChromeNotifications() |
| 379 { |
| 380 // Chrome hides notifications in notification center when clicked so we need t
o clear them |
| 381 function clearActiveNotification(notificationId) |
| 382 { |
| 383 if (activeNotification && activeNotification.type != "question" && !("links"
in activeNotification)) |
| 384 return; |
| 385 |
| 386 chrome.notifications.clear(notificationId, function(wasCleared) |
| 387 { |
| 388 if (wasCleared) |
| 389 notificationClosed(); |
| 390 }); |
| 391 } |
| 392 |
| 393 chrome.notifications.onButtonClicked.addListener(function(notificationId, butt
onIndex) |
| 394 { |
| 395 notificationButtonClick(buttonIndex); |
| 396 clearActiveNotification(notificationId); |
303 }); | 397 }); |
304 } | 398 chrome.notifications.onClicked.addListener(clearActiveNotification); |
305 | 399 chrome.notifications.onClosed.addListener(notificationClosed); |
306 function prepareNotificationIconAndPopup() | |
307 { | |
308 activeNotification.onClicked = function() | |
309 { | |
310 iconAnimation.stop(); | |
311 activeNotification = null; | |
312 }; | |
313 | |
314 iconAnimation.update(activeNotification.severity); | |
315 } | 400 } |
316 | 401 |
317 function showNotification(notification) | 402 function showNotification(notification) |
318 { | 403 { |
| 404 if (activeNotification && activeNotification.id === notification.id) |
| 405 return; |
| 406 |
319 activeNotification = notification; | 407 activeNotification = notification; |
320 | 408 if (activeNotification.type === "critical" || activeNotification.type === "que
stion") |
321 if (activeNotification.severity === "critical" | 409 { |
322 && typeof webkitNotifications !== "undefined") | 410 var hasWebkitNotifications = typeof webkitNotifications !== "undefined"; |
323 { | 411 if (hasWebkitNotifications && "createHTMLNotification" in webkitNotification
s) |
324 var notification = webkitNotifications.createHTMLNotification("notification.
html"); | 412 { |
325 notification.show(); | 413 var notification = webkitNotifications.createHTMLNotification("notificatio
n.html"); |
326 notification.addEventListener("close", prepareNotificationIconAndPopup); | 414 notification.show(); |
327 } | 415 prepareNotificationIconAndPopup(); |
328 else | 416 return; |
329 prepareNotificationIconAndPopup(); | 417 } |
330 } | 418 |
331 | 419 var texts = Notification.getLocalizedTexts(notification); |
332 /** | 420 var title = texts.title || ""; |
333 * This function is a hack - we only know the tabId and document URL for a | 421 var message = texts.message ? texts.message.replace(/<\/?(a|strong)>/g, "")
: ""; |
334 * message but we need to know the frame ID. Try to find it in webRequest"s | 422 var iconUrl = ext.getURL("icons/abp-128.png"); |
335 * frame data. | 423 var hasLinks = activeNotification.links && activeNotification.links.length >
0; |
336 */ | 424 |
337 function getFrameId(tab, url) | 425 if (canUseChromeNotifications) |
338 { | 426 { |
339 for (var frameId in frames.get(tab)) | 427 var opts = { |
340 if (getFrameUrl(tab, frameId) == url) | 428 type: "basic", |
341 return frameId; | 429 title: title, |
342 return -1; | 430 message: message, |
| 431 buttons: [], |
| 432 priority: 2 // We use the highest priority to prevent the notification f
rom closing automatically |
| 433 }; |
| 434 if (activeNotification.type === "question") |
| 435 { |
| 436 opts.buttons.push({title: ext.i18n.getMessage("overlay_notification_butt
on_yes")}); |
| 437 opts.buttons.push({title: ext.i18n.getMessage("overlay_notification_butt
on_no")}); |
| 438 } |
| 439 else |
| 440 { |
| 441 var regex = /<a>(.*?)<\/a>/g; |
| 442 var plainMessage = texts.message || ""; |
| 443 var match; |
| 444 while (match = regex.exec(plainMessage)) |
| 445 opts.buttons.push({title: match[1]}); |
| 446 } |
| 447 |
| 448 imgToBase64(iconUrl, function(iconData) |
| 449 { |
| 450 opts["iconUrl"] = iconData; |
| 451 chrome.notifications.create("", opts, function() {}); |
| 452 }); |
| 453 } |
| 454 else if (hasWebkitNotifications && "createNotification" in webkitNotificatio
ns && activeNotification.type !== "question") |
| 455 { |
| 456 if (hasLinks) |
| 457 message += " " + ext.i18n.getMessage("notification_without_buttons"); |
| 458 |
| 459 imgToBase64(iconUrl, function(iconData) |
| 460 { |
| 461 var notification = webkitNotifications.createNotification(iconData, titl
e, message); |
| 462 notification.show(); |
| 463 notification.addEventListener("click", openNotificationLinks, false); |
| 464 notification.addEventListener("close", notificationClosed, false); |
| 465 }); |
| 466 } |
| 467 else |
| 468 { |
| 469 var message = title + "\n" + message; |
| 470 if (hasLinks) |
| 471 message += "\n\n" + ext.i18n.getMessage("notification_with_buttons"); |
| 472 |
| 473 var approved = confirm(message); |
| 474 if (activeNotification.type === "question") |
| 475 notificationButtonClick(approved ? 0 : 1); |
| 476 else if (approved) |
| 477 openNotificationLinks(); |
| 478 } |
| 479 } |
| 480 prepareNotificationIconAndPopup(); |
| 481 } |
| 482 |
| 483 // This is a hack to speedup loading of the options page on Safari. |
| 484 // Once we replaced the background page proxy with message passing |
| 485 // this global function should removed. |
| 486 function getUserFilters() |
| 487 { |
| 488 var filters = []; |
| 489 var exceptions = []; |
| 490 |
| 491 for (var i = 0; i < FilterStorage.subscriptions.length; i++) |
| 492 { |
| 493 var subscription = FilterStorage.subscriptions[i]; |
| 494 if (!(subscription instanceof SpecialSubscription)) |
| 495 continue; |
| 496 |
| 497 for (var j = 0; j < subscription.filters.length; j++) |
| 498 { |
| 499 var filter = subscription.filters[j]; |
| 500 if (filter instanceof WhitelistFilter && /^@@\|\|([^\/:]+)\^\$document$/.
test(filter.text)) |
| 501 exceptions.push(RegExp.$1); |
| 502 else |
| 503 filters.push(filter.text); |
| 504 } |
| 505 } |
| 506 |
| 507 return {filters: filters, exceptions: exceptions}; |
343 } | 508 } |
344 | 509 |
345 ext.onMessage.addListener(function (msg, sender, sendResponse) | 510 ext.onMessage.addListener(function (msg, sender, sendResponse) |
346 { | 511 { |
347 switch (msg.type) | 512 switch (msg.type) |
348 { | 513 { |
349 case "get-selectors": | 514 case "get-selectors": |
350 var selectors = null; | 515 var selectors = []; |
351 var frameId = sender.tab ? getFrameId(sender.tab, msg.frameUrl) : -1; | |
352 | 516 |
353 if (!isFrameWhitelisted(sender.tab, frameId, "DOCUMENT") && | 517 if (!isFrameWhitelisted(sender.page, sender.frame, "DOCUMENT") && |
354 !isFrameWhitelisted(sender.tab, frameId, "ELEMHIDE")) | 518 !isFrameWhitelisted(sender.page, sender.frame, "ELEMHIDE")) |
355 { | 519 { |
356 var noStyleRules = false; | 520 var noStyleRules = false; |
357 var host = extractHostFromURL(msg.frameUrl); | 521 var host = extractHostFromFrame(sender.frame); |
358 for (var i = 0; i < noStyleRulesHosts.length; i++) | 522 for (var i = 0; i < noStyleRulesHosts.length; i++) |
359 { | 523 { |
360 var noStyleHost = noStyleRulesHosts[i]; | 524 var noStyleHost = noStyleRulesHosts[i]; |
361 if (host == noStyleHost || (host.length > noStyleHost.length && | 525 if (host == noStyleHost || (host.length > noStyleHost.length && |
362 host.substr(host.length - noStyleHost.leng
th - 1) == "." + noStyleHost)) | 526 host.substr(host.length - noStyleHost.leng
th - 1) == "." + noStyleHost)) |
363 { | 527 { |
364 noStyleRules = true; | 528 noStyleRules = true; |
365 } | 529 } |
366 } | 530 } |
367 selectors = ElemHide.getSelectorsForDomain(host, false); | 531 selectors = ElemHide.getSelectorsForDomain(host, false); |
368 if (noStyleRules) | 532 if (noStyleRules) |
369 { | 533 { |
370 selectors = selectors.filter(function(s) | 534 selectors = selectors.filter(function(s) |
371 { | 535 { |
372 return !/\[style[\^\$]?=/.test(s); | 536 return !/\[style[\^\$]?=/.test(s); |
373 }); | 537 }); |
374 } | 538 } |
375 } | 539 } |
376 | 540 |
377 sendResponse(selectors); | 541 sendResponse(selectors); |
378 break; | 542 break; |
379 case "should-collapse": | 543 case "should-collapse": |
380 var frameId = sender.tab ? getFrameId(sender.tab, msg.documentUrl) : -1; | 544 if (isFrameWhitelisted(sender.page, sender.frame, "DOCUMENT")) |
381 | |
382 if (isFrameWhitelisted(sender.tab, frameId, "DOCUMENT")) | |
383 { | 545 { |
384 sendResponse(false); | 546 sendResponse(false); |
385 break; | 547 break; |
386 } | 548 } |
387 | 549 |
388 var requestHost = extractHostFromURL(msg.url); | 550 var requestHost = extractHostFromURL(msg.url); |
389 var documentHost = extractHostFromURL(msg.documentUrl); | 551 var documentHost = extractHostFromFrame(sender.frame); |
390 var thirdParty = isThirdParty(requestHost, documentHost); | 552 var thirdParty = isThirdParty(requestHost, documentHost); |
391 var filter = defaultMatcher.matchesAny(msg.url, msg.mediatype, documentHos
t, thirdParty); | 553 var filter = defaultMatcher.matchesAny(msg.url, msg.mediatype, documentHos
t, thirdParty); |
392 if (filter instanceof BlockingFilter) | 554 if (filter instanceof BlockingFilter) |
393 { | 555 { |
394 var collapse = filter.collapse; | 556 var collapse = filter.collapse; |
395 if (collapse == null) | 557 if (collapse == null) |
396 collapse = (localStorage.hidePlaceholders != "false"); | 558 collapse = Prefs.hidePlaceholders; |
397 sendResponse(collapse); | 559 sendResponse(collapse); |
398 } | 560 } |
399 else | 561 else |
400 sendResponse(false); | 562 sendResponse(false); |
401 break; | 563 break; |
402 case "get-domain-enabled-state": | 564 case "get-domain-enabled-state": |
403 // Returns whether this domain is in the exclusion list. | 565 // Returns whether this domain is in the exclusion list. |
404 // The browser action popup asks us this. | 566 // The browser action popup asks us this. |
405 if(sender.tab) | 567 if(sender.page) |
406 { | 568 { |
407 sendResponse({enabled: !isWhitelisted(sender.tab.url)}); | 569 sendResponse({enabled: !isWhitelisted(sender.page.url)}); |
408 return; | 570 return; |
409 } | 571 } |
410 break; | 572 break; |
411 case "add-filters": | 573 case "add-filters": |
412 if (msg.filters && msg.filters.length) | 574 if (msg.filters && msg.filters.length) |
413 { | 575 { |
414 for (var i = 0; i < msg.filters.length; i++) | 576 for (var i = 0; i < msg.filters.length; i++) |
415 FilterStorage.addFilter(Filter.fromText(msg.filters[i])); | 577 FilterStorage.addFilter(Filter.fromText(msg.filters[i])); |
416 } | 578 } |
417 break; | 579 break; |
418 case "add-subscription": | 580 case "add-subscription": |
419 openOptions(function(tab) | 581 openOptions(function(page) |
420 { | 582 { |
421 tab.sendMessage(msg); | 583 page.sendMessage(msg); |
422 }); | 584 }); |
423 break; | 585 break; |
| 586 case "add-key-exception": |
| 587 processKeyException(msg.token, sender.page, sender.frame); |
| 588 break; |
424 case "forward": | 589 case "forward": |
425 if (sender.tab) | 590 if (sender.page) |
426 { | 591 { |
427 sender.tab.sendMessage(msg.payload, sendResponse); | 592 sender.page.sendMessage(msg.payload, sendResponse); |
428 // Return true to indicate that we want to call | 593 // Return true to indicate that we want to call |
429 // sendResponse asynchronously | 594 // sendResponse asynchronously |
430 return true; | 595 return true; |
431 } | 596 } |
432 break; | 597 break; |
433 default: | 598 default: |
434 sendResponse({}); | 599 sendResponse({}); |
435 break; | 600 break; |
436 } | 601 } |
437 }); | 602 }); |
438 | 603 |
439 // Show icon as browser action for all tabs that already exist | 604 // update icon when page changes location |
440 ext.windows.getAll(function(windows) | 605 ext.pages.onLoading.addListener(function(page) |
441 { | 606 { |
442 for (var i = 0; i < windows.length; i++) | 607 page.sendMessage({type: "clickhide-deactivate"}); |
443 { | 608 refreshIconAndContextMenu(page); |
444 windows[i].getAllTabs(function(tabs) | |
445 { | |
446 tabs.forEach(refreshIconAndContextMenu); | |
447 }); | |
448 } | |
449 }); | |
450 | |
451 // Update icon if a tab changes location | |
452 ext.tabs.onLoading.addListener(function(tab) | |
453 { | |
454 tab.sendMessage({type: "clickhide-deactivate"}); | |
455 refreshIconAndContextMenu(tab); | |
456 }); | 609 }); |
457 | 610 |
458 setTimeout(function() | 611 setTimeout(function() |
459 { | 612 { |
460 var notificationToShow = Notification.getNextToShow(); | 613 var notificationToShow = Notification.getNextToShow(); |
461 if (notificationToShow) | 614 if (notificationToShow) |
462 showNotification(notificationToShow); | 615 showNotification(notificationToShow); |
463 }, 3 * 60 * 1000); | 616 }, 3 * 60 * 1000); |
OLD | NEW |