summaryrefslogtreecommitdiffstats
path: root/toolkit/components/contentprefs/ContentPrefServiceChild.sys.mjs
diff options
context:
space:
mode:
Diffstat (limited to 'toolkit/components/contentprefs/ContentPrefServiceChild.sys.mjs')
-rw-r--r--toolkit/components/contentprefs/ContentPrefServiceChild.sys.mjs185
1 files changed, 185 insertions, 0 deletions
diff --git a/toolkit/components/contentprefs/ContentPrefServiceChild.sys.mjs b/toolkit/components/contentprefs/ContentPrefServiceChild.sys.mjs
new file mode 100644
index 0000000000..38d0d3c160
--- /dev/null
+++ b/toolkit/components/contentprefs/ContentPrefServiceChild.sys.mjs
@@ -0,0 +1,185 @@
+/* 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/. */
+
+import {
+ ContentPref,
+ _methodsCallableFromChild,
+ cbHandleCompletion,
+ cbHandleError,
+ cbHandleResult,
+ safeCallback,
+} from "resource://gre/modules/ContentPrefUtils.sys.mjs";
+
+// 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(contentPref) {
+ cbHandleResult(
+ this._callback,
+ new ContentPref(contentPref.domain, contentPref.name, contentPref.value)
+ );
+ },
+
+ handleError(result) {
+ cbHandleError(this._callback, result);
+ },
+
+ handleCompletion(reason) {
+ cbHandleCompletion(this._callback, reason);
+ },
+};
+
+export class ContentPrefsChild extends JSProcessActorChild {
+ constructor() {
+ super();
+
+ // Map from pref name -> set of observers
+ this._observers = new Map();
+
+ // Map from random ID string -> CallbackCaller, per request
+ this._requests = new Map();
+ }
+
+ _getRandomId() {
+ return Services.uuid.generateUUID().toString();
+ }
+
+ receiveMessage(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(call, args, callback) {
+ let requestId = this._getRandomId();
+ let data = { call, args, requestId };
+
+ this._requests.set(requestId, new CallbackCaller(callback));
+ this.sendAsyncMessage("ContentPrefs:FunctionCall", data);
+ }
+
+ addObserverForName(name, observer) {
+ let set = this._observers.get(name);
+ if (!set) {
+ set = new Set();
+
+ // This is the first observer for this name. Start listening for changes
+ // to it.
+ this.sendAsyncMessage("ContentPrefs:AddObserverForName", {
+ name,
+ });
+ this._observers.set(name, set);
+ }
+
+ set.add(observer);
+ }
+
+ removeObserverForName(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.sendAsyncMessage("ContentPrefs:RemoveObserverForName", {
+ name,
+ });
+
+ this._observers.delete(name);
+ }
+ }
+}
+
+export var ContentPrefServiceChild = {
+ QueryInterface: ChromeUtils.generateQI(["nsIContentPrefService2"]),
+
+ addObserverForName: (name, observer) => {
+ ChromeUtils.domProcessChild
+ .getActor("ContentPrefs")
+ .addObserverForName(name, observer);
+ },
+ removeObserverForName: (name, observer) => {
+ ChromeUtils.domProcessChild
+ .getActor("ContentPrefs")
+ .removeObserverForName(name, observer);
+ },
+
+ getCachedByDomainAndName: NYI,
+ getCachedBySubdomainAndName: NYI,
+ getCachedGlobal: NYI,
+ 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];
+ }
+
+ let actor = ChromeUtils.domProcessChild.getActor("ContentPrefs");
+ actor.callFunction(method, args, callback);
+}
+
+for (let [method, signature] of _methodsCallableFromChild) {
+ ContentPrefServiceChild[method] = forwardMethodToParent.bind(
+ ContentPrefServiceChild,
+ method,
+ signature
+ );
+}