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


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

import { MockRegistrar } from "resource://testing-common/MockRegistrar.sys.mjs";

class MockWindowsRegKey {
  key = null;

  // --- Overridden nsISupports interface functions ---
  QueryInterface = ChromeUtils.generateQI(["nsIWindowsRegKey"]);

  #assertKey() {
    if (this.key) {
      return;
    }
    throw Components.Exception("invalid registry path", Cr.NS_ERROR_FAILURE);
  }

  #findOrMaybeCreateKey(root, path, mode, maybeCreateCallback) {
    let rootKey = MockRegistry.getRoot(root);
    let parts = path.split("\\");
    if (parts.some(part => !part.length)) {
      throw Components.Exception("", Cr.NS_ERROR_FAILURE);
    }

    let key = rootKey;
    for (let part of parts) {
      if (!key.subkeys.has(part)) {
        maybeCreateCallback(key.subkeys, part);
      }
      key = key.subkeys.get(part);
    }
    this.key = key;
  }

  // --- Overridden nsIWindowsRegKey interface functions ---
  open(root, path, mode) {
    // eslint-disable-next-line no-unused-vars
    this.#findOrMaybeCreateKey(root, path, mode, (subkeys, part) => {
      throw Components.Exception("", Cr.NS_ERROR_FAILURE);
    });
  }

  create(root, path, mode) {
    this.#findOrMaybeCreateKey(root, path, mode, (subkeys, part) =>
      subkeys.set(part, { subkeys: new Map(), values: new Map() })
    );
  }

  close() {
    this.key = null;
  }

  get valueCount() {
    this.#assertKey();
    return this.key.values.size;
  }

  hasValue(name) {
    this.#assertKey();
    return this.key.values.has(name);
  }

  #getValuePair(name, expectedType = null) {
    this.#assertKey();
    if (!this.key.values.has(name)) {
      throw Components.Exception("invalid value name", Cr.NS_ERROR_FAILURE);
    }
    let [value, type] = this.key.values.get(name);
    if (expectedType && type !== expectedType) {
      throw Components.Exception("unexpected value type", Cr.NS_ERROR_FAILURE);
    }
    return [value, type];
  }

  getValueType(name) {
    let [, type] = this.#getValuePair(name);
    return type;
  }

  getValueName(index) {
    if (!this.key || index >= this.key.values.size) {
      throw Components.Exception("", Cr.NS_ERROR_FAILURE);
    }
    let names = Array.from(this.key.values.keys());
    return names[index];
  }

  readStringValue(name) {
    let [value] = this.#getValuePair(name, Ci.nsIWindowsRegKey.TYPE_STRING);
    return value;
  }

  readIntValue(name) {
    let [value] = this.#getValuePair(name, Ci.nsIWindowsRegKey.TYPE_INT);
    return value;
  }

  readInt64Value(name) {
    let [value] = this.#getValuePair(name, Ci.nsIWindowsRegKey.TYPE_INT64);
    return value;
  }

  readBinaryValue(name) {
    let [value] = this.#getValuePair(name, Ci.nsIWindowsRegKey.TYPE_BINARY);
    return value;
  }

  #writeValuePair(name, value, type) {
    this.#assertKey();
    this.key.values.set(name, [value, type]);
  }

  writeStringValue(name, value) {
    this.#writeValuePair(name, value, Ci.nsIWindowsRegKey.TYPE_STRING);
  }

  writeIntValue(name, value) {
    this.#writeValuePair(name, value, Ci.nsIWindowsRegKey.TYPE_INT);
  }

  writeInt64Value(name, value) {
    this.#writeValuePair(name, value, Ci.nsIWindowsRegKey.TYPE_INT64);
  }

  writeBinaryValue(name, value) {
    this.#writeValuePair(name, value, Ci.nsIWindowsRegKey.TYPE_BINARY);
  }

  removeValue(name) {
    this.#assertKey();
    this.key.values.delete(name);
  }

  get childCount() {
    this.#assertKey();
    return this.key.subkeys.size;
  }

  getChildName(index) {
    if (!this.key || index >= this.key.values.size) {
      throw Components.Exception("", Cr.NS_ERROR_FAILURE);
    }
    let names = Array.from(this.key.subkeys.keys());
    return names[index];
  }

  hasChild(name) {
    this.#assertKey();
    return this.key.subkeys.has(name);
  }

  removeChild(name) {
    this.#assertKey();
    let child = this.key.subkeys.get(name);

    if (!child) {
      throw Components.Exception("", Cr.NS_ERROR_FAILURE);
    }
    if (child.subkeys.size > 0) {
      throw Components.Exception("", Cr.NS_ERROR_FAILURE);
    }

    this.key.subkeys.delete(name);
  }

  #findOrMaybeCreateChild(name, mode, maybeCreateCallback) {
    this.#assertKey();
    if (name.split("\\").length > 1) {
      throw Components.Exception("", Cr.NS_ERROR_FAILURE);
    }
    if (!this.key.subkeys.has(name)) {
      maybeCreateCallback(this.key.subkeys, name);
    }
    // This won't wrap in the same way as `Cc["@mozilla.org/windows-registry-key;1"].createInstance(nsIWindowsRegKey);`.
    let subKey = new MockWindowsRegKey();
    subKey.key = this.key.subkeys.get(name);
    return subKey;
  }

  openChild(name, mode) {
    // eslint-disable-next-line no-unused-vars
    return this.#findOrMaybeCreateChild(name, mode, (subkeys, part) => {
      throw Components.Exception("", Cr.NS_ERROR_FAILURE);
    });
  }

  createChild(name, mode) {
    return this.#findOrMaybeCreateChild(name, mode, (subkeys, part) =>
      subkeys.set(part, { subkeys: new Map(), values: new Map() })
    );
  }
}

export class MockRegistry {
  // All instances of `MockRegistry` share a single data-store; this is
  // conceptually parallel to the Windows registry, which is a shared global
  // resource.  It would be possible to have separate data-stores for separate
  // instances with a little adjustment to `MockWindowsRegKey`.
  //
  // Top-level map is indexed by roots.  A "key" is an object that has
  // `subkeys` and `values`, both maps indexed by strings.  Subkey items are
  // again "key" objects.  Value items are `[value, type]` pairs.
  //
  // In pseudo-code:
  //
  // {Ci.nsIWindowsRegKey.ROOT_KEY_CURRENT_USER:
  //  {subkeys:
  //   {child: {subkeys: {}, values: {key: ["string_value", Ci.nsIWindowsRegKey.TYPE_STRING]}}},
  //  values: {}
  //  },
  //  ...
  // }
  static roots;

  constructor() {
    MockRegistry.roots = new Map([
      [
        Ci.nsIWindowsRegKey.ROOT_KEY_LOCAL_MACHINE,
        { subkeys: new Map(), values: new Map() },
      ],
      [
        Ci.nsIWindowsRegKey.ROOT_KEY_CURRENT_USER,
        { subkeys: new Map(), values: new Map() },
      ],
      [
        Ci.nsIWindowsRegKey.ROOT_KEY_CLASSES_ROOT,
        { subkeys: new Map(), values: new Map() },
      ],
    ]);

    // See bug 1688838 - nsNotifyAddrListener::CheckAdaptersAddresses might
    // attempt to use the registry off the main thread, so we disable that
    // feature while the mock registry is active.
    this.oldSuffixListPref = Services.prefs.getBoolPref(
      "network.notify.dnsSuffixList"
    );
    Services.prefs.setBoolPref("network.notify.dnsSuffixList", false);

    this.oldCheckForProxiesPref = Services.prefs.getBoolPref(
      "network.notify.checkForProxies"
    );
    Services.prefs.setBoolPref("network.notify.checkForProxies", false);

    this.oldCheckForNRPTPref = Services.prefs.getBoolPref(
      "network.notify.checkForNRPT"
    );
    Services.prefs.setBoolPref("network.notify.checkForNRPT", false);

    this.cid = MockRegistrar.register(
      "@mozilla.org/windows-registry-key;1",
      () => new MockWindowsRegKey()
    );
  }

  shutdown() {
    MockRegistrar.unregister(this.cid);
    Services.prefs.setBoolPref(
      "network.notify.dnsSuffixList",
      this.oldSuffixListPref
    );
    Services.prefs.setBoolPref(
      "network.notify.checkForProxies",
      this.oldCheckForProxiesPref
    );
    Services.prefs.setBoolPref(
      "network.notify.checkForNRPT",
      this.oldCheckForNRPTPref
    );
    this.cid = null;
  }

  static getRoot(root) {
    if (!this.roots.has(root)) {
      throw new Error(`No such root ${root}`);
    }
    return this.roots.get(root);
  }

  setValue(root, path, name, value, type = Ci.nsIWindowsRegKey.TYPE_STRING) {
    let key = new MockWindowsRegKey();
    key.create(root, path, Ci.nsIWindowsRegKey.ACCESS_ALL);
    if (value == null) {
      try {
        key.removeValue(name);
      } catch (e) {
        if (
          !(e instanceof Ci.nsIException && e.result == Cr.NS_ERROR_FAILURE)
        ) {
          throw e;
        }
      }
    } else {
      switch (type) {
        case Ci.nsIWindowsRegKey.TYPE_STRING:
          key.writeStringValue(name, value);
          break;
        case Ci.nsIWindowsRegKey.TYPE_BINARY:
          key.writeBinaryValue(name, value);
          break;
        case Ci.nsIWindowsRegKey.TYPE_INT:
          key.writeIntValue(name, value);
          break;
        case Ci.nsIWindowsRegKey.TYPE_INT64:
          key.writeInt64Value(name, value);
          break;
      }
    }
  }

  /**
   * Dump given `key` (or, if not given, all roots), and all its value and its
   * subkeys recursively, using the given function to `printOneLine`.
   */
  static dump(key = null, indent = "", printOneLine = console.log) {
    let types = new Map([
      [1, "REG_SZ"],
      [3, "REG_BINARY"],
      [4, "REG_DWORD"],
      [11, "REG_QWORD"],
    ]);

    if (!key) {
      let roots = [
        "ROOT_KEY_LOCAL_MACHINE",
        "ROOT_KEY_CURRENT_USER",
        "ROOT_KEY_CLASSES_ROOT",
      ];
      for (let root of roots) {
        printOneLine(indent + root);
        this.dump(
          this.roots.get(Ci.nsIWindowsRegKey[root]),
          "  " + indent,
          printOneLine
        );
      }
    } else {
      for (let [k, v] of key.values.entries()) {
        let [value, type] = v;
        printOneLine(`${indent}${k}: ${value} (${types.get(type)})`);
      }
      for (let [k, child] of key.subkeys.entries()) {
        printOneLine(indent + k);
        this.dump(child, "  " + indent, printOneLine);
      }
    }
  }
}

[ Dauer der Verarbeitung: 0.4 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