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) |
{ |