--- a/CLOBBER
+++ b/CLOBBER
@@ -17,9 +17,9 @@
#
# Modifying this file will now automatically clobber the buildbot machines \o/
#
# Are you updating CLOBBER because you think it's needed for your WebIDL
# changes to stick? As of bug 928195, this shouldn't be necessary! Please
# don't change CLOBBER for WebIDL changes any more.
-Merge day clobber
+Bug 1443983: Removing addoncompat.manifest requires clobber.
--- a/browser/base/content/tabbrowser.js
+++ b/browser/base/content/tabbrowser.js
@@ -2,18 +2,16 @@
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
/* eslint-env mozilla/browser-window */
window._gBrowser = {
init() {
- this.requiresAddonInterpositions = true;
-
ChromeUtils.defineModuleGetter(this, "AsyncTabSwitcher",
"resource:///modules/AsyncTabSwitcher.jsm");
XPCOMUtils.defineLazyServiceGetters(this, {
_unifiedComplete: ["@mozilla.org/autocomplete/search;1?name=unifiedcomplete", "mozIPlacesAutoComplete"],
serializationHelper: ["@mozilla.org/network/serialization-helper;1", "nsISerializationHelper"],
mURIFixup: ["@mozilla.org/docshell/urifixup;1", "nsIURIFixup"],
});
deleted file mode 100644
--- a/toolkit/components/addoncompat/Prefetcher.jsm
+++ /dev/null
@@ -1,536 +0,0 @@
-// This Source Code Form is subject to the terms of the Mozilla Public
-// License, v. 2.0. If a copy of the MPL was not distributed with this
-// file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-var EXPORTED_SYMBOLS = ["Prefetcher"];
-
-ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm");
-ChromeUtils.import("resource://gre/modules/Services.jsm");
-
-// Rules are defined at the bottom of this file.
-var PrefetcherRules = {};
-
-/*
- * When events that trigger in the content process are forwarded to
- * add-ons in the chrome process, we expect the add-ons to send a lot
- * of CPOWs to query content nodes while processing the events. To
- * speed this up, the prefetching system anticipates which properties
- * will be read and reads them ahead of time. The prefetched
- * properties are passed to the chrome process along with each
- * event. A typical scenario might work like this:
- *
- * 1. "load" event fires in content
- * 2. Content process prefetches:
- * event.target.defaultView = <win 1>
- * <win 1>.location = <location obj>
- * event.target.getElementsByTagName("form") = [<elt 1>, <elt 2>]
- * <elt 1>.id = "login-form"
- * <elt 2>.id = "subscribe-form"
- * 3. Content process forwards "load" event to add-on along with
- * prefetched data
- * 4. Add-on reads:
- * event.target.defaultView (already prefetched)
- * event.target.getElementsByTagName("form") (already prefetched)
- * <elt 1>.id (already prefetched)
- * <elt 1>.className (not prefetched; CPOW must be sent)
- *
- * The amount of data to prefetch is determined based on the add-on ID
- * and the event type. The specific data to select is determined using
- * a set of Datalog-like rules (http://en.wikipedia.org/wiki/Datalog).
- *
- * Rules operate on a series of "tables" like in a database. Each
- * table contains a set of content-process objects. When an event
- * handler runs, it seeds some initial tables with objects of
- * interest. For example, the Event table might start out containing
- * the event that fired.
- *
- * Objects are added to tables using a set of rules of the form "if X
- * is in table A, then add F(X) to table B", where F(X) is typically a
- * property access or a method call. The most common functions F are:
- *
- * PropertyOp(destTable, sourceTable, property):
- * For each object X in sourceTable, add X.property to destTable.
- * MethodOp(destTable, sourceTable, method, args):
- * For each object X in sourceTable, add X.method(args) to destTable.
- * CollectionOp(destTable, sourceTable):
- * For each object X in sourceTable, add X[i] to destTable for
- * all i from 0 to X.length - 1.
- *
- * To generate the prefetching in the example above, the following
- * rules would work:
- *
- * 1. PropertyOp("EventTarget", "Event", "target")
- * 2. PropertyOp("Window", "EventTarget", "defaultView")
- * 3. MethodOp("FormCollection", "EventTarget", "getElementsByTagName", "form")
- * 4. CollectionOp("Form", "FormCollection")
- * 5. PropertyOp(null, "Form", "id")
- *
- * Rules are written at the bottom of this file.
- *
- * When a rule runs, it will usually generate some cache entries that
- * will be passed to the chrome process. For example, when PropertyOp
- * prefetches obj.prop and gets the value X, it caches the value of
- * obj and X. When the chrome process receives this data, it creates a
- * two-level map [obj -> [prop -> X]]. When the add-on accesses a
- * property on obj, the add-on shim code consults this map to see if
- * the property has already been cached.
- */
-
-const PREF_PREFETCHING_ENABLED = "extensions.interposition.prefetching";
-
-function isPrimitive(v) {
- if (!v)
- return true;
- let type = typeof(v);
- return type !== "object" && type !== "function";
-}
-
-function objAddr(obj) {
-/*
- if (!isPrimitive(obj)) {
- return String(obj) + "[" + Cu.getJSTestingFunctions().objectAddress(obj) + "]";
- }
- return String(obj);
-*/
-}
-
-function log(/* ...args*/) {
-/*
- for (let arg of args) {
- dump(arg);
- dump(" ");
- }
- dump("\n");
-*/
-}
-
-function logPrefetch(/* kind, value1, component, value2*/) {
-/*
- log("prefetching", kind, objAddr(value1) + "." + component, "=", objAddr(value2));
-*/
-}
-
-/*
- * All the Op classes (representing Datalog rules) have the same interface:
- * outputTable: Table that objects generated by the rule are added to.
- * Note that this can be null.
- * inputTable: Table that the rule draws objects from.
- * addObject(database, obj): Called when an object is added to inputTable.
- * This code should take care of adding objects to outputTable.
- * Data to be cached should be stored by calling database.cache.
- * makeCacheEntry(item, cache):
- * Called by the chrome process to create the two-level map of
- * prefetched objects. |item| holds the cached data
- * generated by the content process. |cache| is the map to be
- * generated.
- */
-
-function PropertyOp(outputTable, inputTable, prop) {
- this.outputTable = outputTable;
- this.inputTable = inputTable;
- this.prop = prop;
-}
-
-PropertyOp.prototype.addObject = function(database, obj) {
- let has = false, propValue;
- try {
- if (this.prop in obj) {
- has = true;
- propValue = obj[this.prop];
- }
- } catch (e) {
- // Don't cache anything if an exception is thrown.
- return;
- }
-
- logPrefetch("prop", obj, this.prop, propValue);
- database.cache(this.index, obj, has, propValue);
- if (has && !isPrimitive(propValue) && this.outputTable) {
- database.add(this.outputTable, propValue);
- }
-};
-
-PropertyOp.prototype.makeCacheEntry = function(item, cache) {
- let [, obj, , propValue] = item;
-
- let desc = { configurable: false, enumerable: true, writable: false, value: propValue };
-
- if (!cache.has(obj)) {
- cache.set(obj, new Map());
- }
- let propMap = cache.get(obj);
- propMap.set(this.prop, desc);
-};
-
-function MethodOp(outputTable, inputTable, method, ...args) {
- this.outputTable = outputTable;
- this.inputTable = inputTable;
- this.method = method;
- this.args = args;
-}
-
-MethodOp.prototype.addObject = function(database, obj) {
- let result;
- try {
- result = obj[this.method].apply(obj, this.args);
- } catch (e) {
- // Don't cache anything if an exception is thrown.
- return;
- }
-
- logPrefetch("method", obj, this.method + "(" + this.args + ")", result);
- database.cache(this.index, obj, result);
- if (!isPrimitive(result) && this.outputTable) {
- database.add(this.outputTable, result);
- }
-};
-
-MethodOp.prototype.makeCacheEntry = function(item, cache) {
- let [, obj, result] = item;
-
- if (!cache.has(obj)) {
- cache.set(obj, new Map());
- }
- let propMap = cache.get(obj);
- let fallback = propMap.get(this.method);
-
- let method = this.method;
- let selfArgs = this.args;
- let methodImpl = function(...args) {
- if (args.length == selfArgs.length && args.every((v, i) => v === selfArgs[i])) {
- return result;
- }
-
- if (fallback) {
- return fallback.value(...args);
- }
- return obj[method](...args);
- };
-
- let desc = { configurable: false, enumerable: true, writable: false, value: methodImpl };
- propMap.set(this.method, desc);
-};
-
-function CollectionOp(outputTable, inputTable) {
- this.outputTable = outputTable;
- this.inputTable = inputTable;
-}
-
-CollectionOp.prototype.addObject = function(database, obj) {
- let elements = [];
- try {
- let len = obj.length;
- for (let i = 0; i < len; i++) {
- logPrefetch("index", obj, i, obj[i]);
- elements.push(obj[i]);
- }
- } catch (e) {
- // Don't cache anything if an exception is thrown.
- return;
- }
-
- database.cache(this.index, obj, ...elements);
- for (let i = 0; i < elements.length; i++) {
- if (!isPrimitive(elements[i]) && this.outputTable) {
- database.add(this.outputTable, elements[i]);
- }
- }
-};
-
-CollectionOp.prototype.makeCacheEntry = function(item, cache) {
- let [, obj, ...elements] = item;
-
- if (!cache.has(obj)) {
- cache.set(obj, new Map());
- }
- let propMap = cache.get(obj);
-
- let lenDesc = { configurable: false, enumerable: true, writable: false, value: elements.length };
- propMap.set("length", lenDesc);
-
- for (let i = 0; i < elements.length; i++) {
- let desc = { configurable: false, enumerable: true, writable: false, value: elements[i] };
- propMap.set(i, desc);
- }
-};
-
-function CopyOp(outputTable, inputTable) {
- this.outputTable = outputTable;
- this.inputTable = inputTable;
-}
-
-CopyOp.prototype.addObject = function(database, obj) {
- database.add(this.outputTable, obj);
-};
-
-function Database(trigger, addons) {
- // Create a map of rules that apply to this specific trigger and set
- // of add-ons. The rules are indexed based on their inputTable.
- this.rules = new Map();
- for (let addon of addons) {
- let addonRules = PrefetcherRules[addon] || {};
- let triggerRules = addonRules[trigger] || [];
- for (let rule of triggerRules) {
- let inTable = rule.inputTable;
- if (!this.rules.has(inTable)) {
- this.rules.set(inTable, new Set());
- }
- let set = this.rules.get(inTable);
- set.add(rule);
- }
- }
-
- // this.tables maps table names to sets of objects contained in them.
- this.tables = new Map();
-
- // todo is a worklist of items added to tables that have not had
- // rules run on them yet.
- this.todo = [];
-
- // Cached data to be sent to the chrome process.
- this.cached = [];
-}
-
-Database.prototype = {
- // Add an object to a table.
- add(table, obj) {
- if (!this.tables.has(table)) {
- this.tables.set(table, new Set());
- }
- let tableSet = this.tables.get(table);
- if (tableSet.has(obj)) {
- return;
- }
- tableSet.add(obj);
-
- this.todo.push([table, obj]);
- },
-
- cache(...args) {
- this.cached.push(args);
- },
-
- // Run a fixed-point iteration that adds objects to table based on
- // this.rules until there are no more objects to add.
- process() {
- while (this.todo.length) {
- let [table, obj] = this.todo.pop();
- let rules = this.rules.get(table);
- if (!rules) {
- continue;
- }
- for (let rule of rules) {
- rule.addObject(this, obj);
- }
- }
- },
-};
-
-var Prefetcher = {
- init() {
- // Give an index to each rule and store it in this.ruleMap based
- // on the index. The index is used to serialize and deserialize
- // data from content to chrome.
- let counter = 0;
- this.ruleMap = new Map();
- for (let addon in PrefetcherRules) {
- for (let trigger in PrefetcherRules[addon]) {
- for (let rule of PrefetcherRules[addon][trigger]) {
- rule.index = counter++;
- this.ruleMap.set(rule.index, rule);
- }
- }
- }
-
- this.prefetchingEnabled = Services.prefs.getBoolPref(PREF_PREFETCHING_ENABLED, false);
- Services.prefs.addObserver(PREF_PREFETCHING_ENABLED, this);
- Services.obs.addObserver(this, "xpcom-shutdown");
- },
-
- observe(subject, topic, data) {
- if (topic == "xpcom-shutdown") {
- Services.prefs.removeObserver(PREF_PREFETCHING_ENABLED, this);
- Services.obs.removeObserver(this, "xpcom-shutdown");
- } else if (topic == PREF_PREFETCHING_ENABLED) {
- this.prefetchingEnabled = Services.prefs.getBoolPref(PREF_PREFETCHING_ENABLED, false);
- }
- },
-
- // Called when an event occurs in the content process. The event is
- // described by the trigger string. |addons| is a list of addons
- // that have listeners installed for the event. |args| is
- // event-specific data (such as the event object).
- prefetch(trigger, addons, args) {
- if (!this.prefetchingEnabled) {
- return [[], []];
- }
-
- let db = new Database(trigger, addons);
- for (let table in args) {
- log("root", table, "=", objAddr(args[table]));
- db.add(table, args[table]);
- }
-
- // Prefetch objects and add them to tables.
- db.process();
-
- // Data passed to sendAsyncMessage must be split into a JSON
- // portion and a CPOW portion. This code splits apart db.cached
- // into these two pieces. Any object in db.cache is added to an
- // array of CPOWs and replaced with {cpow: <index in array>}.
- let cpowIndexes = new Map();
- let prefetched = [];
- let cpows = [];
- for (let item of db.cached) {
- item = item.map((elt) => {
- if (!isPrimitive(elt)) {
- if (!cpowIndexes.has(elt)) {
- let index = cpows.length;
- cpows.push(elt);
- cpowIndexes.set(elt, index);
- }
- return {cpow: cpowIndexes.get(elt)};
- }
- return elt;
- });
-
- prefetched.push(item);
- }
-
- return [prefetched, cpows];
- },
-
- cache: null,
-
- // Generate a two-level mapping based on cached data received from
- // the content process.
- generateCache(prefetched, cpows) {
- let cache = new Map();
- for (let item of prefetched) {
- // Replace anything of the form {cpow: <index>} with the actual
- // object in |cpows|.
- item = item.map((elt) => {
- if (!isPrimitive(elt)) {
- return cpows[elt.cpow];
- }
- return elt;
- });
-
- let index = item[0];
- let op = this.ruleMap.get(index);
- op.makeCacheEntry(item, cache);
- }
- return cache;
- },
-
- // Run |func|, using the prefetched data in |prefetched| and |cpows|
- // as a cache.
- withPrefetching(prefetched, cpows, func) {
- if (!this.prefetchingEnabled) {
- return func();
- }
-
- this.cache = this.generateCache(prefetched, cpows);
-
- try {
- log("Prefetching on");
- return func();
- } finally {
- // After we return from this event handler, the content process
- // is free to continue executing, so we invalidate our cache.
- log("Prefetching off");
- this.cache = null;
- }
- },
-
- // Called by shim code in the chrome process to check if target.prop
- // is cached.
- lookupInCache(addon, target, prop) {
- if (!this.cache || !Cu.isCrossProcessWrapper(target)) {
- return null;
- }
-
- let propMap = this.cache.get(target);
- if (!propMap) {
- return null;
- }
-
- return propMap.get(prop);
- },
-};
-
-var AdblockId = "{d10d0bf8-f5b5-c8b4-a8b2-2b9879e08c5d}";
-var AdblockRules = {
- "ContentPolicy.shouldLoad": [
- new MethodOp("Node", "InitNode", "QueryInterface", Ci.nsISupports),
- new PropertyOp("Document", "Node", "ownerDocument"),
- new PropertyOp("Window", "Node", "defaultView"),
- new PropertyOp("Window", "Document", "defaultView"),
- new PropertyOp("TopWindow", "Window", "top"),
- new PropertyOp("WindowLocation", "Window", "location"),
- new PropertyOp(null, "WindowLocation", "href"),
- new PropertyOp("Window", "Window", "parent"),
- new PropertyOp(null, "Window", "name"),
- new PropertyOp("Document", "Window", "document"),
- new PropertyOp("TopDocumentElement", "Document", "documentElement"),
- new MethodOp(null, "TopDocumentElement", "getAttribute", "data-adblockkey"),
- ]
-};
-PrefetcherRules[AdblockId] = AdblockRules;
-
-var LastpassId = "support@lastpass.com";
-var LastpassRules = {
- "EventTarget.handleEvent": [
- new PropertyOp("EventTarget", "Event", "target"),
- new PropertyOp("EventOriginalTarget", "Event", "originalTarget"),
- new PropertyOp("Window", "EventOriginalTarget", "defaultView"),
-
- new CopyOp("Frame", "Window"),
- new PropertyOp("FrameCollection", "Window", "frames"),
- new CollectionOp("Frame", "FrameCollection"),
- new PropertyOp("FrameCollection", "Frame", "frames"),
- new PropertyOp("FrameDocument", "Frame", "document"),
- new PropertyOp(null, "Frame", "window"),
- new PropertyOp(null, "FrameDocument", "defaultView"),
-
- new PropertyOp("FrameDocumentLocation", "FrameDocument", "location"),
- new PropertyOp(null, "FrameDocumentLocation", "href"),
- new PropertyOp("FrameLocation", "Frame", "location"),
- new PropertyOp(null, "FrameLocation", "href"),
-
- new MethodOp("FormCollection", "FrameDocument", "getElementsByTagName", "form"),
- new MethodOp("FormCollection", "FrameDocument", "getElementsByTagName", "FORM"),
- new CollectionOp("Form", "FormCollection"),
- new PropertyOp("FormElementCollection", "Form", "elements"),
- new CollectionOp("FormElement", "FormElementCollection"),
- new PropertyOp("Style", "Form", "style"),
-
- new PropertyOp(null, "FormElement", "type"),
- new PropertyOp(null, "FormElement", "name"),
- new PropertyOp(null, "FormElement", "value"),
- new PropertyOp(null, "FormElement", "tagName"),
- new PropertyOp(null, "FormElement", "id"),
- new PropertyOp("Style", "FormElement", "style"),
-
- new PropertyOp(null, "Style", "visibility"),
-
- new MethodOp("MetaElementsCollection", "EventOriginalTarget", "getElementsByTagName", "meta"),
- new CollectionOp("MetaElement", "MetaElementsCollection"),
- new PropertyOp(null, "MetaElement", "httpEquiv"),
-
- new MethodOp("InputElementCollection", "FrameDocument", "getElementsByTagName", "input"),
- new MethodOp("InputElementCollection", "FrameDocument", "getElementsByTagName", "INPUT"),
- new CollectionOp("InputElement", "InputElementCollection"),
- new PropertyOp(null, "InputElement", "type"),
- new PropertyOp(null, "InputElement", "name"),
- new PropertyOp(null, "InputElement", "tagName"),
- new PropertyOp(null, "InputElement", "form"),
-
- new PropertyOp("BodyElement", "FrameDocument", "body"),
- new PropertyOp("BodyInnerText", "BodyElement", "innerText"),
-
- new PropertyOp("DocumentFormCollection", "FrameDocument", "forms"),
- new CollectionOp("DocumentForm", "DocumentFormCollection"),
- ]
-};
-PrefetcherRules[LastpassId] = LastpassRules;
deleted file mode 100644
--- a/toolkit/components/addoncompat/RemoteAddonsChild.jsm
+++ /dev/null
@@ -1,167 +0,0 @@
-// This Source Code Form is subject to the terms of the Mozilla Public
-// License, v. 2.0. If a copy of the MPL was not distributed with this
-// file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-var EXPORTED_SYMBOLS = ["RemoteAddonsChild"];
-
-ChromeUtils.import("resource://gre/modules/Services.jsm");
-
-// Similar to Python. Returns dict[key] if it exists. Otherwise,
-// sets dict[key] to default_ and returns default_.
-function setDefault(dict, key, default_) {
- if (key in dict) {
- return dict[key];
- }
- dict[key] = default_;
- return default_;
-}
-
-// This code keeps track of a set of paths of the form [component_1,
-// ..., component_n]. The components can be strings or booleans. The
-// child is notified whenever a path is added or removed, and new
-// children can request the current set of paths. The purpose is to
-// keep track of all the observers and events that the child should
-// monitor for the parent.
-//
-// In the child, clients can watch for changes to all paths that start
-// with a given component.
-var NotificationTracker = {
- init() {
- let cpmm = Cc["@mozilla.org/childprocessmessagemanager;1"]
- .getService(Ci.nsISyncMessageSender);
- cpmm.addMessageListener("Addons:ChangeNotification", this);
- this._paths = cpmm.initialProcessData.remoteAddonsNotificationPaths;
- this._registered = new Map();
- this._watchers = {};
- },
-
- receiveMessage(msg) {
- let path = msg.data.path;
- let count = msg.data.count;
-
- let tracked = this._paths;
- for (let component of path) {
- tracked = setDefault(tracked, component, {});
- }
-
- tracked._count = count;
-
- if (this._watchers[path[0]]) {
- for (let watcher of this._watchers[path[0]]) {
- this.runCallback(watcher, path, count);
- }
- }
- },
-
- runCallback(watcher, path, count) {
- let pathString = path.join("/");
- let registeredSet = this._registered.get(watcher);
- let registered = registeredSet.has(pathString);
- if (count && !registered) {
- watcher.track(path, true);
- registeredSet.add(pathString);
- } else if (!count && registered) {
- watcher.track(path, false);
- registeredSet.delete(pathString);
- }
- },
-
- findPaths(prefix) {
- if (!this._paths) {
- return [];
- }
-
- let tracked = this._paths;
- for (let component of prefix) {
- tracked = setDefault(tracked, component, {});
- }
-
- let result = [];
- let enumerate = (tracked, curPath) => {
- for (let component in tracked) {
- if (component == "_count") {
- result.push([curPath, tracked._count]);
- } else {
- let path = curPath.slice();
- if (component === "true") {
- component = true;
- } else if (component === "false") {
- component = false;
- }
- path.push(component);
- enumerate(tracked[component], path);
- }
- }
- };
- enumerate(tracked, prefix);
-
- return result;
- },
-
- findSuffixes(prefix) {
- let paths = this.findPaths(prefix);
- return paths.map(([path, count]) => path[path.length - 1]);
- },
-
- watch(component1, watcher) {
- setDefault(this._watchers, component1, []).push(watcher);
- this._registered.set(watcher, new Set());
-
- let paths = this.findPaths([component1]);
- for (let [path, count] of paths) {
- this.runCallback(watcher, path, count);
- }
- },
-
- unwatch(component1, watcher) {
- let watchers = this._watchers[component1];
- let index = watchers.lastIndexOf(watcher);
- if (index > -1) {
- watchers.splice(index, 1);
- }
-
- this._registered.delete(watcher);
- },
-
- getCount(component1) {
- return this.findPaths([component1]).length;
- },
-};
-
-
-var RemoteAddonsChild = {
- _ready: false,
-
- makeReady() {
- },
-
- init(global) {
-
- if (!this._ready) {
- if (!Services.cpmm.initialProcessData.remoteAddonsParentInitted) {
- return null;
- }
-
- this.makeReady();
- this._ready = true;
- }
-
- global.sendAsyncMessage("Addons:RegisterGlobal", {}, {global});
-
- return [];
- },
-
- uninit(perTabShims) {
- for (let shim of perTabShims) {
- try {
- shim.uninit();
- } catch (e) {
- Cu.reportError(e);
- }
- }
- },
-
- get useSyncWebProgress() {
- return NotificationTracker.getCount("web-progress") > 0;
- },
-};
deleted file mode 100644
--- a/toolkit/components/addoncompat/RemoteAddonsParent.jsm
+++ /dev/null
@@ -1,168 +0,0 @@
-// This Source Code Form is subject to the terms of the Mozilla Public
-// License, v. 2.0. If a copy of the MPL was not distributed with this
-// file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-var EXPORTED_SYMBOLS = ["RemoteAddonsParent"];
-
-ChromeUtils.import("resource://gre/modules/RemoteWebProgress.jsm");
-ChromeUtils.import("resource://gre/modules/Services.jsm");
-
-Cu.permitCPOWsInScope(this);
-
-// Similar to Python. Returns dict[key] if it exists. Otherwise,
-// sets dict[key] to default_ and returns default_.
-function setDefault(dict, key, default_) {
- if (key in dict) {
- return dict[key];
- }
- dict[key] = default_;
- return default_;
-}
-
-// This code keeps track of a set of paths of the form [component_1,
-// ..., component_n]. The components can be strings or booleans. The
-// child is notified whenever a path is added or removed, and new
-// children can request the current set of paths. The purpose is to
-// keep track of all the observers and events that the child should
-// monitor for the parent.
-var NotificationTracker = {
- // _paths is a multi-level dictionary. Let's add paths [A, B] and
- // [A, C]. Then _paths will look like this:
- // { 'A': { 'B': { '_count': 1 }, 'C': { '_count': 1 } } }
- // Each component in a path will be a key in some dictionary. At the
- // end, the _count property keeps track of how many instances of the
- // given path are present in _paths.
- _paths: {},
-
- init() {
- let ppmm = Cc["@mozilla.org/parentprocessmessagemanager;1"]
- .getService(Ci.nsIMessageBroadcaster);
- ppmm.initialProcessData.remoteAddonsNotificationPaths = this._paths;
- },
-
- add(path) {
- let tracked = this._paths;
- for (let component of path) {
- tracked = setDefault(tracked, component, {});
- }
- let count = tracked._count || 0;
- count++;
- tracked._count = count;
-
- let ppmm = Cc["@mozilla.org/parentprocessmessagemanager;1"]
- .getService(Ci.nsIMessageBroadcaster);
- ppmm.broadcastAsyncMessage("Addons:ChangeNotification", {path, count});
- },
-
- remove(path) {
- let tracked = this._paths;
- for (let component of path) {
- tracked = setDefault(tracked, component, {});
- }
- tracked._count--;
-
- let ppmm = Cc["@mozilla.org/parentprocessmessagemanager;1"]
- .getService(Ci.nsIMessageBroadcaster);
- ppmm.broadcastAsyncMessage("Addons:ChangeNotification", {path, count: tracked._count});
- },
-};
-NotificationTracker.init();
-
-// An interposition is an object with three properties: methods,
-// getters, and setters. See multiprocessShims.js for an explanation
-// of how these are used. The constructor here just allows one
-// interposition to inherit members from another.
-function Interposition(name, base) {
- this.name = name;
- if (base) {
- this.methods = Object.create(base.methods);
- this.getters = Object.create(base.getters);
- this.setters = Object.create(base.setters);
- } else {
- this.methods = Object.create(null);
- this.getters = Object.create(null);
- this.setters = Object.create(null);
- }
-}
-
-var TabBrowserElementInterposition = new Interposition("TabBrowserElementInterposition");
-
-// This function returns a wrapper around an
-// nsIWebProgressListener. When the wrapper is invoked, it calls the
-// real listener but passes CPOWs for the nsIWebProgress and
-// nsIRequest arguments.
-var progressListeners = {global: new WeakMap(), tabs: new WeakMap()};
-function wrapProgressListener(kind, listener) {
- if (progressListeners[kind].has(listener)) {
- return progressListeners[kind].get(listener);
- }
-
- let ListenerHandler = {
- get(target, name) {
- if (name.startsWith("on")) {
- return function(...args) {
- listener[name].apply(listener, RemoteWebProgressManager.argumentsForAddonListener(kind, args));
- };
- }
-
- return listener[name];
- }
- };
- let listenerProxy = new Proxy(listener, ListenerHandler);
-
- progressListeners[kind].set(listener, listenerProxy);
- return listenerProxy;
-}
-
-TabBrowserElementInterposition.methods.addProgressListener = function(addon, target, listener) {
- if (!target.ownerGlobal.gMultiProcessBrowser) {
- return target.addProgressListener(listener);
- }
-
- NotificationTracker.add(["web-progress", addon]);
- return target.addProgressListener(wrapProgressListener("global", listener));
-};
-
-TabBrowserElementInterposition.methods.removeProgressListener = function(addon, target, listener) {
- if (!target.ownerGlobal.gMultiProcessBrowser) {
- return target.removeProgressListener(listener);
- }
-
- NotificationTracker.remove(["web-progress", addon]);
- return target.removeProgressListener(wrapProgressListener("global", listener));
-};
-
-var RemoteAddonsParent = {
- init() {
- let mm = Cc["@mozilla.org/globalmessagemanager;1"].getService(Ci.nsIMessageListenerManager);
- mm.addMessageListener("Addons:RegisterGlobal", this);
-
- Services.ppmm.initialProcessData.remoteAddonsParentInitted = true;
-
- Services.ppmm.loadProcessScript("data:,new " + function() {
- ChromeUtils.import("resource://gre/modules/RemoteAddonsChild.jsm");
- }, true);
-
- this.globalToBrowser = new WeakMap();
- this.browserToGlobal = new WeakMap();
- },
-
- getInterfaceInterpositions() {
- return {};
- },
-
- getTaggedInterpositions() {
- return {
- TabBrowserElement: TabBrowserElementInterposition,
- };
- },
-
- receiveMessage(msg) {
- switch (msg.name) {
- case "Addons:RegisterGlobal":
- this.browserToGlobal.set(msg.target, msg.objects.global);
- this.globalToBrowser.set(msg.objects.global, msg.target);
- break;
- }
- }
-};
deleted file mode 100644
--- a/toolkit/components/addoncompat/addoncompat.manifest
+++ /dev/null
@@ -1,4 +0,0 @@
-component {1363d5f0-d95e-11e3-9c1a-0800200c9a66} multiprocessShims.js
-contract @mozilla.org/addons/multiprocess-shims;1 {1363d5f0-d95e-11e3-9c1a-0800200c9a66}
-component {50bc93ce-602a-4bef-bf3a-61fc749c4caf} defaultShims.js
-contract @mozilla.org/addons/default-addon-shims;1 {50bc93ce-602a-4bef-bf3a-61fc749c4caf}
deleted file mode 100644
--- a/toolkit/components/addoncompat/defaultShims.js
+++ /dev/null
@@ -1,36 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-"use strict";
-
-ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm");
-
-/**
- * Using multiprocessShims is optional, and if an add-on is e10s compatible it should not
- * use it. But in some cases we still want to use the interposition service for various
- * features so we have a default shim service.
- */
-
-function DefaultInterpositionService() {
-}
-
-DefaultInterpositionService.prototype = {
- classID: Components.ID("{50bc93ce-602a-4bef-bf3a-61fc749c4caf}"),
- QueryInterface: XPCOMUtils.generateQI([Ci.nsIAddonInterposition, Ci.nsISupportsWeakReference]),
-
- getWhitelist() {
- return [];
- },
-
- interposeProperty(addon, target, iid, prop) {
- return null;
- },
-
- interposeCall(addonId, originalFunc, originalThis, args) {
- args.splice(0, 0, addonId);
- return originalFunc.apply(originalThis, args);
- },
-};
-
-this.NSGetFactory = XPCOMUtils.generateNSGetFactory([DefaultInterpositionService]);
deleted file mode 100644
--- a/toolkit/components/addoncompat/moz.build
+++ /dev/null
@@ -1,20 +0,0 @@
-# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
-# vim: set filetype=python:
-# This Source Code Form is subject to the terms of the Mozilla Public
-# License, v. 2.0. If a copy of the MPL was not distributed with this
-# file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-with Files('**'):
- BUG_COMPONENT = ('Firefox', 'Extension Compatibility')
-
-EXTRA_COMPONENTS += [
- 'addoncompat.manifest',
- 'defaultShims.js',
- 'multiprocessShims.js',
-]
-
-EXTRA_JS_MODULES += [
- 'Prefetcher.jsm',
- 'RemoteAddonsChild.jsm',
- 'RemoteAddonsParent.jsm',
-]
deleted file mode 100644
--- a/toolkit/components/addoncompat/multiprocessShims.js
+++ /dev/null
@@ -1,163 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-"use strict";
-
-ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm");
-
-ChromeUtils.defineModuleGetter(this, "Prefetcher",
- "resource://gre/modules/Prefetcher.jsm");
-ChromeUtils.defineModuleGetter(this, "RemoteAddonsParent",
- "resource://gre/modules/RemoteAddonsParent.jsm");
-
-/**
- * This service overlays the API that the browser exposes to
- * add-ons. The overlay tries to make a multiprocess browser appear as
- * much as possible like a single process browser. An overlay can
- * replace methods, getters, and setters of arbitrary browser objects.
- *
- * Most of the actual replacement code is implemented in
- * RemoteAddonsParent. The code in this service simply decides how to
- * replace code. For a given type of object (say, an
- * nsIObserverService) the code in RemoteAddonsParent can register a
- * set of replacement methods. This set is called an
- * "interposition". The service keeps track of all the different
- * interpositions. Whenever a method is called on some part of the
- * browser API, this service gets a chance to replace it. To do so, it
- * consults its map based on the type of object. If an interposition
- * is found, the given method is looked up on it and called
- * instead. If no method (or no interposition) is found, then the
- * original target method is called as normal.
- *
- * For each method call, we need to determine the type of the target
- * object. If the object is an old-style XPConnect wrapped native,
- * then the type is simply the interface that the method was called on
- * (Ci.nsIObserverService, say). For all other objects (WebIDL
- * objects, CPOWs, and normal JS objects), the type is determined by
- * calling getObjectTag.
- *
- * The interpositions defined in RemoteAddonsParent have three
- * properties: methods, getters, and setters. When accessing a
- * property, we first consult methods. If nothing is found, then we
- * consult getters or setters, depending on whether the access is a
- * get or a set.
- *
- * The methods in |methods| are functions that will be called whenever
- * the given method is called on the target object. They are passed
- * the same parameters as the original function except for two
- * additional ones at the beginning: the add-on ID and the original
- * target object that the method was called on. Additionally, the
- * value of |this| is set to the original target object.
- *
- * The values in |getters| and |setters| should also be
- * functions. They are called immediately when the given property is
- * accessed. The functions in |getters| take two parameters: the
- * add-on ID and the original target object. The functions in
- * |setters| take those arguments plus the value that the property is
- * being set to.
- */
-
-function AddonInterpositionService() {
- Prefetcher.init();
- RemoteAddonsParent.init();
-
- // These maps keep track of the interpositions for all different
- // kinds of objects.
- this._interfaceInterpositions = RemoteAddonsParent.getInterfaceInterpositions();
- this._taggedInterpositions = RemoteAddonsParent.getTaggedInterpositions();
-
- let wl = [];
- for (let v in this._interfaceInterpositions) {
- let interp = this._interfaceInterpositions[v];
- wl.push(...Object.getOwnPropertyNames(interp.methods));
- wl.push(...Object.getOwnPropertyNames(interp.getters));
- wl.push(...Object.getOwnPropertyNames(interp.setters));
- }
-
- for (let v in this._taggedInterpositions) {
- let interp = this._taggedInterpositions[v];
- wl.push(...Object.getOwnPropertyNames(interp.methods));
- wl.push(...Object.getOwnPropertyNames(interp.getters));
- wl.push(...Object.getOwnPropertyNames(interp.setters));
- }
-
- let nameSet = new Set();
- wl = wl.filter(function(item) {
- if (nameSet.has(item))
- return true;
-
- nameSet.add(item);
- return true;
- });
-
- this._whitelist = wl;
-}
-
-AddonInterpositionService.prototype = {
- classID: Components.ID("{1363d5f0-d95e-11e3-9c1a-0800200c9a66}"),
- QueryInterface: XPCOMUtils.generateQI([Ci.nsIAddonInterposition, Ci.nsISupportsWeakReference]),
-
- getWhitelist() {
- return this._whitelist;
- },
-
- // When the interface is not known for a method call, this code
- // determines the type of the target object.
- getObjectTag(target) {
- if (Cu.isCrossProcessWrapper(target)) {
- return Cu.getCrossProcessWrapperTag(target);
- }
-
- if (target.ownerGlobal && target === target.ownerGlobal.gBrowser) {
- return "TabBrowserElement";
- }
-
- return "generic";
- },
-
- interposeProperty(addon, target, iid, prop) {
- let interp;
- if (iid) {
- interp = this._interfaceInterpositions[iid];
- } else {
- try {
- interp = this._taggedInterpositions[this.getObjectTag(target)];
- } catch (e) {
- Cu.reportError(new Components.Exception("Failed to interpose object", e.result, Components.stack.caller));
- }
- }
-
- if (!interp) {
- return Prefetcher.lookupInCache(addon, target, prop);
- }
-
- let desc = { configurable: false, enumerable: true };
-
- if ("methods" in interp && prop in interp.methods) {
- desc.writable = false;
- desc.value = function(...args) {
- return interp.methods[prop](addon, target, ...args);
- };
-
- return desc;
- } else if ("getters" in interp && prop in interp.getters) {
- desc.get = function() { return interp.getters[prop](addon, target); };
-
- if ("setters" in interp && prop in interp.setters) {
- desc.set = function(v) { return interp.setters[prop](addon, target, v); };
- }
-
- return desc;
- }
-
- return Prefetcher.lookupInCache(addon, target, prop);
- },
-
- interposeCall(addonId, originalFunc, originalThis, args) {
- args.splice(0, 0, addonId);
- return originalFunc.apply(originalThis, args);
- },
-};
-
-this.NSGetFactory = XPCOMUtils.generateNSGetFactory([AddonInterpositionService]);
--- a/toolkit/components/moz.build
+++ b/toolkit/components/moz.build
@@ -11,17 +11,16 @@ with Files('**'):
if CONFIG['MOZ_ENABLE_XREMOTE']:
DIRS += ['remote']
DIRS += [
'aboutcache',
'aboutcheckerboard',
'aboutmemory',
'aboutperformance',
- 'addoncompat',
'alerts',
'apppicker',
'asyncshutdown',
'backgroundhangmonitor',
'browser',
'cloudstorage',
'commandlines',
'contentprefs',
--- a/toolkit/content/browser-child.js
+++ b/toolkit/content/browser-child.js
@@ -3,17 +3,16 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
/* eslint-env mozilla/frame-script */
ChromeUtils.import("resource://gre/modules/AppConstants.jsm");
ChromeUtils.import("resource://gre/modules/BrowserUtils.jsm");
ChromeUtils.import("resource://gre/modules/Services.jsm");
ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm");
-ChromeUtils.import("resource://gre/modules/RemoteAddonsChild.jsm");
ChromeUtils.import("resource://gre/modules/Timer.jsm");
ChromeUtils.defineModuleGetter(this, "PageThumbUtils",
"resource://gre/modules/PageThumbUtils.jsm");
ChromeUtils.defineModuleGetter(this, "Utils",
"resource://gre/modules/sessionstore/Utils.jsm");
@@ -110,21 +109,17 @@ var WebProgressListener = {
// DOMWindow is not necessarily the content-window with subframes.
DOMWindow: domWindow,
webProgress: aWebProgress,
request: aRequest,
};
},
_send(name, data, objects) {
- if (RemoteAddonsChild.useSyncWebProgress) {
- sendRpcMessage(name, data, objects);
- } else {
- sendAsyncMessage(name, data, objects);
- }
+ sendAsyncMessage(name, data, objects);
},
onStateChange: function onStateChange(aWebProgress, aRequest, aStateFlags, aStatus) {
let json = this._setupJSON(aWebProgress, aRequest, aStateFlags);
let objects = this._setupObjects(aWebProgress, aRequest);
json.stateFlags = aStateFlags;
json.status = aStatus;
@@ -600,25 +595,16 @@ addMessageListener("Browser:CreateAboutB
if (!content.document || content.document.documentURI != "about:blank") {
throw new Error("Can't create a content viewer unless on about:blank");
}
let principal = aMessage.data;
principal = BrowserUtils.principalWithMatchingOA(principal, content.document.nodePrincipal);
docShell.createAboutBlankContentViewer(principal);
});
-// The AddonsChild needs to be rooted so that it stays alive as long as
-// the tab.
-var AddonsChild = RemoteAddonsChild.init(this);
-if (AddonsChild) {
- addEventListener("unload", () => {
- RemoteAddonsChild.uninit(AddonsChild);
- });
-}
-
addMessageListener("InPermitUnload", msg => {
let inPermitUnload = docShell.contentViewer && docShell.contentViewer.inPermitUnload;
sendAsyncMessage("InPermitUnload", {id: msg.data.id, inPermitUnload});
});
addMessageListener("PermitUnload", msg => {
sendAsyncMessage("PermitUnload", {id: msg.data.id, kind: "start"});
--- a/toolkit/mozapps/extensions/AddonManagerStartup.cpp
+++ b/toolkit/mozapps/extensions/AddonManagerStartup.cpp
@@ -23,17 +23,16 @@
#include "mozilla/Unused.h"
#include "mozilla/ErrorResult.h"
#include "mozilla/dom/ipc/StructuredCloneData.h"
#include "nsAppDirectoryServiceDefs.h"
#include "nsAppRunner.h"
#include "nsContentUtils.h"
#include "nsChromeRegistry.h"
-#include "nsIAddonInterposition.h"
#include "nsIDOMWindowUtils.h" // for nsIJSRAIIHelper
#include "nsIFileURL.h"
#include "nsIIOService.h"
#include "nsIJARProtocolHandler.h"
#include "nsIJARURI.h"
#include "nsIStringEnumerator.h"
#include "nsIZipReader.h"
#include "nsJSUtils.h"
@@ -507,29 +506,19 @@ InstallLocation::InstallLocation(JSConte
}
/*****************************************************************************
* XPC interfacing
*****************************************************************************/
static void
-EnableShimsAndCPOWs(const nsAString& addonId, bool enableShims)
+EnableShimsAndCPOWs(const nsAString& addonId)
{
NS_ConvertUTF16toUTF8 id(addonId);
-
- if (enableShims) {
- nsCOMPtr<nsIAddonInterposition> interposition =
- do_GetService("@mozilla.org/addons/multiprocess-shims;1");
-
- if (!interposition || !xpc::SetAddonInterposition(id, interposition)) {
- return;
- }
- }
-
Unused << xpc::AllowCPOWsInAddon(id, true);
}
Result<Ok, nsresult>
AddonManagerStartup::AddInstallLocation(Addon& addon)
{
nsCOMPtr<nsIFile> file;
MOZ_TRY_VAR(file, addon.FullPath());
@@ -608,30 +597,28 @@ AddonManagerStartup::InitializeExtension
NS_ENSURE_TRUE(locations.isObject(), NS_ERROR_INVALID_ARG);
mInitialized = true;
if (!Preferences::GetBool("extensions.defaultProviders.enabled", true)) {
return NS_OK;
}
- bool enableInterpositions = Preferences::GetBool("extensions.interposition.enabled", false);
-
JS::RootedObject locs(cx, &locations.toObject());
for (auto e1 : PropertyIter(cx, locs)) {
InstallLocation loc(e1);
for (auto e2 : loc.Addons()) {
Addon addon(e2);
if (addon.Enabled() && !addon.Bootstrapped()) {
Unused << AddInstallLocation(addon);
if (addon.ShimsEnabled()) {
- EnableShimsAndCPOWs(addon.Id(), enableInterpositions);
+ EnableShimsAndCPOWs(addon.Id());
}
}
}
}
return NS_OK;
}
--- a/toolkit/mozapps/extensions/internal/XPIProvider.jsm
+++ b/toolkit/mozapps/extensions/internal/XPIProvider.jsm
@@ -80,17 +80,16 @@ const PREF_XPI_FILE_WHITELISTED =
// xpinstall.signatures.required only supported in dev builds
const PREF_XPI_SIGNATURES_REQUIRED = "xpinstall.signatures.required";
const PREF_XPI_SIGNATURES_DEV_ROOT = "xpinstall.signatures.dev-root";
const PREF_XPI_PERMISSIONS_BRANCH = "xpinstall.";
const PREF_INSTALL_REQUIRESECUREORIGIN = "extensions.install.requireSecureOrigin";
const PREF_INSTALL_DISTRO_ADDONS = "extensions.installDistroAddons";
const PREF_BRANCH_INSTALLED_ADDON = "extensions.installedDistroAddon.";
const PREF_DISTRO_ADDONS_PERMS = "extensions.distroAddons.promptForPermissions";
-const PREF_INTERPOSITION_ENABLED = "extensions.interposition.enabled";
const PREF_SYSTEM_ADDON_SET = "extensions.systemAddonSet";
const PREF_SYSTEM_ADDON_UPDATE_URL = "extensions.systemAddon.update.url";
const PREF_ALLOW_LEGACY = "extensions.legacy.enabled";
const PREF_ALLOW_NON_MPC = "extensions.allow-non-mpc-extensions";
const PREF_EM_MIN_COMPAT_APP_VERSION = "extensions.minCompatibleAppVersion";
const PREF_EM_MIN_COMPAT_PLATFORM_VERSION = "extensions.minCompatiblePlatformVersion";
@@ -4227,21 +4226,16 @@ var XPIProvider = {
let activeAddon = this.activeAddons.get(aId);
logger.debug("Loading bootstrap scope from " + aFile.path);
let principal = Cc["@mozilla.org/systemprincipal;1"].
createInstance(Ci.nsIPrincipal);
if (!aMultiprocessCompatible) {
- if (Services.prefs.getBoolPref(PREF_INTERPOSITION_ENABLED, false)) {
- let interposition = Cc["@mozilla.org/addons/multiprocess-shims;1"].
- getService(Ci.nsIAddonInterposition);
- Cu.setAddonInterposition(aId, interposition);
- }
Cu.allowCPOWsInAddon(aId, true);
}
if (!aFile.exists()) {
activeAddon.bootstrapScope =
new Cu.Sandbox(principal, { sandboxName: aFile.path,
addonId: aId,
wantGlobalProperties: ["ChromeUtils"],
--- a/toolkit/xre/nsXREDirProvider.cpp
+++ b/toolkit/xre/nsXREDirProvider.cpp
@@ -6,17 +6,16 @@
#include "nsAppRunner.h"
#include "nsToolkitCompsCID.h"
#include "nsXREDirProvider.h"
#include "mozilla/AddonManagerStartup.h"
#include "jsapi.h"
#include "xpcpublic.h"
-#include "nsIAddonInterposition.h"
#include "nsIAppStartup.h"
#include "nsIDirectoryEnumerator.h"
#include "nsIFile.h"
#include "nsIObserver.h"
#include "nsIObserverService.h"
#include "nsISimpleEnumerator.h"
#include "nsIToolkitChromeRegistry.h"
#include "nsIToolkitProfileService.h"