| OLD | NEW | 
| (Empty) |  | 
 |    1 /* | 
 |    2  * This file is part of Adblock Plus <https://adblockplus.org/>, | 
 |    3  * Copyright (C) 2006-2015 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 let {startIconAnimation, stopIconAnimation} = require("icon"); | 
 |   19 let {Utils} = require("utils"); | 
 |   20 let {Notification: NotificationStorage} = require("notification"); | 
 |   21 let {stringifyURL} = require("url"); | 
 |   22  | 
 |   23 let activeNotification = null; | 
 |   24  | 
 |   25 // Chrome on Linux does not fully support chrome.notifications until version 35 | 
 |   26 // https://code.google.com/p/chromium/issues/detail?id=291485 | 
 |   27 let canUseChromeNotifications = (function() | 
 |   28 { | 
 |   29   let info = require("info"); | 
 |   30   if (info.platform == "chromium" && "notifications" in chrome) | 
 |   31   { | 
 |   32     if (navigator.platform.indexOf("Linux") == -1) | 
 |   33       return true; | 
 |   34     if (Services.vc.compare(info.applicationVersion, "35") >= 0) | 
 |   35       return true; | 
 |   36   } | 
 |   37   return false; | 
 |   38 })(); | 
 |   39  | 
 |   40 function prepareNotificationIconAndPopup() | 
 |   41 { | 
 |   42   let animateIcon = (activeNotification.type != "question"); | 
 |   43   activeNotification.onClicked = function() | 
 |   44   { | 
 |   45     if (animateIcon) | 
 |   46       stopIconAnimation(); | 
 |   47     notificationClosed(); | 
 |   48   }; | 
 |   49   if (animateIcon) | 
 |   50     startIconAnimation(activeNotification.type); | 
 |   51 } | 
 |   52  | 
 |   53 function openNotificationLinks() | 
 |   54 { | 
 |   55   if (activeNotification.links) | 
 |   56   { | 
 |   57     activeNotification.links.forEach(function(link) | 
 |   58     { | 
 |   59       ext.windows.getLastFocused(function(win) | 
 |   60       { | 
 |   61         win.openTab(Utils.getDocLink(link)); | 
 |   62       }); | 
 |   63     }); | 
 |   64   } | 
 |   65 } | 
 |   66  | 
 |   67 function notificationButtonClick(buttonIndex) | 
 |   68 { | 
 |   69   if (activeNotification.type == "question") | 
 |   70   { | 
 |   71     NotificationStorage.triggerQuestionListeners(activeNotification.id, buttonIn
     dex == 0); | 
 |   72     NotificationStorage.markAsShown(activeNotification.id); | 
 |   73     activeNotification.onClicked(); | 
 |   74   } | 
 |   75   else if (activeNotification.links && activeNotification.links[buttonIndex]) | 
 |   76   { | 
 |   77     ext.windows.getLastFocused(function(win) | 
 |   78     { | 
 |   79       win.openTab(Utils.getDocLink(activeNotification.links[buttonIndex])); | 
 |   80     }); | 
 |   81   } | 
 |   82 } | 
 |   83  | 
 |   84 function notificationClosed() | 
 |   85 { | 
 |   86   activeNotification = null; | 
 |   87 } | 
 |   88  | 
 |   89 function imgToBase64(url, callback) | 
 |   90 { | 
 |   91   let canvas = document.createElement("canvas"), | 
 |   92   ctx = canvas.getContext("2d"), | 
 |   93   img = new Image; | 
 |   94   img.src = url; | 
 |   95   img.onload = function() | 
 |   96   { | 
 |   97     canvas.height = img.height; | 
 |   98     canvas.width = img.width; | 
 |   99     ctx.drawImage(img, 0, 0); | 
 |  100     callback(canvas.toDataURL("image/png")); | 
 |  101     canvas = null; | 
 |  102   }; | 
 |  103 } | 
 |  104  | 
 |  105 function initChromeNotifications() | 
 |  106 { | 
 |  107   // Chrome hides notifications in notification center when clicked so we need t
     o clear them | 
 |  108   function clearActiveNotification(notificationId) | 
 |  109   { | 
 |  110     if (activeNotification && activeNotification.type != "question" && !("links"
      in activeNotification)) | 
 |  111       return; | 
 |  112  | 
 |  113     chrome.notifications.clear(notificationId, function(wasCleared) | 
 |  114     { | 
 |  115       if (wasCleared) | 
 |  116         notificationClosed(); | 
 |  117     }); | 
 |  118   } | 
 |  119  | 
 |  120   chrome.notifications.onButtonClicked.addListener(function(notificationId, butt
     onIndex) | 
 |  121   { | 
 |  122     notificationButtonClick(buttonIndex); | 
 |  123     clearActiveNotification(notificationId); | 
 |  124   }); | 
 |  125   chrome.notifications.onClicked.addListener(clearActiveNotification); | 
 |  126   chrome.notifications.onClosed.addListener(notificationClosed); | 
 |  127 } | 
 |  128  | 
 |  129 let showNextNotification = | 
 |  130 /** | 
 |  131  * Shows the next notification from the queue if any. | 
 |  132  * | 
 |  133  * @param {URL} [url] URL to match notifications to | 
 |  134  */ | 
 |  135 exports.showNextNotification = function(url) | 
 |  136 { | 
 |  137   let notification = NotificationStorage.getNextToShow(url && stringifyURL(url))
     ; | 
 |  138   if (!notification || activeNotification && activeNotification.id == notificati
     on.id) | 
 |  139     return; | 
 |  140  | 
 |  141   activeNotification = notification; | 
 |  142   if (activeNotification.type == "critical" || activeNotification.type == "quest
     ion") | 
 |  143   { | 
 |  144     let texts = NotificationStorage.getLocalizedTexts(notification); | 
 |  145     let title = texts.title || ""; | 
 |  146     let message = texts.message ? texts.message.replace(/<\/?(a|strong)>/g, "") 
     : ""; | 
 |  147     let iconUrl = ext.getURL("icons/detailed/abp-128.png"); | 
 |  148     let hasLinks = activeNotification.links && activeNotification.links.length >
      0; | 
 |  149  | 
 |  150     if (canUseChromeNotifications) | 
 |  151     { | 
 |  152       let opts = { | 
 |  153         type: "basic", | 
 |  154         title: title, | 
 |  155         message: message, | 
 |  156         buttons: [], | 
 |  157         priority: 2 // We use the highest priority to prevent the notification f
     rom closing automatically | 
 |  158       }; | 
 |  159       if (activeNotification.type == "question") | 
 |  160       { | 
 |  161         opts.buttons.push({title: ext.i18n.getMessage("overlay_notification_butt
     on_yes")}); | 
 |  162         opts.buttons.push({title: ext.i18n.getMessage("overlay_notification_butt
     on_no")}); | 
 |  163       } | 
 |  164       else | 
 |  165       { | 
 |  166         let regex = /<a>(.*?)<\/a>/g; | 
 |  167         let plainMessage = texts.message || ""; | 
 |  168         let match; | 
 |  169         while (match = regex.exec(plainMessage)) | 
 |  170           opts.buttons.push({title: match[1]}); | 
 |  171       } | 
 |  172  | 
 |  173       imgToBase64(iconUrl, function(iconData) | 
 |  174       { | 
 |  175         opts["iconUrl"] = iconData; | 
 |  176         chrome.notifications.create("", opts, function() {}); | 
 |  177       }); | 
 |  178     } | 
 |  179     else if ("Notification" in window && activeNotification.type != "question") | 
 |  180     { | 
 |  181       if (hasLinks) | 
 |  182         message += " " + ext.i18n.getMessage("notification_without_buttons"); | 
 |  183  | 
 |  184       imgToBase64(iconUrl, function(iconData) | 
 |  185       { | 
 |  186         let notification = new Notification( | 
 |  187           title, | 
 |  188           { | 
 |  189             lang: Utils.appLocale, | 
 |  190             dir: ext.i18n.getMessage("@@bidi_dir"), | 
 |  191             body: message, | 
 |  192             icon: iconData | 
 |  193           } | 
 |  194         ); | 
 |  195  | 
 |  196         notification.addEventListener("click", openNotificationLinks); | 
 |  197         notification.addEventListener("close", notificationClosed); | 
 |  198       }); | 
 |  199     } | 
 |  200     else | 
 |  201     { | 
 |  202       let message = title + "\n" + message; | 
 |  203       if (hasLinks) | 
 |  204         message += "\n\n" + ext.i18n.getMessage("notification_with_buttons"); | 
 |  205  | 
 |  206       let approved = confirm(message); | 
 |  207       if (activeNotification.type == "question") | 
 |  208         notificationButtonClick(approved ? 0 : 1); | 
 |  209       else if (approved) | 
 |  210         openNotificationLinks(); | 
 |  211     } | 
 |  212   } | 
 |  213   prepareNotificationIconAndPopup(); | 
 |  214 }; | 
 |  215  | 
 |  216 setTimeout(showNextNotification, 3 * 60 * 1000); | 
| OLD | NEW |