| Index: lib/ui.js |
| =================================================================== |
| --- a/lib/ui.js |
| +++ b/lib/ui.js |
| @@ -454,16 +454,32 @@ let UI = exports.UI = |
| }.bind(UI) |
| }; |
| Services.obs.addObserver(documentCreationObserver, "content-document-global-created", false); |
| onShutdown.add(function() |
| { |
| Services.obs.removeObserver(documentCreationObserver, "content-document-global-created", false); |
| }); |
| + // Frame script URL has to be randomized due to caching |
| + // (see https://bugzilla.mozilla.org/show_bug.cgi?id=1051238) |
| + let frameScript = "chrome://adblockplus/content/subscribeLinkHandler.js?" + Math.random(); |
| + |
| + // Initialize subscribe link handling |
| + let callback = this.subscribeLinkClicked.bind(this); |
| + let messageManager = Cc["@mozilla.org/globalmessagemanager;1"] |
| + .getService(Ci.nsIMessageListenerManager); |
| + messageManager.loadFrameScript(frameScript, true); |
| + messageManager.addMessageListener("AdblockPlus:SubscribeLink", callback); |
| + onShutdown.add(() => { |
| + messageManager.broadcastAsyncMessage("AdblockPlus:Shutdown", frameScript); |
| + messageManager.removeDelayedFrameScript(frameScript); |
| + messageManager.removeMessageListener("AdblockPlus:SubscribeLink", callback); |
| + }); |
| + |
| // Execute first-run actions if a window is open already, otherwise it |
| // will happen in applyToWindow() when a window is opened. |
| this.firstRunActions(this.currentWindow); |
| }, |
| addToolbarButton: function() |
| { |
| let {WindowObserver} = require("windowObserver"); |
| @@ -537,17 +553,17 @@ let UI = exports.UI = |
| */ |
| firstRunDone: false, |
| /** |
| * Initializes Adblock Plus UI in a window. |
| */ |
| applyToWindow: function(/**Window*/ window, /**Boolean*/ noDelay) |
| { |
| - let {delayInitialization, isKnownWindow, getBrowser, addBrowserLocationListener, addBrowserClickListener} = require("appSupport"); |
| + let {delayInitialization, isKnownWindow, getBrowser, addBrowserLocationListener} = require("appSupport"); |
| if (window.document.documentElement.id == "CustomizeToolbarWindow" || isKnownWindow(window)) |
| { |
| // Add style processing instruction |
| let style = window.document.createProcessingInstruction("xml-stylesheet", 'class="adblockplus-node" href="chrome://adblockplus/skin/overlay.css" type="text/css"'); |
| window.document.insertBefore(style, window.document.firstChild); |
| } |
| if (!isKnownWindow(window)) |
| @@ -588,17 +604,16 @@ let UI = exports.UI = |
| window.addEventListener("popupshowing", this.onPopupShowing, false); |
| window.addEventListener("keypress", this.onKeyPress, false); |
| addBrowserLocationListener(window, function() |
| { |
| this.updateIconState(window, window.document.getElementById("abp-status")); |
| this.updateIconState(window, window.document.getElementById("abp-toolbarbutton")); |
| }.bind(this)); |
| - addBrowserClickListener(window, this.onBrowserClick.bind(this, window)); |
| let notificationPanel = window.document.getElementById("abp-notification"); |
| notificationPanel.addEventListener("command", function(event) |
| { |
| switch (event.target.id) |
| { |
| case "abp-notification-close": |
| notificationPanel.classList.add("abp-closing"); |
| @@ -623,17 +638,17 @@ let UI = exports.UI = |
| .allowSubframes = true; |
| }, |
| /** |
| * Removes Adblock Plus UI from a window. |
| */ |
| removeFromWindow: function(/**Window*/ window) |
| { |
| - let {isKnownWindow, removeBrowserLocationListeners, removeBrowserClickListeners} = require("appSupport"); |
| + let {isKnownWindow, removeBrowserLocationListeners} = require("appSupport"); |
| if (window.document.documentElement.id == "CustomizeToolbarWindow" || isKnownWindow(window)) |
| { |
| // Remove style processing instruction |
| for (let child = window.document.firstChild; child; child = child.nextSibling) |
| if (child.nodeType == child.PROCESSING_INSTRUCTION_NODE && child.data.indexOf("adblockplus-node") >= 0) |
| child.parentNode.removeChild(child); |
| } |
| @@ -658,17 +673,16 @@ let UI = exports.UI = |
| if (clone) |
| clone.parentNode.removeChild(clone); |
| } |
| } |
| window.removeEventListener("popupshowing", this.onPopupShowing, false); |
| window.removeEventListener("keypress", this.onKeyPress, false); |
| removeBrowserLocationListeners(window); |
| - removeBrowserClickListeners(window); |
| }, |
| /** |
| * The overlay information to be used when adding elements to the UI. |
| * @type Object |
| */ |
| overlay: null, |
| @@ -918,84 +932,22 @@ let UI = exports.UI = |
| }, false); |
| request.send(); |
| } |
| else |
| notifyUser(); |
| }, |
| /** |
| - * Handles clicks inside the browser's content area, will intercept clicks on |
| - * abp: links as well as links to subscribe.adblockplus.org. |
| + * Called whenever subscribeLinkHandler.js intercepts clicks on abp: links |
| + * as well as links to subscribe.adblockplus.org. |
| */ |
| - onBrowserClick: function (/**Window*/ window, /**Event*/ event) |
| + subscribeLinkClicked: function(message) |
| { |
| - // Ignore right-clicks |
| - if (event.button == 2) |
| - return; |
| - |
| - // Search the link associated with the click |
| - let link = event.target; |
| - while (!(link instanceof Ci.nsIDOMHTMLAnchorElement)) |
| - { |
| - link = link.parentNode; |
| - |
| - if (!link) |
| - return; |
| - } |
| - |
| - let queryString = null; |
| - if (link.protocol == "http:" || link.protocol == "https:") |
| - { |
| - if (link.host == "subscribe.adblockplus.org" && link.pathname == "/") |
| - queryString = link.search.substr(1); |
| - } |
| - else |
| - { |
| - // Firefox doesn't populate the "search" property for links with |
| - // non-standard URL schemes so we need to extract the query string |
| - // manually |
| - let match = /^abp:\/*subscribe\/*\?(.*)/i.exec(link.href); |
| - if (match) |
| - queryString = match[1]; |
| - } |
| - |
| - if (!queryString) |
| - return; |
| - |
| - // This is our link - make sure the browser doesn't handle it |
| - event.preventDefault(); |
| - event.stopPropagation(); |
| - |
| - // Decode URL parameters |
| - let title = null; |
| - let url = null; |
| - let mainSubscriptionTitle = null; |
| - let mainSubscriptionURL = null; |
| - for (let param of queryString.split("&")) |
| - { |
| - let parts = param.split("=", 2); |
| - if (parts.length != 2 || !/\S/.test(parts[1])) |
| - continue; |
| - switch (parts[0]) |
| - { |
| - case "title": |
| - title = decodeURIComponent(parts[1]); |
| - break; |
| - case "location": |
| - url = decodeURIComponent(parts[1]); |
| - break; |
| - case "requiresTitle": |
| - mainSubscriptionTitle = decodeURIComponent(parts[1]); |
| - break; |
| - case "requiresLocation": |
| - mainSubscriptionURL = decodeURIComponent(parts[1]); |
| - break; |
| - } |
| - } |
| + let {title, url, mainSubscriptionTitle, mainSubscriptionURL} = message.data; |
| if (!url) |
| return; |
| // Default title to the URL |
| if (!title) |
| title = url; |
| // Main subscription needs both title and URL |
| @@ -1023,17 +975,17 @@ let UI = exports.UI = |
| { |
| mainSubscriptionURL = Utils.makeURI(mainSubscriptionURL); |
| if (!mainSubscriptionURL || (mainSubscriptionURL.scheme != "http" && mainSubscriptionURL.scheme != "https" && mainSubscriptionURL.scheme != "ftp")) |
| mainSubscriptionURL = mainSubscriptionTitle = null; |
| else |
| mainSubscriptionURL = mainSubscriptionURL.spec; |
| } |
| - this.openSubscriptionDialog(window, url, title, mainSubscriptionURL, mainSubscriptionTitle); |
| + this.openSubscriptionDialog(this.currentWindow, url, title, mainSubscriptionURL, mainSubscriptionTitle); |
| }, |
| /** |
| * Opens a dialog letting the user confirm/adjust a filter subscription to |
| * be added. |
| */ |
| openSubscriptionDialog: function(/**Window*/ window, /**String*/ url, /**String*/ title, /**String*/ mainURL, /**String*/ mainTitle) |
| { |