Index: lib/child/requestNotifier.js |
=================================================================== |
copy from lib/requestNotifier.js |
copy to lib/child/requestNotifier.js |
--- a/lib/requestNotifier.js |
+++ b/lib/child/requestNotifier.js |
@@ -13,107 +13,108 @@ |
* |
* You should have received a copy of the GNU General Public License |
* along with Adblock Plus. If not, see <http://www.gnu.org/licenses/>. |
*/ |
/** |
* @fileOverview Stores Adblock Plus data to be attached to a window. |
*/ |
+let {Services} = Cu.import("resource://gre/modules/Services.jsm", {}); |
let {Utils} = require("utils"); |
let nodeData = new WeakMap(); |
let windowStats = new WeakMap(); |
-let windowSelection = new WeakMap(); |
-let requestNotifierMaxId = 0; |
let requestEntryMaxId = 0; |
/** |
* Active RequestNotifier instances by their ID |
* @type Map |
*/ |
let notifiers = new Map(); |
+addMessageListener("AdblockPlus:StartWindowScan", onStartScan); |
+addMessageListener("AdblockPlus:ShutdownNotifier", onNotifierShutdown); |
+ |
+onShutdown.add(() => { |
+ removeMessageListener("AdblockPlus:StartWindowScan", onStartScan); |
+ removeMessageListener("AdblockPlus:ShutdownNotifier", onNotifierShutdown); |
+}); |
+ |
+function onStartScan(message) |
+{ |
+ let {notifierID, outerWindowID} = message.data; |
+ let window = Services.wm.getOuterWindowWithId(outerWindowID); |
+ if (window) |
+ new RequestNotifier(window, notifierID); |
+} |
+ |
+function onNotifierShutdown(message) |
+{ |
+ let notifier = notifiers.get(message.data); |
+ if (notifier) |
+ notifier.shutdown(); |
+} |
+ |
/** |
* Creates a notifier object for a particular window. After creation the window |
* will first be scanned for previously saved requests. Once that scan is |
* complete only new requests for this window will be reported. |
- * @param {Window} wnd window to attach the notifier to |
- * @param {Function} listener listener to be called whenever a new request is found |
- * @param {Object} [listenerObj] "this" pointer to be used when calling the listener |
+ * @param {Window} window window to attach the notifier to |
+ * @param {Integer} notifierID Parent notifier ID to be messaged |
*/ |
-function RequestNotifier(wnd, listener, listenerObj) |
+function RequestNotifier(window, notifierID) |
{ |
- this.window = wnd; |
- this.listener = listener; |
- this.listenerObj = listenerObj || null; |
- this.id = ++requestNotifierMaxId; |
+ this.window = window; |
+ this.id = notifierID; |
notifiers.set(this.id, this); |
- if (wnd) |
- this.startScan(wnd); |
- else |
- this.scanComplete = true; |
+ this.startScan(window); |
} |
exports.RequestNotifier = RequestNotifier; |
RequestNotifier.prototype = |
{ |
/** |
- * The unique ID of this notifier. |
+ * Parent notifier ID to be messaged |
* @type Integer |
*/ |
id: null, |
/** |
* The window this notifier is associated with. |
* @type Window |
*/ |
window: null, |
/** |
- * The listener to be called when a new request is found. |
- * @type Function |
- */ |
- listener: null, |
- |
- /** |
- * "this" pointer to be used when calling the listener. |
- * @type Object |
- */ |
- listenerObj: null, |
- |
- /** |
- * Will be set to true once the initial window scan is complete. |
- * @type Boolean |
- */ |
- scanComplete: false, |
- |
- /** |
* Shuts down the notifier once it is no longer used. The listener |
* will no longer be called after that. |
*/ |
shutdown: function() |
{ |
delete this.window; |
- delete this.listener; |
- delete this.listenerObj; |
- |
notifiers.delete(this.id); |
}, |
/** |
- * Notifies listener about a new request. |
- * @param {Window} wnd |
- * @param {Node} node |
+ * Notifies the parent about a new request. |
* @param {Object} entry |
*/ |
- notifyListener: function(wnd, node, entry) |
+ notifyListener: function(entry) |
{ |
- this.listener.call(this.listenerObj, wnd, node, entry, this.scanComplete); |
+ sendAsyncMessage("AdblockPlus:FoundNodeData", { |
+ notifierID: this.id, |
+ data: entry |
+ }); |
+ }, |
+ |
+ onComplete: function() |
+ { |
+ sendAsyncMessage("AdblockPlus:ScanComplete", this.id); |
}, |
/** |
* Number of currently posted scan events (will be 0 when the scan finishes |
* running). |
*/ |
eventsPosted: 0, |
@@ -123,77 +124,66 @@ RequestNotifier.prototype = |
*/ |
startScan: function(wnd) |
{ |
let doc = wnd.document; |
let walker = doc.createTreeWalker(doc, Ci.nsIDOMNodeFilter.SHOW_ELEMENT, null, false); |
let process = function() |
{ |
- if (!this.listener) |
+ // Don't do anything if the notifier was shut down already. |
+ if (!this.window) |
return; |
let node = walker.currentNode; |
let data = nodeData.get(node); |
if (typeof data != "undefined") |
for (let k in data) |
- this.notifyListener(wnd, node, data[k]); |
+ this.notifyListener(data[k]); |
if (walker.nextNode()) |
Utils.runAsync(process); |
else |
{ |
// Done with the current window, start the scan for its frames |
for (let i = 0; i < wnd.frames.length; i++) |
this.startScan(wnd.frames[i]); |
this.eventsPosted--; |
if (!this.eventsPosted) |
{ |
this.scanComplete = true; |
- this.notifyListener(wnd, null, null); |
+ this.onComplete(); |
} |
} |
}.bind(this); |
// Process each node in a separate event to allow other events to process |
this.eventsPosted++; |
Utils.runAsync(process); |
} |
}; |
-RequestNotifier.storeSelection = function(/**Window*/ wnd, /**String*/ selection) |
-{ |
- windowSelection.set(wnd.document, selection); |
-}; |
-RequestNotifier.getSelection = function(/**Window*/ wnd) /**String*/ |
-{ |
- if (windowSelection.has(wnd.document)) |
- return windowSelection.get(wnd.document); |
- else |
- return null; |
-}; |
- |
/** |
* Attaches request data to a DOM node. |
* @param {Node} node node to attach data to |
* @param {Window} topWnd top-level window the node belongs to |
* @param {String} contentType request type, e.g. "IMAGE" |
* @param {String} docDomain domain of the document that initiated the request |
* @param {Boolean} thirdParty will be true if a third-party server has been requested |
* @param {String} location the address that has been requested |
* @param {Filter} filter filter applied to the request or null if none |
*/ |
RequestNotifier.addNodeData = function(/**Node*/ node, /**Window*/ topWnd, /**String*/ contentType, /**String*/ docDomain, /**Boolean*/ thirdParty, /**String*/ location, /**Filter*/ filter) |
{ |
let entry = { |
id: ++requestEntryMaxId, |
type: contentType, |
docDomain, thirdParty, location, filter |
- } |
+ }; |
let existingData = nodeData.get(node); |
if (typeof existingData == "undefined") |
{ |
existingData = {}; |
nodeData.set(node, existingData); |
} |
@@ -229,68 +219,10 @@ RequestNotifier.addNodeData = function(/ |
stats.filters[filter.text]++; |
else |
stats.filters[filter.text] = 1; |
} |
// Notify listeners |
for (let notifier of notifiers.values()) |
if (!notifier.window || notifier.window == topWnd) |
- notifier.notifyListener(topWnd, node, entry); |
+ notifier.notifyListener(entry); |
} |
- |
-/** |
- * Retrieves the statistics for a window. |
- * @result {Object} Object with the properties items, blocked, whitelisted, hidden, filters containing statistics for the window (might be null) |
- */ |
-RequestNotifier.getWindowStatistics = function(/**Window*/ wnd) |
-{ |
- if (windowStats.has(wnd.document)) |
- return windowStats.get(wnd.document); |
- else |
- return null; |
-} |
- |
-/** |
- * Retrieves the request data associated with a DOM node. |
- * @param {Node} node |
- * @param {Boolean} noParent if missing or false, the search will extend to the parent nodes until one is found that has data associated with it |
- * @param {Integer} [type] request type to be looking for |
- * @param {String} [location] request location to be looking for |
- * @result {[Node, Object]} |
- * @static |
- */ |
-RequestNotifier.getDataForNode = function(node, noParent, type, location) |
-{ |
- while (node) |
- { |
- let data = nodeData.get(node); |
- if (typeof data != "undefined") |
- { |
- let entry = null; |
- // Look for matching entry |
- for (let k in data) |
- { |
- if ((!entry || entry.id < data[k].id) && |
- (typeof type == "undefined" || data[k].type == type) && |
- (typeof location == "undefined" || data[k].location == location)) |
- { |
- entry = data[k]; |
- } |
- } |
- if (entry) |
- return [node, entry]; |
- } |
- |
- // If we don't have any match on this node then maybe its parent will do |
- if ((typeof noParent != "boolean" || !noParent) && |
- node.parentNode instanceof Ci.nsIDOMElement) |
- { |
- node = node.parentNode; |
- } |
- else |
- { |
- node = null; |
- } |
- } |
- |
- return null; |
-}; |