summaryrefslogtreecommitdiff
path: root/data/extensions/spyblock@gnu.org/lib/messageResponder.js
diff options
context:
space:
mode:
Diffstat (limited to 'data/extensions/spyblock@gnu.org/lib/messageResponder.js')
-rw-r--r--data/extensions/spyblock@gnu.org/lib/messageResponder.js515
1 files changed, 383 insertions, 132 deletions
diff --git a/data/extensions/spyblock@gnu.org/lib/messageResponder.js b/data/extensions/spyblock@gnu.org/lib/messageResponder.js
index 0f5ff0e..5dfc2e9 100644
--- a/data/extensions/spyblock@gnu.org/lib/messageResponder.js
+++ b/data/extensions/spyblock@gnu.org/lib/messageResponder.js
@@ -1,6 +1,6 @@
/*
* This file is part of Adblock Plus <https://adblockplus.org/>,
- * Copyright (C) 2006-2015 Eyeo GmbH
+ * 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
@@ -15,166 +15,417 @@
* along with Adblock Plus. If not, see <http://www.gnu.org/licenses/>.
*/
+/* globals require */
+
+"use strict";
+
(function(global)
{
- if (!global.ext)
- global.ext = require("ext_background");
-
- var Utils = require("utils").Utils;
- var FilterStorage = require("filterStorage").FilterStorage;
- var FilterNotifier = require("filterNotifier").FilterNotifier;
- var defaultMatcher = require("matcher").defaultMatcher;
- var BlockingFilter = require("filterClasses").BlockingFilter;
- var Synchronizer = require("synchronizer").Synchronizer;
-
- var subscriptionClasses = require("subscriptionClasses");
- var Subscription = subscriptionClasses.Subscription;
- var DownloadableSubscription = subscriptionClasses.DownloadableSubscription;
- var SpecialSubscription = subscriptionClasses.SpecialSubscription;
-
- var subscriptionKeys = ["disabled", "homepage", "lastSuccess", "title", "url", "downloadStatus"];
- function convertSubscription(subscription)
- {
- var result = {};
- for (var i = 0; i < subscriptionKeys.length; i++)
- result[subscriptionKeys[i]] = subscription[subscriptionKeys[i]]
- return result;
- }
+ let ext = global.ext || require("ext_background");
+
+ const {port} = require("messaging");
+ const {Prefs} = require("prefs");
+ const {Utils} = require("utils");
+ const {FilterStorage} = require("filterStorage");
+ const {FilterNotifier} = require("filterNotifier");
+ const {defaultMatcher} = require("matcher");
+ const {ElemHideEmulation} = require("elemHideEmulation");
+ const {Notification: NotificationStorage} = require("notification");
+
+ const {Filter, BlockingFilter, RegExpFilter} = require("filterClasses");
+ const {Synchronizer} = require("synchronizer");
- var changeListeners = null;
- var messageTypes = {
- "app": "app.listen",
- "filter": "filters.listen",
- "subscription": "subscriptions.listen"
- };
+ const info = require("info");
+ const {Subscription,
+ DownloadableSubscription,
+ SpecialSubscription} = require("subscriptionClasses");
- function onFilterChange(action)
+ // Some modules doesn't exist on Firefox. Moreover,
+ // require() throws an exception on Firefox in that case.
+ // However, try/catch causes the whole function to to be
+ // deoptimized on V8. So we wrap it into another function.
+ function tryRequire(module)
{
- var parts = action.split(".", 2);
- var type;
- if (parts.length == 1)
+ try
{
- type = "app";
- action = parts[0];
+ return require(module);
}
- else
+ catch (e)
+ {
+ return null;
+ }
+ }
+
+ function convertObject(keys, obj)
+ {
+ let result = {};
+ for (let key of keys)
{
- type = parts[0];
- action = parts[1];
+ if (key in obj)
+ result[key] = obj[key];
}
+ return result;
+ }
+
+ function convertSubscription(subscription)
+ {
+ let obj = convertObject(["disabled", "downloadStatus", "homepage",
+ "lastDownload", "title", "url"], subscription);
+ obj.isDownloading = Synchronizer.isExecuting(subscription.url);
+ return obj;
+ }
- if (!messageTypes.hasOwnProperty(type))
+ let convertFilter = convertObject.bind(null, ["text"]);
+
+ let changeListeners = new ext.PageMap();
+ let listenedPreferences = Object.create(null);
+ let listenedFilterChanges = Object.create(null);
+ let messageTypes = new Map([
+ ["app", "app.respond"],
+ ["filter", "filters.respond"],
+ ["pref", "prefs.respond"],
+ ["subscription", "subscriptions.respond"]
+ ]);
+
+ function sendMessage(type, action, ...args)
+ {
+ let pages = changeListeners.keys();
+ if (pages.length == 0)
return;
- var args = Array.prototype.slice.call(arguments, 1).map(function(arg)
+ let convertedArgs = [];
+ for (let arg of args)
{
if (arg instanceof Subscription)
- return convertSubscription(arg);
+ convertedArgs.push(convertSubscription(arg));
+ else if (arg instanceof Filter)
+ convertedArgs.push(convertFilter(arg));
else
- return arg;
- });
+ convertedArgs.push(arg);
+ }
- var pages = changeListeners.keys();
- for (var i = 0; i < pages.length; i++)
+ for (let page of pages)
{
- var filters = changeListeners.get(pages[i]);
- if (filters[type] && filters[type].indexOf(action) >= 0)
+ let filters = changeListeners.get(page);
+ let actions = filters[type];
+ if (actions && actions.indexOf(action) != -1)
{
- pages[i].sendMessage({
- type: messageTypes[type],
- action: action,
- args: args
+ page.sendMessage({
+ type: messageTypes.get(type),
+ action,
+ args: convertedArgs
});
}
}
- };
+ }
- global.ext.onMessage.addListener(function(message, sender, callback)
+ function addFilterListeners(type, actions)
{
- switch (message.type)
+ for (let action of actions)
{
- case "app.get":
- if (message.what == "issues")
- {
- var info = require("info");
- callback({
- seenDataCorruption: "seenDataCorruption" in global ? global.seenDataCorruption : false,
- filterlistsReinitialized: "filterlistsReinitialized" in global ? global.filterlistsReinitialized : false,
- legacySafariVersion: (info.platform == "safari" && (
- Services.vc.compare(info.platformVersion, "6.0") < 0 || // beforeload breaks websites in Safari 5
- Services.vc.compare(info.platformVersion, "6.1") == 0 || // extensions are broken in 6.1 and 7.0
- Services.vc.compare(info.platformVersion, "7.0") == 0))
- });
- }
- else if (message.what == "doclink")
- callback(Utils.getDocLink(message.link));
- else if (message.what == "localeInfo")
- {
- var bidiDir;
- if ("chromeRegistry" in Utils)
- bidiDir = Utils.chromeRegistry.isLocaleRTL("adblockplus") ? "rtl" : "ltr";
- else
- bidiDir = ext.i18n.getMessage("@@bidi_dir");
-
- callback({locale: Utils.appLocale, bidiDir: bidiDir});
- }
- else
- callback(null);
- break;
- case "app.open":
- if (message.what == "options")
- ext.showOptions();
- break;
- case "subscriptions.get":
- var subscriptions = FilterStorage.subscriptions.filter(function(s)
+ let name;
+ if (type == "filter" && action == "loaded")
+ name = "load";
+ else
+ name = type + "." + action;
+
+ if (!(name in listenedFilterChanges))
+ {
+ listenedFilterChanges[name] = null;
+ FilterNotifier.on(name, (...args) =>
{
- if (message.ignoreDisabled && s.disabled)
- return false;
- if (s instanceof DownloadableSubscription && message.downloadable)
- return true;
- if (s instanceof SpecialSubscription && message.special)
- return true;
- return false;
+ sendMessage(type, action, ...args);
});
- callback(subscriptions.map(convertSubscription));
- break;
- case "filters.blocked":
- var filter = defaultMatcher.matchesAny(message.url, message.requestType, message.docDomain, message.thirdParty);
- callback(filter instanceof BlockingFilter);
- break;
- case "subscriptions.toggle":
- var subscription = Subscription.fromURL(message.url);
- if (subscription.url in FilterStorage.knownSubscriptions && !subscription.disabled)
- FilterStorage.removeSubscription(subscription);
- else
- {
- subscription.disabled = false;
- subscription.title = message.title;
- subscription.homepage = message.homepage;
- FilterStorage.addSubscription(subscription);
- if (!subscription.lastDownload)
- Synchronizer.execute(subscription);
- }
- break;
- case "subscriptions.listen":
- if (!changeListeners)
+ }
+ }
+ }
+
+ function getListenerFilters(page)
+ {
+ let listenerFilters = changeListeners.get(page);
+ if (!listenerFilters)
+ {
+ listenerFilters = Object.create(null);
+ changeListeners.set(page, listenerFilters);
+ }
+ return listenerFilters;
+ }
+
+ port.on("app.get", (message, sender) =>
+ {
+ if (message.what == "issues")
+ {
+ let subscriptionInit = tryRequire("subscriptionInit");
+ let result = subscriptionInit ? subscriptionInit.reinitialized : false;
+ return {filterlistsReinitialized: result};
+ }
+
+ if (message.what == "doclink")
+ return Utils.getDocLink(message.link);
+
+ if (message.what == "localeInfo")
+ {
+ let bidiDir;
+ if ("chromeRegistry" in Utils)
+ {
+ let isRtl = Utils.chromeRegistry.isLocaleRTL("adblockplus");
+ bidiDir = isRtl ? "rtl" : "ltr";
+ }
+ else
+ bidiDir = ext.i18n.getMessage("@@bidi_dir");
+
+ return {locale: Utils.appLocale, bidiDir};
+ }
+
+ if (message.what == "features")
+ {
+ return {
+ devToolsPanel: info.platform == "chromium"
+ };
+ }
+
+ return info[message.what];
+ });
+
+ port.on("app.listen", (message, sender) =>
+ {
+ getListenerFilters(sender.page).app = message.filter;
+ });
+
+ port.on("app.open", (message, sender) =>
+ {
+ if (message.what == "options")
+ ext.showOptions();
+ });
+
+ port.on("filters.add", (message, sender) =>
+ {
+ let result = require("filterValidation").parseFilter(message.text);
+ let errors = [];
+ if (result.error)
+ errors.push(result.error.toString());
+ else if (result.filter)
+ FilterStorage.addFilter(result.filter);
+
+ return errors;
+ });
+
+ port.on("filters.blocked", (message, sender) =>
+ {
+ let filter = defaultMatcher.matchesAny(message.url,
+ RegExpFilter.typeMap[message.requestType], message.docDomain,
+ message.thirdParty);
+
+ return filter instanceof BlockingFilter;
+ });
+
+ port.on("filters.get", (message, sender) =>
+ {
+ if (message.what == "elemhideemulation")
+ {
+ let filters = [];
+ const {checkWhitelisted} = require("whitelisting");
+
+ if (Prefs.enabled && !checkWhitelisted(sender.page, sender.frame,
+ RegExpFilter.typeMap.DOCUMENT |
+ RegExpFilter.typeMap.ELEMHIDE))
+ {
+ let {hostname} = sender.frame.url;
+ filters = ElemHideEmulation.getRulesForDomain(hostname);
+ filters = filters.map((filter) =>
{
- changeListeners = new global.ext.PageMap();
- FilterNotifier.addListener(onFilterChange);
- }
+ return {
+ selector: filter.selector,
+ text: filter.text
+ };
+ });
+ }
+ return filters;
+ }
- var filters = changeListeners.get(sender.page);
- if (!filters)
+ let subscription = Subscription.fromURL(message.subscriptionUrl);
+ if (!subscription)
+ return [];
+
+ return subscription.filters.map(convertFilter);
+ });
+
+ port.on("filters.importRaw", (message, sender) =>
+ {
+ let result = require("filterValidation").parseFilters(message.text);
+ let errors = [];
+ for (let error of result.errors)
+ {
+ if (error.type != "unexpected-filter-list-header")
+ errors.push(error.toString());
+ }
+
+ if (errors.length > 0)
+ return errors;
+
+ let seenFilter = Object.create(null);
+ for (let filter of result.filters)
+ {
+ FilterStorage.addFilter(filter);
+ seenFilter[filter.text] = null;
+ }
+
+ if (!message.removeExisting)
+ return errors;
+
+ for (let subscription of FilterStorage.subscriptions)
+ {
+ if (!(subscription instanceof SpecialSubscription))
+ continue;
+
+ for (let j = subscription.filters.length - 1; j >= 0; j--)
+ {
+ let filter = subscription.filters[j];
+ if (/^@@\|\|([^/:]+)\^\$document$/.test(filter.text))
+ continue;
+
+ if (!(filter.text in seenFilter))
+ FilterStorage.removeFilter(filter);
+ }
+ }
+
+ return errors;
+ });
+
+ port.on("filters.listen", (message, sender) =>
+ {
+ getListenerFilters(sender.page).filter = message.filter;
+ addFilterListeners("filter", message.filter);
+ });
+
+ port.on("filters.remove", (message, sender) =>
+ {
+ let filter = Filter.fromText(message.text);
+ let subscription = null;
+ if (message.subscriptionUrl)
+ subscription = Subscription.fromURL(message.subscriptionUrl);
+
+ if (!subscription)
+ FilterStorage.removeFilter(filter);
+ else
+ FilterStorage.removeFilter(filter, subscription, message.index);
+ });
+
+ port.on("prefs.get", (message, sender) =>
+ {
+ return Prefs[message.key];
+ });
+
+ port.on("prefs.listen", (message, sender) =>
+ {
+ getListenerFilters(sender.page).pref = message.filter;
+ for (let preference of message.filter)
+ {
+ if (!(preference in listenedPreferences))
+ {
+ listenedPreferences[preference] = null;
+ Prefs.on(preference, () =>
{
- filters = Object.create(null);
- changeListeners.set(sender.page, filters);
- }
-
- if (message.filter)
- filters.subscription = message.filter;
- else
- delete filters.subscription;
- break;
+ sendMessage("pref", preference, Prefs[preference]);
+ });
+ }
+ }
+ });
+
+ port.on("prefs.toggle", (message, sender) =>
+ {
+ if (message.key == "notifications_ignoredcategories")
+ NotificationStorage.toggleIgnoreCategory("*");
+ else
+ Prefs[message.key] = !Prefs[message.key];
+ });
+
+ port.on("subscriptions.add", (message, sender) =>
+ {
+ let subscription = Subscription.fromURL(message.url);
+ if ("title" in message)
+ subscription.title = message.title;
+ if ("homepage" in message)
+ subscription.homepage = message.homepage;
+
+ if (message.confirm)
+ {
+ ext.showOptions(() =>
+ {
+ sendMessage("app", "addSubscription", subscription);
+ });
+ }
+ else
+ {
+ subscription.disabled = false;
+ FilterStorage.addSubscription(subscription);
+
+ if (subscription instanceof DownloadableSubscription &&
+ !subscription.lastDownload)
+ Synchronizer.execute(subscription);
+ }
+ });
+
+ port.on("subscriptions.get", (message, sender) =>
+ {
+ let subscriptions = FilterStorage.subscriptions.filter((s) =>
+ {
+ if (message.ignoreDisabled && s.disabled)
+ return false;
+ if (s instanceof DownloadableSubscription && message.downloadable)
+ return true;
+ if (s instanceof SpecialSubscription && message.special)
+ return true;
+ return false;
+ });
+
+ return subscriptions.map(convertSubscription);
+ });
+
+ port.on("subscriptions.listen", (message, sender) =>
+ {
+ getListenerFilters(sender.page).subscription = message.filter;
+ addFilterListeners("subscription", message.filter);
+ });
+
+ port.on("subscriptions.remove", (message, sender) =>
+ {
+ let subscription = Subscription.fromURL(message.url);
+ if (subscription.url in FilterStorage.knownSubscriptions)
+ FilterStorage.removeSubscription(subscription);
+ });
+
+ port.on("subscriptions.toggle", (message, sender) =>
+ {
+ let subscription = Subscription.fromURL(message.url);
+ if (subscription.url in FilterStorage.knownSubscriptions)
+ {
+ if (subscription.disabled || message.keepInstalled)
+ subscription.disabled = !subscription.disabled;
+ else
+ FilterStorage.removeSubscription(subscription);
+ }
+ else
+ {
+ subscription.disabled = false;
+ subscription.title = message.title;
+ subscription.homepage = message.homepage;
+ FilterStorage.addSubscription(subscription);
+ if (!subscription.lastDownload)
+ Synchronizer.execute(subscription);
+ }
+ });
+
+ port.on("subscriptions.update", (message, sender) =>
+ {
+ let {subscriptions} = FilterStorage;
+ if (message.url)
+ subscriptions = [Subscription.fromURL(message.url)];
+
+ for (let subscription of subscriptions)
+ {
+ if (subscription instanceof DownloadableSubscription)
+ Synchronizer.execute(subscription, true);
}
});
})(this);