summaryrefslogtreecommitdiffstats
path: root/toolkit/components/contentprefs/ContentPrefServiceChild.jsm
diff options
context:
space:
mode:
Diffstat (limited to 'toolkit/components/contentprefs/ContentPrefServiceChild.jsm')
-rw-r--r--toolkit/components/contentprefs/ContentPrefServiceChild.jsm182
1 files changed, 182 insertions, 0 deletions
diff --git a/toolkit/components/contentprefs/ContentPrefServiceChild.jsm b/toolkit/components/contentprefs/ContentPrefServiceChild.jsm
new file mode 100644
index 000000000..7faca8970
--- /dev/null
+++ b/toolkit/components/contentprefs/ContentPrefServiceChild.jsm
@@ -0,0 +1,182 @@
+/* vim: set ts=2 sw=2 sts=2 et tw=80: */
+/* 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";
+
+this.EXPORTED_SYMBOLS = [ "ContentPrefServiceChild" ];
+
+const Ci = Components.interfaces;
+const Cc = Components.classes;
+const Cu = Components.utils;
+
+Cu.import("resource://gre/modules/XPCOMUtils.jsm");
+Cu.import("resource://gre/modules/ContentPrefUtils.jsm");
+Cu.import("resource://gre/modules/ContentPrefStore.jsm");
+
+// We only need one bit of information out of the context.
+function contextArg(context) {
+ return (context && context.usePrivateBrowsing) ?
+ { usePrivateBrowsing: true } :
+ null;
+}
+
+function NYI() {
+ throw new Error("Do not add any new users of these functions");
+}
+
+function CallbackCaller(callback) {
+ this._callback = callback;
+}
+
+CallbackCaller.prototype = {
+ handleResult: function(contentPref) {
+ cbHandleResult(this._callback,
+ new ContentPref(contentPref.domain,
+ contentPref.name,
+ contentPref.value));
+ },
+
+ handleError: function(result) {
+ cbHandleError(this._callback, result);
+ },
+
+ handleCompletion: function(reason) {
+ cbHandleCompletion(this._callback, reason);
+ },
+};
+
+var ContentPrefServiceChild = {
+ QueryInterface: XPCOMUtils.generateQI([ Ci.nsIContentPrefService2 ]),
+
+ // Map from pref name -> set of observers
+ _observers: new Map(),
+
+ _mm: Cc["@mozilla.org/childprocessmessagemanager;1"]
+ .getService(Ci.nsIMessageSender),
+
+ _getRandomId: function() {
+ return Cc["@mozilla.org/uuid-generator;1"]
+ .getService(Ci.nsIUUIDGenerator).generateUUID().toString();
+ },
+
+ // Map from random ID string -> CallbackCaller, per request
+ _requests: new Map(),
+
+ init: function() {
+ this._mm.addMessageListener("ContentPrefs:HandleResult", this);
+ this._mm.addMessageListener("ContentPrefs:HandleError", this);
+ this._mm.addMessageListener("ContentPrefs:HandleCompletion", this);
+ },
+
+ receiveMessage: function(msg) {
+ let data = msg.data;
+ let callback;
+ switch (msg.name) {
+ case "ContentPrefs:HandleResult":
+ callback = this._requests.get(data.requestId);
+ callback.handleResult(data.contentPref);
+ break;
+
+ case "ContentPrefs:HandleError":
+ callback = this._requests.get(data.requestId);
+ callback.handleError(data.error);
+ break;
+
+ case "ContentPrefs:HandleCompletion":
+ callback = this._requests.get(data.requestId);
+ this._requests.delete(data.requestId);
+ callback.handleCompletion(data.reason);
+ break;
+
+ case "ContentPrefs:NotifyObservers": {
+ let observerList = this._observers.get(data.name);
+ if (!observerList)
+ break;
+
+ for (let observer of observerList) {
+ safeCallback(observer, data.callback, data.args);
+ }
+
+ break;
+ }
+ }
+ },
+
+ _callFunction: function(call, args, callback) {
+ let requestId = this._getRandomId();
+ let data = { call: call, args: args, requestId: requestId };
+
+ this._mm.sendAsyncMessage("ContentPrefs:FunctionCall", data);
+
+ this._requests.set(requestId, new CallbackCaller(callback));
+ },
+
+ getCachedByDomainAndName: NYI,
+ getCachedBySubdomainAndName: NYI,
+ getCachedGlobal: NYI,
+
+ addObserverForName: function(name, observer) {
+ let set = this._observers.get(name);
+ if (!set) {
+ set = new Set();
+ if (this._observers.size === 0) {
+ // This is the first observer of any kind. Start listening for changes.
+ this._mm.addMessageListener("ContentPrefs:NotifyObservers", this);
+ }
+
+ // This is the first observer for this name. Start listening for changes
+ // to it.
+ this._mm.sendAsyncMessage("ContentPrefs:AddObserverForName", { name: name });
+ this._observers.set(name, set);
+ }
+
+ set.add(observer);
+ },
+
+ removeObserverForName: function(name, observer) {
+ let set = this._observers.get(name);
+ if (!set)
+ return;
+
+ set.delete(observer);
+ if (set.size === 0) {
+ // This was the last observer for this name. Stop listening for changes.
+ this._mm.sendAsyncMessage("ContentPrefs:RemoveObserverForName", { name: name });
+
+ this._observers.delete(name);
+ if (this._observers.size === 0) {
+ // This was the last observer for this process. Stop listing for all
+ // changes.
+ this._mm.removeMessageListener("ContentPrefs:NotifyObservers", this);
+ }
+ }
+ },
+
+ extractDomain: NYI
+};
+
+function forwardMethodToParent(method, signature, ...args) {
+ // Ignore superfluous arguments
+ args = args.slice(0, signature.length);
+
+ // Process context argument for forwarding
+ let contextIndex = signature.indexOf("context");
+ if (contextIndex > -1) {
+ args[contextIndex] = contextArg(args[contextIndex]);
+ }
+ // Take out the callback argument, if present.
+ let callbackIndex = signature.indexOf("callback");
+ let callback = null;
+ if (callbackIndex > -1 && args.length > callbackIndex) {
+ callback = args.splice(callbackIndex, 1)[0];
+ }
+ this._callFunction(method, args, callback);
+}
+
+for (let [method, signature] of _methodsCallableFromChild) {
+ ContentPrefServiceChild[method] = forwardMethodToParent.bind(ContentPrefServiceChild, method, signature);
+}
+
+ContentPrefServiceChild.init();