| LEFT | RIGHT | 
|    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-2013 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 | 
| (...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|  101 { |  101 { | 
|  102   // Ignore fragment identifier |  102   // Ignore fragment identifier | 
|  103   var index = url.indexOf("#"); |  103   var index = url.indexOf("#"); | 
|  104   if (index >= 0) |  104   if (index >= 0) | 
|  105     url = url.substring(0, index); |  105     url = url.substring(0, index); | 
|  106  |  106  | 
|  107   var result = defaultMatcher.matchesAny(url, type || "DOCUMENT", extractHostFro
     mURL(parentUrl || url), false); |  107   var result = defaultMatcher.matchesAny(url, type || "DOCUMENT", extractHostFro
     mURL(parentUrl || url), false); | 
|  108   return (result instanceof WhitelistFilter ? result : null); |  108   return (result instanceof WhitelistFilter ? result : null); | 
|  109 } |  109 } | 
|  110  |  110  | 
 |  111 var activeNotification = null; | 
 |  112  | 
|  111 // Adds or removes page action icon according to options. |  113 // Adds or removes page action icon according to options. | 
|  112 function refreshIconAndContextMenu(tab) |  114 function refreshIconAndContextMenu(tab) | 
|  113 { |  115 { | 
|  114   // The tab could have been closed by the time this function is called |  116   // The tab could have been closed by the time this function is called | 
|  115   if(!tab) |  117   if(!tab) | 
|  116     return; |  118     return; | 
|  117  |  119  | 
|  118   var excluded = isWhitelisted(tab.url); |  120   var excluded = isWhitelisted(tab.url); | 
|  119   var iconFilename = excluded ? "icons/abp-19-whitelisted.png" : "icons/abp-19.p
     ng"; |  121   var iconFilename = excluded ? "icons/abp-19-whitelisted.png" : "icons/abp-19.p
     ng"; | 
|  120   chrome.pageAction.setIcon({tabId: tab.id, path: iconFilename}); |  122  | 
 |  123   if (activeNotification) | 
 |  124     startIconAnimation(tab, iconFilename); | 
 |  125   else | 
 |  126     chrome.pageAction.setIcon({tabId: tab.id, path: iconFilename}); | 
|  121  |  127  | 
|  122   // Only show icon for pages we can influence (http: and https:) |  128   // Only show icon for pages we can influence (http: and https:) | 
|  123   if(/^https?:/.test(tab.url)) |  129   if(/^https?:/.test(tab.url)) | 
|  124   { |  130   { | 
|  125     chrome.pageAction.setTitle({tabId: tab.id, title: "Adblock Plus"}); |  131     chrome.pageAction.setTitle({tabId: tab.id, title: "Adblock Plus"}); | 
|  126     if ("shouldShowIcon" in localStorage && localStorage["shouldShowIcon"] == "f
     alse") |  132     if ("shouldShowIcon" in localStorage && localStorage["shouldShowIcon"] == "f
     alse") | 
|  127       chrome.pageAction.hide(tab.id); |  133       chrome.pageAction.hide(tab.id); | 
|  128     else |  134     else | 
|  129       chrome.pageAction.show(tab.id); |  135       chrome.pageAction.show(tab.id); | 
|  130  |  136  | 
|  131     // Set context menu status according to whether current tab has whitelisted 
     domain |  137     // Set context menu status according to whether current tab has whitelisted 
     domain | 
|  132     if (excluded) |  138     if (excluded) | 
|  133       chrome.contextMenus.removeAll(); |  139       chrome.contextMenus.removeAll(); | 
|  134     else |  140     else | 
|  135       showContextMenu(); |  141       showContextMenu(); | 
|  136   } |  142   } | 
|  137  |  | 
|  138   if (activeNotification) |  | 
|  139     setNotificationPageAction(tab); |  | 
|  140 } |  143 } | 
|  141  |  144  | 
|  142 /** |  145 /** | 
|  143  * Old versions stored filter data in the localStorage object, this will import |  146  * Old versions stored filter data in the localStorage object, this will import | 
|  144  * it into FilterStorage properly. |  147  * it into FilterStorage properly. | 
|  145  */ |  148  */ | 
|  146 function importOldData() |  149 function importOldData() | 
|  147 { |  150 { | 
|  148   function addSubscription(url, title) |  151   function addSubscription(url, title) | 
|  149   { |  152   { | 
| (...skipping 320 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|  470             chrome.tabs.onUpdated.removeListener(listener); |  473             chrome.tabs.onUpdated.removeListener(listener); | 
|  471             onLoad(); |  474             onLoad(); | 
|  472           } |  475           } | 
|  473         }; |  476         }; | 
|  474         chrome.tabs.onUpdated.addListener(listener); |  477         chrome.tabs.onUpdated.addListener(listener); | 
|  475       } |  478       } | 
|  476     }); |  479     }); | 
|  477   } |  480   } | 
|  478 } |  481 } | 
|  479  |  482  | 
|  480 var activeNotification; |  483 var iconAnimationTimer = null; | 
 |  484 var animatedIconTab = null; | 
 |  485  | 
 |  486 function stopIconAnimation() | 
 |  487 { | 
 |  488   if (!iconAnimationTimer) | 
 |  489     return; | 
 |  490  | 
 |  491   clearTimeout(iconAnimationTimer); | 
 |  492   iconAnimationTimer = null; | 
 |  493   animatedIconTab = null; | 
 |  494 } | 
|  481  |  495  | 
|  482 function loadImages(imageFiles, callback) |  496 function loadImages(imageFiles, callback) | 
|  483 { |  497 { | 
|  484   var images = {}; |  498   var images = {}; | 
 |  499   var imagesLoaded = 0; | 
|  485   imageFiles.forEach(function(imageFile) |  500   imageFiles.forEach(function(imageFile) | 
|  486   { |  501   { | 
|  487     var image = new Image(); |  502     var image = new Image(); | 
|  488     image.src = imageFile; |  503     image.src = imageFile; | 
|  489     image.addEventListener("load", function() |  504     image.addEventListener("load", function() | 
|  490     { |  505     { | 
|  491       images[imageFile] = image; |  506       images[imageFile] = image; | 
|  492       if (Object.keys(images).length === imageFiles.length) |  507       if (++imagesLoaded === imageFiles.length) | 
|  493         callback(images); |  508         callback(images); | 
|  494     }); |  509     }); | 
|  495   }); |  510   }); | 
|  496 } |  511 } | 
|  497  |  512  | 
|  498 function startInformationNotificationAnimation() |  513 function startIconAnimation(tab, iconPath) | 
|  499 { |  514 { | 
|  500   var abpIconFile = "icons/abp-19.png"; |  515   stopIconAnimation(); | 
|  501   var notificationIconFile = "icons/notification-information.png"; |  516   animatedIconTab = tab; | 
|  502   var iconFiles = [abpIconFile, notificationIconFile]; |  517  | 
 |  518   var severitySuffix = activeNotification.severity === "critical" | 
 |  519       ? "critical" : "information"; | 
 |  520   var notificationIconPath = "icons/notification-" + severitySuffix + ".png"; | 
 |  521   var iconFiles = [iconPath, notificationIconPath]; | 
|  503   loadImages(iconFiles, function(images) |  522   loadImages(iconFiles, function(images) | 
|  504   { |  523   { | 
|  505     var abpIcon = images[abpIconFile]; |  524     var icon = images[iconPath]; | 
|  506     var notificationIcon = images[notificationIconFile]; |  525     var notificationIcon = images[notificationIconPath]; | 
 |  526  | 
|  507     var canvas = document.createElement("canvas"); |  527     var canvas = document.createElement("canvas"); | 
|  508     canvas.width = abpIcon.width; |  528     canvas.width = icon.width; | 
|  509     canvas.height = abpIcon.height; |  529     canvas.height = icon.height; | 
|  510     var context = canvas.getContext("2d"); |  530     var context = canvas.getContext("2d"); | 
|  511  |  531  | 
|  512     var animationStartTime = Date.now(); |  532     var currentFrame = 0; | 
|  513     var animationInterval = 1000 / 60; |  533     var frameOpacities = [0, 0.2, 0.4, 0.6, 0.8, | 
 |  534                           1, 1, 1, 1, 1, | 
 |  535                           0.8, 0.6, 0.4, 0.2, 0]; | 
 |  536  | 
|  514     function animationStep() |  537     function animationStep() | 
|  515     { |  538     { | 
|  516       var timeElapsed = Date.now() - animationStartTime; |  539       var opacity = frameOpacities[currentFrame]; | 
|  517       var duration = 3000; |  | 
|  518       var animationTime = timeElapsed % duration; |  | 
|  519       var delay = 1000; |  | 
|  520       var fadeInEndTime = duration / 2 - delay / 2; |  | 
|  521       var fadeOutStartTime = fadeInEndTime + delay; |  | 
|  522  |  | 
|  523       var opacity; |  | 
|  524       if (animationTime < fadeInEndTime) |  | 
|  525         opacity = animationTime / fadeInEndTime; |  | 
|  526       else if (animationTime > fadeOutStartTime) |  | 
|  527         opacity = 1 - (animationTime - fadeOutStartTime) |  | 
|  528           / (duration - fadeOutStartTime); |  | 
|  529  |  | 
|  530       context.clearRect(0, 0, canvas.width, canvas.height); |  540       context.clearRect(0, 0, canvas.width, canvas.height); | 
|  531       context.globalAlpha = 1; |  541       context.globalAlpha = 1; | 
|  532       context.drawImage(abpIcon, 0, 0); |  542       context.drawImage(icon, 0, 0); | 
|  533       context.globalAlpha = opacity; |  543       context.globalAlpha = opacity; | 
|  534       context.drawImage(notificationIcon, 0, 0); |  544       context.drawImage(notificationIcon, 0, 0); | 
|  535       var imageData = context.getImageData(0, 0, canvas.width, canvas.height); |  545       var imageData = context.getImageData(0, 0, canvas.width, canvas.height); | 
|  536  |  546       chrome.pageAction.setIcon({tabId: tab.id, imageData: imageData}); | 
|  537       chrome.tabs.getSelected(null, function(tab) |  547  | 
|  538       { |  548       var interval; | 
|  539         chrome.pageAction.setIcon({tabId: tab.id, imageData: imageData}); |  549       currentFrame++; | 
|  540         activeNotification.animationTimer = |  550       if (currentFrame < frameOpacities.length) | 
|  541           setTimeout(animationStep, animationInterval); |  551       { | 
|  542       }); |  552         var duration = 3000; | 
 |  553         interval = duration / frameOpacities.length; | 
 |  554       } | 
 |  555       else | 
 |  556       { | 
 |  557         currentFrame = 0; | 
 |  558         interval = 10000; | 
 |  559       } | 
 |  560       iconAnimationTimer = setTimeout(animationStep, interval); | 
|  543     } |  561     } | 
|  544     animationStep(); |  562     animationStep(); | 
|  545   }); |  563   }); | 
|  546 } |  564 } | 
|  547  |  565  | 
|  548 function showInformationNotification() |  566 function prepareNotificationIconAndPopup() | 
|  549 { |  567 { | 
|  550   activeNotification.onClicked = function() |  568   activeNotification.onClicked = function() | 
|  551   { |  569   { | 
|  552     clearTimeout(activeNotification.animationTimer); |  570     var tab = animatedIconTab; | 
|  553     chrome.tabs.getAllInWindow(null, function(tabs) |  571     stopIconAnimation(); | 
 |  572     activeNotification = null; | 
 |  573     refreshIconAndContextMenu(tab); | 
 |  574   }; | 
 |  575  | 
 |  576   chrome.windows.getLastFocused({populate: true}, function(window) | 
 |  577   { | 
 |  578     chrome.tabs.query({active: true, windowId: window.id}, function(tabs) | 
|  554     { |  579     { | 
|  555       tabs.forEach(refreshIconAndContextMenu); |  580       tabs.forEach(refreshIconAndContextMenu); | 
|  556       activeNotification = null; |  | 
|  557     }); |  581     }); | 
|  558   }; |  | 
|  559  |  | 
|  560   startInformationNotificationAnimation(); |  | 
|  561 } |  | 
|  562  |  | 
|  563 function showCriticalNotification() |  | 
|  564 { |  | 
|  565   var notification = webkitNotifications.createHTMLNotification("notification.ht
     ml"); |  | 
|  566   notification.show(); |  | 
|  567 } |  | 
|  568  |  | 
|  569 function setNotificationPageAction(tab) |  | 
|  570 { |  | 
|  571   if (activeNotification.severity !== "critical") |  | 
|  572     return; |  | 
|  573  |  | 
|  574   var abpIconFile = "icons/abp-19.png"; |  | 
|  575   var notificationIconFile = "icons/notification-critical.png"; |  | 
|  576   var iconFiles = [abpIconFile, notificationIconFile]; |  | 
|  577   loadImages(iconFiles, function(images) |  | 
|  578   { |  | 
|  579     var abpIcon = images[abpIconFile]; |  | 
|  580     var notificationIcon = images[notificationIconFile]; |  | 
|  581     var canvas = document.createElement("canvas"); |  | 
|  582     canvas.width = abpIcon.width; |  | 
|  583     canvas.height = abpIcon.height; |  | 
|  584     var context = canvas.getContext("2d"); |  | 
|  585     context.clearRect(0, 0, canvas.width, canvas.height); |  | 
|  586     context.drawImage(abpIcon, 0, 0); |  | 
|  587     context.drawImage(notificationIcon, 0, 0); |  | 
|  588     var imageData = context.getImageData(0, 0, canvas.width, canvas.height); |  | 
|  589     chrome.pageAction.setIcon({tabId: tab.id, imageData: imageData}); |  | 
|  590   }); |  582   }); | 
|  591 } |  583 } | 
|  592  |  584  | 
|  593 function showNotification(notification) |  585 function showNotification(notification) | 
|  594 { |  586 { | 
|  595   activeNotification = notification; |  587   activeNotification = notification; | 
|  596  |  588  | 
|  597   if (notification.severity === "critical") |  589   if (activeNotification.severity === "critical") | 
|  598     showCriticalNotification(); |  590   { | 
 |  591     var notification = webkitNotifications.createHTMLNotification("notification.
     html"); | 
 |  592     notification.show(); | 
 |  593     notification.addEventListener("close", prepareNotificationIconAndPopup); | 
 |  594   } | 
|  599   else |  595   else | 
|  600     showInformationNotification(); |  596     prepareNotificationIconAndPopup(); | 
|  601  |  | 
|  602   chrome.tabs.getAllInWindow(null, function(tabs) |  | 
|  603   { |  | 
|  604     tabs.forEach(setNotificationPageAction); |  | 
|  605   }); |  | 
|  606 } |  | 
|  607  |  | 
|  608 function getLocalizedTexts(notification) |  | 
|  609 { |  | 
|  610   return Notification.getLocalizedTexts(notification); |  | 
|  611 } |  | 
|  612  |  | 
|  613 function getDocLinks(notification) |  | 
|  614 { |  | 
|  615   if (!notification.links) |  | 
|  616     return []; |  | 
|  617  |  | 
|  618   var docLinks = []; |  | 
|  619   notification.links.forEach(function(link) |  | 
|  620   { |  | 
|  621     docLinks.push(Utils.getDocLink(link)); |  | 
|  622   }); |  | 
|  623   return docLinks; |  | 
|  624 } |  597 } | 
|  625  |  598  | 
|  626 /** |  599 /** | 
|  627  * This function is a hack - we only know the tabId and document URL for a |  600  * This function is a hack - we only know the tabId and document URL for a | 
|  628  * message but we need to know the frame ID. Try to find it in webRequest's |  601  * message but we need to know the frame ID. Try to find it in webRequest's | 
|  629  * frame data. |  602  * frame data. | 
|  630  */ |  603  */ | 
|  631 function getFrameId(tabId, url) |  604 function getFrameId(tabId, url) | 
|  632 { |  605 { | 
|  633   if (tabId in frames) |  606   if (tabId in frames) | 
| (...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|  753 }); |  726 }); | 
|  754  |  727  | 
|  755 // Update icon if a tab changes location |  728 // Update icon if a tab changes location | 
|  756 chrome.tabs.onUpdated.addListener(function(tabId, changeInfo, tab) |  729 chrome.tabs.onUpdated.addListener(function(tabId, changeInfo, tab) | 
|  757 { |  730 { | 
|  758   chrome.tabs.sendRequest(tabId, {reqtype: "clickhide-deactivate"}) |  731   chrome.tabs.sendRequest(tabId, {reqtype: "clickhide-deactivate"}) | 
|  759   if(changeInfo.status == "loading") |  732   if(changeInfo.status == "loading") | 
|  760     refreshIconAndContextMenu(tab); |  733     refreshIconAndContextMenu(tab); | 
|  761 }); |  734 }); | 
|  762  |  735  | 
 |  736 // Refresh icon when switching tabs or windows | 
 |  737 chrome.tabs.onActivated.addListener(function(activeInfo) | 
 |  738 { | 
 |  739   refreshIconAndContextMenu(animatedIconTab); | 
 |  740   chrome.tabs.get(activeInfo.tabId, refreshIconAndContextMenu); | 
 |  741 }); | 
 |  742 chrome.windows.onFocusChanged.addListener(function(windowId) | 
 |  743 { | 
 |  744   refreshIconAndContextMenu(animatedIconTab); | 
 |  745   chrome.tabs.query({active: true, windowId: windowId}, function(tabs) | 
 |  746   { | 
 |  747     tabs.forEach(refreshIconAndContextMenu); | 
 |  748   }); | 
 |  749 }); | 
 |  750  | 
|  763 setTimeout(function() |  751 setTimeout(function() | 
|  764 { |  752 { | 
|  765   var notificationToShow = Notification.getNextToShow(); |  753   var notificationToShow = Notification.getNextToShow(); | 
|  766   if (notificationToShow) |  754   if (notificationToShow) | 
|  767     showNotification(notificationToShow); |  755     showNotification(notificationToShow); | 
|  768 }, 3 * 60 * 1000); |  756 }, 3 * 60 * 1000); | 
| LEFT | RIGHT |