/* * This file is part of Adblock Plus , * Copyright (C) 2006-2017 eyeo GmbH * * Adblock Plus is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License version 3 as * published by the Free Software Foundation. * * Adblock Plus is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Adblock Plus. If not, see . */ /** * @fileOverview Stores Adblock Plus data to be attached to a window. */ let {port} = require("messaging"); let requestNotifierMaxId = 0; /** * Active RequestNotifier instances by their ID * @type Map. */ let notifiers = new Map(); port.on("foundNodeData", ({notifierID, data}, sender) => { let notifier = notifiers.get(notifierID); if (notifier) notifier.notifyListener(data); }); port.on("scanComplete", (notifierID, sender) => { let notifier = notifiers.get(notifierID); if (notifier) notifier.onComplete(); }); /** * 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 {Integer} outerWindowID ID of the 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 */ function RequestNotifier(outerWindowID, listener, listenerObj) { this.listener = listener; this.listenerObj = listenerObj || null; this.id = ++requestNotifierMaxId; notifiers.set(this.id, this); port.emit("startWindowScan", { notifierID: this.id, outerWindowID: outerWindowID }); } exports.RequestNotifier = RequestNotifier; RequestNotifier.prototype = { /** * The unique ID of this notifier. * @type Integer */ id: 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() { notifiers.delete(this.id); port.emit("shutdownNotifier", this.id); }, /** * Notifies listener about a new request. * @param {Object} entry */ notifyListener: function(entry) { this.listener.call(this.listenerObj, entry, this.scanComplete); }, onComplete: function() { this.scanComplete = true; this.notifyListener(null); }, /** * 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) { if (!requests) requests = []; port.emit("flashNodes", { notifierID: this.id, requests, scrollToItem }); }, /** * Attempts to calculate the size of the nodes associated with the requests. * @param {number[]} requests list of request IDs that were previously * reported by this notifier. * @param {Function} callback function to be called with two parameters (x,y) */ retrieveNodeSize: function(requests, callback) { if (!requests) requests = []; port.emitWithResponse("retrieveNodeSize", { notifierID: this.id, requests }).then(callback); }, /** * Stores the nodes associated with the requests and generates a unique ID * for them that can be used with Policy.refilterNodes(). Note that * Policy.deleteNodes() always has to be called to release the memory. * @param {number[]} requests list of request IDs that were previously * reported by this notifier. * @param {Function} callback function to be called with the nodes ID. */ storeNodesForEntries: function(requests, callback) { if (!requests) requests = []; port.emitWithResponse("storeNodesForEntries", { notifierID: this.id, requests }).then(callback); } }; /** * Associates a piece of data with a particular window. * @param {number} outerWindowID the ID of the window * @static */ RequestNotifier.storeWindowData = function(outerWindowID, data) { port.emit("storeWindowData", { outerWindowID, data }); }; /** * Retrieves a piece of data previously associated with the window by calling * storeWindowData. * @param {number} outerWindowID the ID of the window * @param {Function} callback function to be called with the data. * @static */ RequestNotifier.retrieveWindowData = function(outerWindowID, callback) { port.emitWithResponse("retrieveWindowData", outerWindowID).then(callback); }; /** * Retrieves the statistics for a window. * @param {number} outerWindowID the ID of the window * @param {Function} callback the callback to be called with the resulting * object (object properties will be items, blocked, * whitelisted, hidden, filters) or null. */ RequestNotifier.getWindowStatistics = function(outerWindowID, callback) { port.emitWithResponse("retrieveWindowStats", outerWindowID).then(callback); };