Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code

Unified Diff: lib/child/requestNotifier.js

Issue 29329779: Issue 3258 - Blockable items: restore item flashing functionality (Closed)
Patch Set: Better handling of dead objects Created Nov. 5, 2015, 11:06 p.m.
Use n/p to move between diff chunks; N/P to move between comments.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: lib/child/requestNotifier.js
===================================================================
--- a/lib/child/requestNotifier.js
+++ b/lib/child/requestNotifier.js
@@ -16,33 +16,36 @@
*/
/**
* @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 {Flasher} = require("child/flasher");
let nodeData = new WeakMap();
let windowStats = new WeakMap();
let requestEntryMaxId = 0;
/**
* Active RequestNotifier instances by their ID
* @type Map.<number,RequestNotifier>
*/
let notifiers = new Map();
addMessageListener("AdblockPlus:StartWindowScan", onStartScan);
addMessageListener("AdblockPlus:ShutdownNotifier", onNotifierShutdown);
+addMessageListener("AdblockPlus:FlashNodes", onFlashNodes);
onShutdown.add(() => {
removeMessageListener("AdblockPlus:StartWindowScan", onStartScan);
removeMessageListener("AdblockPlus:ShutdownNotifier", onNotifierShutdown);
+ removeMessageListener("AdblockPlus:FlashNodes", onFlashNodes);
});
function onStartScan(message)
{
let {notifierID, outerWindowID} = message.data;
let window = Services.wm.getOuterWindowWithId(outerWindowID);
if (window)
new RequestNotifier(window, notifierID);
@@ -50,28 +53,37 @@ function onStartScan(message)
function onNotifierShutdown(message)
{
let notifier = notifiers.get(message.data);
if (notifier)
notifier.shutdown();
}
+function onFlashNodes(message)
+{
+ let {notifierID, requests, scrollToItem} = message.data;
+ let notifier = notifiers.get(notifierID);
+ if (notifier)
+ notifier.flashNodes(requests, scrollToItem);
+}
+
/**
* 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 {Integer} id Parent notifier ID to be messaged
*/
function RequestNotifier(window, notifierID)
{
this.window = window;
this.id = notifierID;
notifiers.set(this.id, this);
+ this.nodes = new Map();
this.startScan(window);
}
exports.RequestNotifier = RequestNotifier;
RequestNotifier.prototype =
{
/**
* Parent notifier ID to be messaged
@@ -81,31 +93,42 @@ RequestNotifier.prototype =
/**
* The window this notifier is associated with.
* @type Window
*/
window: null,
/**
+ * Nodes associated with a particular request ID.
+ * @type Map.<number,Node>
+ */
+ nodes: null,
+
+ /**
* 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.nodes;
+ this.stopFlashing();
notifiers.delete(this.id);
},
/**
* Notifies the parent about a new request.
+ * @param {Node} node DOM node that the request is associated with
* @param {Object} entry
*/
- notifyListener: function(entry)
+ notifyListener: function(node, entry)
{
+ if (this.nodes)
+ this.nodes.set(entry.id, node);
sendAsyncMessage("AdblockPlus:FoundNodeData", {
notifierID: this.id,
data: entry
});
},
onComplete: function()
{
@@ -131,17 +154,17 @@ RequestNotifier.prototype =
{
if (!this.window)
return;
let node = walker.currentNode;
let data = nodeData.get(node);
if (typeof data != "undefined")
for (let k in data)
- this.notifyListener(data[k]);
+ this.notifyListener(node, 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]);
@@ -153,16 +176,52 @@ RequestNotifier.prototype =
this.onComplete();
}
}
}.bind(this);
// Process each node in a separate event to allow other events to process
this.eventsPosted++;
Utils.runAsync(process);
+ },
+
+ /**
+ * Makes the nodes associated with the given requests blink.
+ * @param {number[]} requests list of request IDs that were previously
+ * reported by this notifier.
+ * @param {Boolean} scrollToItem if true, scroll to first node
+ */
+ flashNodes: function(requests, scrollToItem)
+ {
+ this.stopFlashing();
+
+ let nodes = [];
+ for (let id of requests)
+ {
+ if (!this.nodes.has(id))
+ continue;
+
+ let node = this.nodes.get(id);
+ if (Cu.isDeadWrapper(node))
+ this.nodes.delete(node);
+ else if (node.nodeType == Ci.nsIDOMNode.ELEMENT_NODE)
+ nodes.push(node);
+ }
+ if (nodes.length)
+ this.flasher = new Flasher(nodes, scrollToItem);
+ },
+
+ /**
+ * Stops flashing nodes after a previous flashNodes() call.
+ */
+ stopFlashing: function()
+ {
+ if (this.flasher)
+ this.flasher.stop();
+ this.flasher = 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"
@@ -218,10 +277,10 @@ RequestNotifier.addNodeData = function(n
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(entry);
+ notifier.notifyListener(node, entry);
}

Powered by Google App Engine
This is Rietveld