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

Delta Between Two Patch Sets: background.js

Issue 5196306347720704: Issue 1965 - Simplified and fixed missing image for icon animation (Closed)
Left Patch Set: Created Feb. 27, 2014, 7:25 p.m.
Right Patch Set: Rebased and addressed comment Created Feb. 12, 2015, 11:15 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 | lib/icon.js » ('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 <http://adblockplus.org/>, 2 * This file is part of Adblock Plus <https://adblockplus.org/>,
3 * Copyright (C) 2006-2013 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.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;
29 } 30 }
30 with(require("whitelisting")) 31 with(require("whitelisting"))
31 { 32 {
32 this.isWhitelisted = isWhitelisted; 33 this.isPageWhitelisted = isPageWhitelisted;
33 this.isFrameWhitelisted = isFrameWhitelisted; 34 this.isFrameWhitelisted = isFrameWhitelisted;
34 this.processKeyException = processKeyException; 35 this.processKey = processKey;
36 this.getKey = getKey;
37 }
38 with(require("url"))
39 {
40 this.stringifyURL = stringifyURL;
41 this.isThirdParty = isThirdParty;
42 this.extractHostFromFrame = extractHostFromFrame;
43 }
44 with(require("icon"))
45 {
46 this.updateIcon = updateIcon;
47 this.startIconAnimation = startIconAnimation;
48 this.stopIconAnimation = stopIconAnimation;
35 } 49 }
36 var FilterStorage = require("filterStorage").FilterStorage; 50 var FilterStorage = require("filterStorage").FilterStorage;
37 var ElemHide = require("elemHide").ElemHide; 51 var ElemHide = require("elemHide").ElemHide;
38 var defaultMatcher = require("matcher").defaultMatcher; 52 var defaultMatcher = require("matcher").defaultMatcher;
39 var Prefs = require("prefs").Prefs; 53 var Prefs = require("prefs").Prefs;
40 var Synchronizer = require("synchronizer").Synchronizer; 54 var Synchronizer = require("synchronizer").Synchronizer;
41 var Utils = require("utils").Utils; 55 var Utils = require("utils").Utils;
42 var Notification = require("notification").Notification; 56 var NotificationStorage = require("notification").Notification;
57 var initAntiAdblockNotification = require("antiadblockInit").initAntiAdblockNoti fication;
58 var parseFilters = require("filterValidation").parseFilters;
43 59
44 // Some types cannot be distinguished 60 // Some types cannot be distinguished
45 RegExpFilter.typeMap.OBJECT_SUBREQUEST = RegExpFilter.typeMap.OBJECT; 61 RegExpFilter.typeMap.OBJECT_SUBREQUEST = RegExpFilter.typeMap.OBJECT;
46 RegExpFilter.typeMap.MEDIA = RegExpFilter.typeMap.FONT = RegExpFilter.typeMap.OT HER; 62 RegExpFilter.typeMap.MEDIA = RegExpFilter.typeMap.FONT = RegExpFilter.typeMap.OT HER;
47 63
48 var isFirstRun = false; 64 // Chrome on Linux does not fully support chrome.notifications until version 35
65 // https://code.google.com/p/chromium/issues/detail?id=291485
66 var canUseChromeNotifications = require("info").platform == "chromium"
67 && "notifications" in chrome
68 && (navigator.platform.indexOf("Linux") == -1 || parseInt(require("info").appl icationVersion, 10) > 34);
69
49 var seenDataCorruption = false; 70 var seenDataCorruption = false;
71 var filterlistsReinitialized = false;
50 require("filterNotifier").FilterNotifier.addListener(function(action) 72 require("filterNotifier").FilterNotifier.addListener(function(action)
51 { 73 {
52 if (action == "load") 74 if (action == "load")
53 { 75 {
54 var importingOldData = importOldData();
55
56 var addonVersion = require("info").addonVersion; 76 var addonVersion = require("info").addonVersion;
57 var prevVersion = localStorage.currentVersion; 77 var prevVersion = ext.storage.currentVersion;
58 if (prevVersion != addonVersion) 78
59 { 79 // There are no filters stored so we need to reinitialize all filterlists
60 isFirstRun = !prevVersion; 80 if (!FilterStorage.firstRun && FilterStorage.subscriptions.length === 0)
61 localStorage.currentVersion = addonVersion; 81 {
62 if (!importingOldData) 82 filterlistsReinitialized = true;
63 addSubscription(prevVersion); 83 prevVersion = null;
64 } 84 }
85
86 if (prevVersion != addonVersion || FilterStorage.firstRun)
87 {
88 seenDataCorruption = prevVersion && FilterStorage.firstRun;
89 ext.storage.currentVersion = addonVersion;
90 addSubscription(prevVersion);
91 }
92
93 if (canUseChromeNotifications)
94 initChromeNotifications();
95 initAntiAdblockNotification();
96
97 // The "Hide placeholders" option has been removed from the UI in 1.8.8.1285
98 // So we reset the option for users updating from older versions.
99 if (prevVersion && Services.vc.compare(prevVersion, "1.8.8.1285") < 0)
100 Prefs.hidePlaceholders = true;
65 } 101 }
66 102
67 // update browser actions when whitelisting might have changed, 103 // update browser actions when whitelisting might have changed,
68 // due to loading filters or saving filter changes 104 // due to loading filters or saving filter changes
69 if (action == "load" || action == "save") 105 if (action == "load" || action == "save")
70 { 106 refreshIconAndContextMenuForAllPages();
71 ext.windows.getAll(function(windows)
72 {
73 for (var i = 0; i < windows.length; i++)
74 {
75 windows[i].getAllTabs(function(tabs)
76 {
77 tabs.forEach(refreshIconAndContextMenu);
78 });
79 }
80 });
81 }
82 }); 107 });
83 108
84 // Special-case domains for which we cannot use style-based hiding rules. 109 // Special-case domains for which we cannot use style-based hiding rules.
85 // See http://crbug.com/68705. 110 // See http://crbug.com/68705.
86 var noStyleRulesHosts = ["mail.google.com", "mail.yahoo.com", "www.google.com"]; 111 var noStyleRulesHosts = ["mail.google.com", "mail.yahoo.com", "www.google.com"];
87 112
113 var htmlPages = new ext.PageMap();
114
88 function removeDeprecatedOptions() 115 function removeDeprecatedOptions()
89 { 116 {
90 var deprecatedOptions = ["specialCaseYouTube", "experimental", "disableInlineT extAds"]; 117 var deprecatedOptions = ["specialCaseYouTube", "experimental", "disableInlineT extAds"];
91 deprecatedOptions.forEach(function(option) 118 deprecatedOptions.forEach(function(option)
92 { 119 {
93 if (option in localStorage) 120 if (option in ext.storage)
94 delete localStorage[option]; 121 delete ext.storage[option];
95 }); 122 });
96 } 123 }
97 124
98 // Remove deprecated options before we do anything else. 125 // Remove deprecated options before we do anything else.
99 removeDeprecatedOptions(); 126 removeDeprecatedOptions();
100 127
101 var activeNotification = null; 128 var activeNotification = null;
102 129
103 function getTabStatus(tab, animation) 130 var contextMenuItem = {
104 { 131 title: ext.i18n.getMessage("block_element"),
105 var whitelisted = isWhitelisted(tab.url); 132 contexts: ["image", "video", "audio"],
106 133 onclick: function(page)
107 var icon; 134 {
108 if (require("info").platform == "safari") 135 page.sendMessage({type: "clickhide-new-filter"});
109 // pick an icon with approtiate size for Safari. However since 136 }
110 // toolbar item icons can't use different colors, we don't have 137 };
111 // different versions indicating whether the page is whitelisted 138
112 icon = "icons/abp-16"; 139 // Adds or removes browser action icon according to options.
113 else 140 function refreshIconAndContextMenu(page)
114 { 141 {
115 // pick an icon with the approtiate size for Chrome/Opera 142 var whitelisted = isPageWhitelisted(page);
116 // that indicates whether the page is whitelisted 143 updateIcon(page, whitelisted);
117 if (whitelisted && (!animation || animation.step < 10))
Felix Dahlke 2014/02/27 22:02:05 So we will use the red ABP icon if the animation s
Sebastian Noack 2014/02/28 08:35:16 We are neither going to use the red default nor th
118 icon = "icons/abp-19-whitelisted";
119 else
120 icon = "icons/abp-19";
121 }
122
123 // pick the current frame if the icon is currently animating
124 // in order to indicate a pending notification
125 if (animation && animation.step > 0)
126 {
127 icon += "-notification-";
128 icon += animation.severity;
Wladimir Palant 2014/03/06 14:31:35 Nit: why split this to two statements? This seems
Sebastian Noack 2014/03/06 20:41:13 I found it slightly more readable to have one oper
129
130 if (animation.step < 10)
131 {
132 icon += "-";
133 icon += animation.step;
134 }
135 }
136
137 icon += ".png";
138
139 return {icon: icon, whitelisted: whitelisted};
140 }
141
142 function refreshIconAndContextMenu(tab)
143 {
144 var status = getTabStatus(tab);
145
146 // update icon indicating whether the page is whitelisted.
147 // But don't interfere the icon animation if active.
Felix Dahlke 2014/02/27 22:02:05 s/interfere/interrupt/?
Sebastian Noack 2014/02/28 08:35:16 Don't know. It wouldn't just pause the animation,
Wladimir Palant 2014/03/06 14:31:35 If we now have a generic function to calculate the
Wladimir Palant 2014/03/06 14:34:33 In fact, this isn't even necessary. If iconAnimati
Sebastian Noack 2014/03/06 20:41:13 Done. On 2014/03/06 14:34:33, Wladimir Palant wro
Wladimir Palant 2014/03/06 20:49:44 Isn't that exactly the issue that registerTab() wa
Sebastian Noack 2014/03/07 17:26:11 Now it is addressed within getTabStatus() as you s
Wladimir Palant 2014/03/07 22:13:29 Still missing something that would start the anima
Sebastian Noack 2014/03/08 11:36:39 Considering that the animation is interrupted anyw
Wladimir Palant 2014/03/21 14:10:11 Why interrupted? The animation step doesn't change
Sebastian Noack 2014/03/31 13:20:32 Since the icon is set per tab, when the active tab
148 // In that case the icon animation takes care to update
149 // the icon to its new status with its next frame.
150 if (!iconAnimation.tabs.has(tab))
151 tab.browserAction.setIcon(status.icon);
152 144
153 // show or hide the context menu entry dependent on whether 145 // show or hide the context menu entry dependent on whether
154 // adblocking is active in the tab 146 // adblocking is active on that page
155 if (status.whitelisted || !/^https?:/.test(tab.url)) 147 page.contextMenus.removeAll();
156 ext.contextMenus.hideMenuItems(); 148 if (Prefs.shouldShowBlockElementMenu && !whitelisted && htmlPages.has(page))
157 else 149 page.contextMenus.create(contextMenuItem);
158 ext.contextMenus.showMenuItems(); 150 }
159 } 151
160 152 function refreshIconAndContextMenuForAllPages()
161 /** 153 {
162 * Old versions for Opera stored patterns.ini in the localStorage object, this 154 ext.pages.query({}, function(pages)
163 * will import it into FilterStorage properly. 155 {
164 * @return {Boolean} true if data import is in progress 156 pages.forEach(refreshIconAndContextMenu);
165 */ 157 });
166 function importOldData()
167 {
168 if ("patterns.ini" in localStorage)
169 {
170 FilterStorage.loadFromDisk(localStorage["patterns.ini"]);
171
172 var remove = [];
173 for (var key in localStorage)
174 if (key.indexOf("patterns.ini") == 0 || key.indexOf("patterns-backup") == 0)
175 remove.push(key);
176 for (var i = 0; i < remove.length; i++)
177 delete localStorage[remove[i]];
178
179 return true;
180 }
181 else
182 return false;
183 } 158 }
184 159
185 /** 160 /**
186 * This function is called on an extension update. It will add the default 161 * This function is called on an extension update. It will add the default
187 * filter subscription if necessary. 162 * filter subscription if necessary.
188 */ 163 */
189 function addSubscription(prevVersion) 164 function addSubscription(prevVersion)
190 { 165 {
191 // Make sure to remove "Recommended filters", no longer necessary 166 // Make sure to remove "Recommended filters", no longer necessary
192 var toRemove = "https://easylist-downloads.adblockplus.org/chrome_supplement.t xt"; 167 var toRemove = "https://easylist-downloads.adblockplus.org/chrome_supplement.t xt";
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
228 { 203 {
229 subscription.title = "Allow non-intrusive advertising"; 204 subscription.title = "Allow non-intrusive advertising";
230 FilterStorage.addSubscription(subscription); 205 FilterStorage.addSubscription(subscription);
231 if (subscription instanceof DownloadableSubscription && !subscription.last Download) 206 if (subscription instanceof DownloadableSubscription && !subscription.last Download)
232 Synchronizer.execute(subscription); 207 Synchronizer.execute(subscription);
233 } 208 }
234 else 209 else
235 addAcceptable = false; 210 addAcceptable = false;
236 } 211 }
237 212
213 // Add "anti-adblock messages" subscription for new users and users updating f rom old ABP versions
214 if (!prevVersion || Services.vc.compare(prevVersion, "1.8") < 0)
215 {
216 var subscription = Subscription.fromURL(Prefs.subscriptions_antiadblockurl);
217 if (subscription && !(subscription.url in FilterStorage.knownSubscriptions))
218 {
219 subscription.disabled = true;
220 FilterStorage.addSubscription(subscription);
221 if (subscription instanceof DownloadableSubscription && !subscription.last Download)
222 Synchronizer.execute(subscription);
223 }
224 }
225
238 if (!addSubscription && !addAcceptable) 226 if (!addSubscription && !addAcceptable)
239 return; 227 return;
240 228
241 function notifyUser() 229 function notifyUser()
242 { 230 {
243 ext.windows.getLastFocused(function(win) 231 ext.pages.open(ext.getURL("firstRun.html"));
244 {
245 win.openTab(ext.getURL("firstRun.html"));
246 });
247 } 232 }
248 233
249 if (addSubscription) 234 if (addSubscription)
250 { 235 {
251 // Load subscriptions data 236 // Load subscriptions data
252 var request = new XMLHttpRequest(); 237 var request = new XMLHttpRequest();
253 request.open("GET", "subscriptions.xml"); 238 request.open("GET", "subscriptions.xml");
254 request.addEventListener("load", function() 239 request.addEventListener("load", function()
255 { 240 {
256 var node = Utils.chooseFilterSubscription(request.responseXML.getElementsB yTagName("subscription")); 241 var node = Utils.chooseFilterSubscription(request.responseXML.getElementsB yTagName("subscription"));
257 var subscription = (node ? Subscription.fromURL(node.getAttribute("url")) : null); 242 var subscription = (node ? Subscription.fromURL(node.getAttribute("url")) : null);
258 if (subscription) 243 if (subscription)
259 { 244 {
260 FilterStorage.addSubscription(subscription); 245 FilterStorage.addSubscription(subscription);
261 subscription.disabled = false; 246 subscription.disabled = false;
262 subscription.title = node.getAttribute("title"); 247 subscription.title = node.getAttribute("title");
263 subscription.homepage = node.getAttribute("homepage"); 248 subscription.homepage = node.getAttribute("homepage");
264 if (subscription instanceof DownloadableSubscription && !subscription.la stDownload) 249 if (subscription instanceof DownloadableSubscription && !subscription.la stDownload)
265 Synchronizer.execute(subscription); 250 Synchronizer.execute(subscription);
266 251
267 notifyUser(); 252 notifyUser();
268 } 253 }
269 }, false); 254 }, false);
270 request.send(null); 255 request.send(null);
271 } 256 }
272 else 257 else
273 notifyUser(); 258 notifyUser();
274 } 259 }
275 260
276 function setContextMenu()
277 {
278 if (Prefs.shouldShowBlockElementMenu)
279 {
280 // Register context menu item
281 ext.contextMenus.addMenuItem(ext.i18n.getMessage("block_element"), ["image", "video", "audio"], function(srcUrl, tab)
282 {
283 if (srcUrl)
284 tab.sendMessage({type: "clickhide-new-filter", filter: srcUrl});
285 });
286 }
287 else
288 ext.contextMenus.removeMenuItems();
289 }
290
291 Prefs.addListener(function(name) 261 Prefs.addListener(function(name)
292 { 262 {
293 if (name == "shouldShowBlockElementMenu") 263 if (name == "shouldShowBlockElementMenu")
294 setContextMenu(); 264 refreshIconAndContextMenuForAllPages();
295 }); 265 });
296 setContextMenu(); 266
297 267 function prepareNotificationIconAndPopup()
298 /** 268 {
299 * Opens options tab or focuses an existing one, within the last focused window . 269 var animateIcon = (activeNotification.type !== "question");
300 * @param {Function} callback function to be called with the 270 activeNotification.onClicked = function()
301 Tab object of the options tab 271 {
302 */ 272 if (animateIcon)
303 function openOptions(callback) 273 stopIconAnimation();
304 { 274 notificationClosed();
305 ext.windows.getLastFocused(function(win) 275 };
306 { 276 if (animateIcon)
307 win.getAllTabs(function(tabs) 277 startIconAnimation(activeNotification.type);
308 { 278 }
309 var optionsUrl = ext.getURL("options.html"); 279
310 280 function openNotificationLinks()
311 for (var i = 0; i < tabs.length; i++) 281 {
312 { 282 if (activeNotification.links)
313 if (tabs[i].url == optionsUrl) 283 {
314 { 284 activeNotification.links.forEach(function(link)
315 tabs[i].activate(); 285 {
316 if (callback) 286 ext.windows.getLastFocused(function(win)
317 callback(tabs[i]); 287 {
318 return; 288 win.openTab(Utils.getDocLink(link));
319 }
320 }
321
322 win.openTab(optionsUrl, callback && function(tab)
323 {
324 tab.onCompleted.addListener(callback);
325 }); 289 });
326 }); 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);
327 }); 351 });
328 } 352 chrome.notifications.onClicked.addListener(clearActiveNotification);
329 353 chrome.notifications.onClosed.addListener(notificationClosed);
330 function prepareNotificationIconAndPopup()
331 {
332 activeNotification.onClicked = function()
333 {
334 iconAnimation.stop();
335 activeNotification = null;
336 };
337
338 iconAnimation.update(activeNotification.severity);
339 } 354 }
340 355
341 function showNotification(notification) 356 function showNotification(notification)
342 { 357 {
358 if (activeNotification && activeNotification.id === notification.id)
359 return;
360
343 activeNotification = notification; 361 activeNotification = notification;
344 362 if (activeNotification.type === "critical" || activeNotification.type === "que stion")
345 if (activeNotification.severity === "critical" 363 {
346 && typeof webkitNotifications !== "undefined") 364 var texts = NotificationStorage.getLocalizedTexts(notification);
347 { 365 var title = texts.title || "";
348 var notification = webkitNotifications.createHTMLNotification("notification. html"); 366 var message = texts.message ? texts.message.replace(/<\/?(a|strong)>/g, "") : "";
349 notification.show(); 367 var iconUrl = ext.getURL("icons/abp-128.png");
350 notification.addEventListener("close", prepareNotificationIconAndPopup); 368 var hasLinks = activeNotification.links && activeNotification.links.length > 0;
351 } 369
352 else 370 if (canUseChromeNotifications)
353 prepareNotificationIconAndPopup(); 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
436 // This is a hack to speedup loading of the options page on Safari.
437 // Once we replaced the background page proxy with message passing
438 // this global function should removed.
439 function getUserFilters()
440 {
441 var filters = [];
442 var exceptions = [];
443
444 for (var i = 0; i < FilterStorage.subscriptions.length; i++)
445 {
446 var subscription = FilterStorage.subscriptions[i];
447 if (!(subscription instanceof SpecialSubscription))
448 continue;
449
450 for (var j = 0; j < subscription.filters.length; j++)
451 {
452 var filter = subscription.filters[j];
453 if (filter instanceof WhitelistFilter && /^@@\|\|([^\/:]+)\^\$document$/. test(filter.text))
454 exceptions.push(RegExp.$1);
455 else
456 filters.push(filter.text);
457 }
458 }
459
460 return {filters: filters, exceptions: exceptions};
354 } 461 }
355 462
356 ext.onMessage.addListener(function (msg, sender, sendResponse) 463 ext.onMessage.addListener(function (msg, sender, sendResponse)
357 { 464 {
358 switch (msg.type) 465 switch (msg.type)
359 { 466 {
360 case "get-selectors": 467 case "get-selectors":
361 var selectors = null; 468 var selectors = [];
362 469
363 if (!isFrameWhitelisted(sender.tab, sender.frame, "DOCUMENT") && 470 if (!isFrameWhitelisted(sender.page, sender.frame, "DOCUMENT") &&
364 !isFrameWhitelisted(sender.tab, sender.frame, "ELEMHIDE")) 471 !isFrameWhitelisted(sender.page, sender.frame, "ELEMHIDE"))
365 { 472 {
366 var noStyleRules = false; 473 var noStyleRules = false;
367 var host = extractHostFromURL(sender.frame.url); 474 var host = extractHostFromFrame(sender.frame);
368 for (var i = 0; i < noStyleRulesHosts.length; i++) 475 for (var i = 0; i < noStyleRulesHosts.length; i++)
369 { 476 {
370 var noStyleHost = noStyleRulesHosts[i]; 477 var noStyleHost = noStyleRulesHosts[i];
371 if (host == noStyleHost || (host.length > noStyleHost.length && 478 if (host == noStyleHost || (host.length > noStyleHost.length &&
372 host.substr(host.length - noStyleHost.leng th - 1) == "." + noStyleHost)) 479 host.substr(host.length - noStyleHost.leng th - 1) == "." + noStyleHost))
373 { 480 {
374 noStyleRules = true; 481 noStyleRules = true;
375 } 482 }
376 } 483 }
377 selectors = ElemHide.getSelectorsForDomain(host, false); 484 selectors = ElemHide.getSelectorsForDomain(host, false);
378 if (noStyleRules) 485 if (noStyleRules)
379 { 486 {
380 selectors = selectors.filter(function(s) 487 selectors = selectors.filter(function(s)
381 { 488 {
382 return !/\[style[\^\$]?=/.test(s); 489 return !/\[style[\^\$]?=/.test(s);
383 }); 490 });
384 } 491 }
385 } 492 }
386 493
387 sendResponse(selectors); 494 sendResponse(selectors);
388 break; 495 break;
389 case "should-collapse": 496 case "should-collapse":
390 if (isFrameWhitelisted(sender.tab, sender.frame, "DOCUMENT")) 497 if (isFrameWhitelisted(sender.page, sender.frame, "DOCUMENT"))
391 { 498 {
392 sendResponse(false); 499 sendResponse(false);
393 break; 500 break;
394 } 501 }
395 502
396 var requestHost = extractHostFromURL(msg.url); 503 var url = new URL(msg.url);
397 var documentHost = extractHostFromURL(sender.frame.url); 504 var documentHost = extractHostFromFrame(sender.frame);
398 var thirdParty = isThirdParty(requestHost, documentHost); 505 var filter = defaultMatcher.matchesAny(
399 var filter = defaultMatcher.matchesAny(msg.url, msg.mediatype, documentHos t, thirdParty); 506 stringifyURL(url), msg.mediatype,
507 documentHost, isThirdParty(url, documentHost)
508 );
509
400 if (filter instanceof BlockingFilter) 510 if (filter instanceof BlockingFilter)
401 { 511 {
402 var collapse = filter.collapse; 512 var collapse = filter.collapse;
403 if (collapse == null) 513 if (collapse == null)
404 collapse = Prefs.hidePlaceholders; 514 collapse = Prefs.hidePlaceholders;
405 sendResponse(collapse); 515 sendResponse(collapse);
406 } 516 }
407 else 517 else
408 sendResponse(false); 518 sendResponse(false);
409 break; 519 break;
410 case "get-domain-enabled-state": 520 case "get-domain-enabled-state":
411 // Returns whether this domain is in the exclusion list. 521 // Returns whether this domain is in the exclusion list.
412 // The browser action popup asks us this. 522 // The browser action popup asks us this.
413 if(sender.tab) 523 if(sender.page)
414 { 524 {
415 sendResponse({enabled: !isWhitelisted(sender.tab.url)}); 525 sendResponse({enabled: !isPageWhitelisted(sender.page)});
416 return; 526 return;
417 } 527 }
418 break; 528 break;
419 case "add-filters": 529 case "add-filters":
420 if (msg.filters && msg.filters.length) 530 var filters;
421 { 531 try
422 for (var i = 0; i < msg.filters.length; i++) 532 {
423 FilterStorage.addFilter(Filter.fromText(msg.filters[i])); 533 filters = parseFilters(msg.text);
424 } 534 }
535 catch (error)
536 {
537 sendResponse({status: "invalid", error: error});
538 break;
539 }
540
541 for (var i = 0; i < filters.length; i++)
542 FilterStorage.addFilter(filters[i]);
543
544 sendResponse({status: "ok"});
425 break; 545 break;
426 case "add-subscription": 546 case "add-subscription":
427 openOptions(function(tab) 547 ext.showOptions(function(page)
428 { 548 {
429 tab.sendMessage(msg); 549 page.sendMessage(msg);
430 }); 550 });
431 break; 551 break;
432 case "add-key-exception": 552 case "add-sitekey":
433 processKeyException(msg.token, sender.tab, sender.frame); 553 processKey(msg.token, sender.page, sender.frame);
554 break;
555 case "report-html-page":
556 htmlPages.set(sender.page, null);
557 refreshIconAndContextMenu(sender.page);
434 break; 558 break;
435 case "forward": 559 case "forward":
436 if (sender.tab) 560 if (sender.page)
437 { 561 {
438 sender.tab.sendMessage(msg.payload, sendResponse); 562 if (msg.expectsResponse)
439 // Return true to indicate that we want to call 563 {
440 // sendResponse asynchronously 564 sender.page.sendMessage(msg.payload, sendResponse);
441 return true; 565 return true;
442 } 566 }
443 break; 567
444 default: 568 sender.page.sendMessage(msg.payload);
445 sendResponse({}); 569 }
446 break; 570 break;
447 } 571 }
448 }); 572 });
449 573
450 // Update icon if a tab changes location 574 // update icon when page changes location
451 ext.tabs.onLoading.addListener(function(tab) 575 ext.pages.onLoading.addListener(function(page)
452 { 576 {
453 tab.sendMessage({type: "clickhide-deactivate"}); 577 page.sendMessage({type: "clickhide-deactivate"});
454 refreshIconAndContextMenu(tab); 578 refreshIconAndContextMenu(page);
455 }); 579 });
456 580
457 setTimeout(function() 581 setTimeout(function()
458 { 582 {
459 var notificationToShow = Notification.getNextToShow(); 583 var notificationToShow = NotificationStorage.getNextToShow();
460 if (notificationToShow) 584 if (notificationToShow)
461 showNotification(notificationToShow); 585 showNotification(notificationToShow);
462 }, 3 * 60 * 1000); 586 }, 3 * 60 * 1000);
LEFTRIGHT
« no previous file | lib/icon.js » ('j') | Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Toggle Comments ('s')

Powered by Google App Engine
This is Rietveld