Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 


Quelle  RemotePageChild.sys.mjs   Sprache: unbekannt

 
/* 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/. */

/**
 * RemotePageChild is a base class for an unprivileged internal page, typically
 * an about: page. A specific implementation should subclass the RemotePageChild
 * actor with a more specific actor for that page. Typically, the child is not
 * needed, but the parent actor will respond to messages and provide results
 * directly to the page.
 */

const lazy = {};
ChromeUtils.defineESModuleGetters(lazy, {
  AsyncPrefs: "resource://gre/modules/AsyncPrefs.sys.mjs",
  PrivateBrowsingUtils: "resource://gre/modules/PrivateBrowsingUtils.sys.mjs",
  RemotePageAccessManager:
    "resource://gre/modules/RemotePageAccessManager.sys.mjs",
});

export class RemotePageChild extends JSWindowActorChild {
  actorCreated() {
    this.listeners = new Map();
    this.exportBaseFunctions();
  }

  exportBaseFunctions() {
    const exportableFunctions = [
      "RPMSendAsyncMessage",
      "RPMSendQuery",
      "RPMAddMessageListener",
      "RPMRemoveMessageListener",
      "RPMGetIntPref",
      "RPMGetStringPref",
      "RPMGetBoolPref",
      "RPMSetPref",
      "RPMGetFormatURLPref",
      "RPMIsWindowPrivate",
    ];

    this.exportFunctions(exportableFunctions);
  }

  /**
   * Exports a list of functions to be accessible by the privileged page.
   * Subclasses may call this function to add functions that are specific
   * to a page. When the page calls a function, a function with the same
   * name is called within the child actor.
   *
   * Only functions that appear in the whitelist in the
   * RemotePageAccessManager for that page will be exported.
   *
   * @param array of function names.
   */
  exportFunctions(functions) {
    let document = this.document;
    let principal = document.nodePrincipal;

    // If there is no content principal, don't export any functions.
    if (!principal) {
      return;
    }

    let window = this.contentWindow;

    for (let fnname of functions) {
      let allowAccess = lazy.RemotePageAccessManager.checkAllowAccessToFeature(
        principal,
        fnname,
        document
      );

      if (allowAccess) {
        // Wrap each function in an access checking function.
        function accessCheckedFn(...args) {
          this.checkAllowAccess(fnname, args[0]);
          return this[fnname](...args);
        }

        Cu.exportFunction(accessCheckedFn.bind(this), window, {
          defineAs: fnname,
        });
      }
    }
  }

  handleEvent() {
    // Do nothing. The DOMDocElementInserted event is just used to create
    // the actor.
  }

  receiveMessage(messagedata) {
    let message = {
      name: messagedata.name,
      data: messagedata.data,
    };

    let listeners = this.listeners.get(message.name);
    if (!listeners) {
      return;
    }

    let clonedMessage = Cu.cloneInto(message, this.contentWindow);
    for (let listener of listeners.values()) {
      try {
        listener(clonedMessage);
      } catch (e) {
        console.error(e);
      }
    }
  }

  wrapPromise(promise) {
    return new this.contentWindow.Promise((resolve, reject) =>
      promise.then(resolve, reject)
    );
  }

  /**
   * Returns true if a feature cannot be accessed by the current page.
   * Throws an exception if the feature may not be accessed.

   * @param aDocument child process document to call from
   * @param aFeature to feature to check access to
   * @param aValue value that must be included with that feature's whitelist
   * @returns true if access is allowed or throws an exception otherwise
   */
  checkAllowAccess(aFeature, aValue) {
    let doc = this.document;
    if (!lazy.RemotePageAccessManager.checkAllowAccess(doc, aFeature, aValue)) {
      throw new Error(
        "RemotePageAccessManager does not allow access to " + aFeature
      );
    }

    return true;
  }

  addPage(aUrl, aFunctionMap) {
    lazy.RemotePageAccessManager.addPage(aUrl, aFunctionMap);
  }

  // Implementation of functions that are exported into the page.

  RPMSendAsyncMessage(aName, aData = null) {
    this.sendAsyncMessage(aName, aData);
  }

  RPMSendQuery(aName, aData = null) {
    return this.wrapPromise(
      new Promise(resolve => {
        this.sendQuery(aName, aData).then(result => {
          resolve(Cu.cloneInto(result, this.contentWindow));
        });
      })
    );
  }

  /**
   * Adds a listener for messages. Many callbacks can be registered for the
   * same message if necessary. An attempt to register the same callback for the
   * same message twice will be ignored. When called the callback is passed an
   * object with these properties:
   *   name:   The message name
   *   data:   Any data sent with the message
   */
  RPMAddMessageListener(aName, aCallback) {
    if (!this.listeners.has(aName)) {
      this.listeners.set(aName, new Set([aCallback]));
    } else {
      this.listeners.get(aName).add(aCallback);
    }
  }

  /**
   * Removes a listener for messages.
   */
  RPMRemoveMessageListener(aName, aCallback) {
    if (!this.listeners.has(aName)) {
      return;
    }

    this.listeners.get(aName).delete(aCallback);
  }

  RPMGetIntPref(aPref, defaultValue) {
    // Only call with a default value if it's defined, to be able to throw
    // errors for non-existent prefs.
    if (defaultValue !== undefined) {
      return Services.prefs.getIntPref(aPref, defaultValue);
    }
    return Services.prefs.getIntPref(aPref);
  }

  RPMGetStringPref(aPref) {
    return Services.prefs.getStringPref(aPref);
  }

  RPMGetBoolPref(aPref, defaultValue) {
    // Only call with a default value if it's defined, to be able to throw
    // errors for non-existent prefs.
    if (defaultValue !== undefined) {
      return Services.prefs.getBoolPref(aPref, defaultValue);
    }
    return Services.prefs.getBoolPref(aPref);
  }

  RPMSetPref(aPref, aVal) {
    return this.wrapPromise(lazy.AsyncPrefs.set(aPref, aVal));
  }

  RPMGetFormatURLPref(aFormatURL) {
    return Services.urlFormatter.formatURLPref(aFormatURL);
  }

  RPMIsWindowPrivate() {
    return lazy.PrivateBrowsingUtils.isContentWindowPrivate(this.contentWindow);
  }
}

[ Dauer der Verarbeitung: 0.3 Sekunden  (vorverarbeitet)  ]

                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Software

     Produkte
     Quellcodebibliothek

Aktivitäten

     Artikel über Sicherheit
     Anleitung zur Aktivierung von SSL

Muße

     Gedichte
     Musik
     Bilder

Jenseits des Üblichen ....

Besucherstatistik

Besucherstatistik

Monitoring

Montastic status badge