Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Firefox/toolkit/mozapps/extensions/test/xpcshell/   (Browser von der Mozilla Stiftung Version 136.0.1©)  Datei vom 10.2.2025 mit Größe 32 kB image not shown  

Quelle  head_addons.js   Sprache: JAVA

 
/* Any copyright is dedicated to the Public Domain.
 * http://creativecommons.org/publicdomain/zero/1.0/
 */


/* eslint no-unused-vars: ["error", {vars: "local", args: "none"}] */

if (!_TEST_NAME.includes("toolkit/mozapps/extensions/test/xpcshell/")) {
  Assert.ok(
    false,
    "head_addons.js may not be loaded by tests outside of " +
      "the add-on manager component."
  );
}

const PREF_EM_CHECK_UPDATE_SECURITY = "extensions.checkUpdateSecurity";
const PREF_EM_STRICT_COMPATIBILITY = "extensions.strictCompatibility";
const PREF_GETADDONS_BYIDS = "extensions.getAddons.get.url";
const PREF_XPI_SIGNATURES_REQUIRED = "xpinstall.signatures.required";

// Maximum error in file modification times. Some file systems don't store
// modification times exactly. As long as we are closer than this then it
// still passes.
const MAX_TIME_DIFFERENCE = 3000;

// Time to reset file modified time relative to Date.now() so we can test that
// times are modified (10 hours old).
const MAKE_FILE_OLD_DIFFERENCE = 10 * 3600 * 1000;

const { AddonManager, AddonManagerPrivate } = ChromeUtils.importESModule(
  "resource://gre/modules/AddonManager.sys.mjs"
);
var { AppConstants } = ChromeUtils.importESModule(
  "resource://gre/modules/AppConstants.sys.mjs"
);
var { FileUtils } = ChromeUtils.importESModule(
  "resource://gre/modules/FileUtils.sys.mjs"
);
var { NetUtil } = ChromeUtils.importESModule(
  "resource://gre/modules/NetUtil.sys.mjs"
);
var { XPCOMUtils } = ChromeUtils.importESModule(
  "resource://gre/modules/XPCOMUtils.sys.mjs"
);
var { AddonRepository } = ChromeUtils.importESModule(
  "resource://gre/modules/addons/AddonRepository.sys.mjs"
);

var { AddonTestUtils, MockAsyncShutdown } = ChromeUtils.importESModule(
  "resource://testing-common/AddonTestUtils.sys.mjs"
);

ChromeUtils.defineESModuleGetters(this, {
  Blocklist: "resource://gre/modules/Blocklist.sys.mjs",
  Extension: "resource://gre/modules/Extension.sys.mjs",
  ExtensionTestCommon: "resource://testing-common/ExtensionTestCommon.sys.mjs",
  ExtensionTestUtils:
    "resource://testing-common/ExtensionXPCShellUtils.sys.mjs",
  HttpServer: "resource://testing-common/httpd.sys.mjs",
  MockRegistrar: "resource://testing-common/MockRegistrar.sys.mjs",
  MockRegistry: "resource://testing-common/MockRegistry.sys.mjs",
  PromiseTestUtils: "resource://testing-common/PromiseTestUtils.sys.mjs",
  RemoteSettings: "resource://services-settings/remote-settings.sys.mjs",
  TestUtils: "resource://testing-common/TestUtils.sys.mjs",
  setTimeout: "resource://gre/modules/Timer.sys.mjs",
});

XPCOMUtils.defineLazyServiceGetter(
  this,
  "aomStartup",
  "@mozilla.org/addons/addon-manager-startup;1",
  "amIAddonManagerStartup"
);

const {
  createAppInfo,
  createHttpServer,
  createTempWebExtensionFile,
  getFileForAddon,
  manuallyInstall,
  manuallyUninstall,
  overrideBuiltIns,
  promiseAddonEvent,
  promiseCompleteAllInstalls,
  promiseCompleteInstall,
  promiseConsoleOutput,
  promiseFindAddonUpdates,
  promiseInstallAllFiles,
  promiseInstallFile,
  promiseRestartManager,
  promiseSetExtensionModifiedTime,
  promiseShutdownManager,
  promiseStartupManager,
  promiseWebExtensionStartup,
  promiseWriteProxyFileToDir,
  registerDirectory,
  setExtensionModifiedTime,
  writeFilesToZip,
} = AddonTestUtils;

// WebExtension wrapper for ease of testing
ExtensionTestUtils.init(this);

AddonTestUtils.init(this);
AddonTestUtils.overrideCertDB();

ChromeUtils.defineLazyGetter(
  this,
  "BOOTSTRAP_REASONS",
  () => AddonManagerPrivate.BOOTSTRAP_REASONS
);

function getReasonName(reason) {
  for (let key of Object.keys(BOOTSTRAP_REASONS)) {
    if (BOOTSTRAP_REASONS[key] == reason) {
      return key;
    }
  }
  throw new Error("This shouldn't happen.");
}

Object.defineProperty(this"gAppInfo", {
  get() {
    return AddonTestUtils.appInfo;
  },
});

Object.defineProperty(this"gAddonStartup", {
  get() {
    return AddonTestUtils.addonStartup.clone();
  },
});

Object.defineProperty(this"gInternalManager", {
  get() {
    return AddonTestUtils.addonIntegrationService.QueryInterface(
      Ci.nsITimerCallback
    );
  },
});

Object.defineProperty(this"gProfD", {
  get() {
    return AddonTestUtils.profileDir.clone();
  },
});

Object.defineProperty(this"gTmpD", {
  get() {
    return AddonTestUtils.tempDir.clone();
  },
});

Object.defineProperty(this"gUseRealCertChecks", {
  get() {
    return AddonTestUtils.useRealCertChecks;
  },
  set(val) {
    AddonTestUtils.useRealCertChecks = val;
  },
});

Object.defineProperty(this"TEST_UNPACKED", {
  get() {
    return AddonTestUtils.testUnpacked;
  },
  set(val) {
    AddonTestUtils.testUnpacked = val;
  },
});

const promiseAddonByID = AddonManager.getAddonByID;
const promiseAddonsByIDs = AddonManager.getAddonsByIDs;
const promiseAddonsByTypes = AddonManager.getAddonsByTypes;

var gPort = null;

var BootstrapMonitor = {
  started: new Map(),
  stopped: new Map(),
  installed: new Map(),
  uninstalled: new Map(),

  init() {
    this.onEvent = this.onEvent.bind(this);

    AddonTestUtils.on("addon-manager-shutdown"this.onEvent);
    AddonTestUtils.on("bootstrap-method"this.onEvent);
  },

  shutdownCheck() {
    equal(
      this.started.size,
      0,
      "Should have no add-ons that were started but not shutdown"
    );
  },

  onEvent(msg, data) {
    switch (msg) {
      case "addon-manager-shutdown":
        this.shutdownCheck();
        break;
      case "bootstrap-method":
        this.onBootstrapMethod(data.method, data.params, data.reason);
        break;
    }
  },

  onBootstrapMethod(method, params, reason) {
    let { id } = params;

    info(
      `Bootstrap method ${method} ${reason} for ${params.id} version ${params.version}`
    );

    if (method !== "install") {
      this.checkInstalled(id);
    }

    switch (method) {
      case "install":
        this.checkNotInstalled(id);
        this.installed.set(id, { reason, params });
        this.uninstalled.delete(id);
        break;
      case "startup":
        this.checkNotStarted(id);
        this.started.set(id, { reason, params });
        this.stopped.delete(id);
        break;
      case "shutdown":
        this.checkMatches("shutdown""startup", params, this.started.get(id));
        this.checkStarted(id);
        this.stopped.set(id, { reason, params });
        this.started.delete(id);
        break;
      case "uninstall":
        this.checkMatches(
          "uninstall",
          "install",
          params,
          this.installed.get(id)
        );
        this.uninstalled.set(id, { reason, params });
        this.installed.delete(id);
        break;
      case "update":
        this.checkMatches("update""install", params, this.installed.get(id));
        this.installed.set(id, { reason, params, method });
        break;
    }
  },

  clear(id) {
    this.installed.delete(id);
    this.started.delete(id);
    this.stopped.delete(id);
    this.uninstalled.delete(id);
  },

  checkMatches(method, lastMethod, params, { params: lastParams } = {}) {
    ok(
      lastParams,
      `Expecting matching ${lastMethod} call for add-on ${params.id} ${method} call`
    );

    if (method == "update") {
      equal(
        params.oldVersion,
        lastParams.version,
        "params.oldVersion should match last call"
      );
    } else {
      equal(
        params.version,
        lastParams.version,
        "params.version should match last call"
      );
    }

    if (method !== "update" && method !== "uninstall") {
      equal(
        params.resourceURI.spec,
        lastParams.resourceURI.spec,
        `params.resourceURI should match last call`
      );

      ok(
        params.resourceURI.equals(lastParams.resourceURI),
        `params.resourceURI should match: "${params.resourceURI.spec}" == "${lastParams.resourceURI.spec}"`
      );
    }
  },

  checkStarted(id, version = undefined) {
    let started = this.started.get(id);
    ok(started, `Should have seen startup method call for ${id}`);

    if (version !== undefined) {
      equal(started.params.version, version, "Expected version number");
    }
    return started;
  },

  checkNotStarted(id) {
    ok(
      !this.started.has(id),
      `Should not have seen startup method call for ${id}`
    );
  },

  checkInstalled(id, version = undefined) {
    const installed = this.installed.get(id);
    ok(installed, `Should have seen install call for ${id}`);

    if (version !== undefined) {
      equal(installed.params.version, version, "Expected version number");
    }

    return installed;
  },

  checkUpdated(id, version = undefined) {
    const installed = this.installed.get(id);
    equal(installed.method, "update", `Should have seen update call for ${id}`);

    if (version !== undefined) {
      equal(installed.params.version, version, "Expected version number");
    }

    return installed;
  },

  checkNotInstalled(id) {
    ok(
      !this.installed.has(id),
      `Should not have seen install method call for ${id}`
    );
  },
};

function isNightlyChannel() {
  var channel = Services.prefs.getCharPref("app.update.channel""default");

  return (
    channel != "aurora" &&
    channel != "beta" &&
    channel != "release" &&
    channel != "esr"
  );
}

async function restartWithLocales(locales) {
  Services.locale.requestedLocales = locales;
  await promiseRestartManager();
}

function delay(msec) {
  return new Promise(resolve => {
    setTimeout(resolve, msec);
  });
}

/**
 * Returns a map of Addon objects for installed add-ons with the given
 * IDs. The returned map contains a key for the ID of each add-on that
 * is found. IDs for add-ons which do not exist are not present in the
 * map.
 *
 * @param {sequence<string>} ids
 *        The list of add-on IDs to get.
 * @returns {Promise<string, Addon>}
 *        Map of add-ons that were found.
 */

async function getAddons(ids) {
  let addons = new Map();
  for (let addon of await AddonManager.getAddonsByIDs(ids)) {
    if (addon) {
      addons.set(addon.id, addon);
    }
  }
  return addons;
}

/**
 * Checks that the given add-on has the given expected properties.
 *
 * @param {string} id
 *        The id of the add-on.
 * @param {Addon?} addon
 *        The add-on object, or null if the add-on does not exist.
 * @param {object?} expected
 *        An object containing the expected values for properties of the
 *        add-on, or null if the add-on is expected not to exist.
 */

function checkAddon(id, addon, expected) {
  info(`Checking state of addon ${id}`);

  if (expected === null) {
    ok(!addon, `Addon ${id} should not exist`);
  } else {
    ok(addon, `Addon ${id} should exist`);
    for (let [key, value] of Object.entries(expected)) {
      if (value instanceof Ci.nsIURI) {
        equal(
          addon[key] && addon[key].spec,
          value.spec,
          `Expected value of addon.${key}`
        );
      } else {
        deepEqual(addon[key], value, `Expected value of addon.${key}`);
      }
    }
  }
}

/**
 * Tests that an add-on does appear in the crash report annotations, if
 * crash reporting is enabled. The test will fail if the add-on is not in the
 * annotation.
 * @param  aId
 *         The ID of the add-on
 * @param  aVersion
 *         The version of the add-on
 */

function do_check_in_crash_annotation(aId, aVersion) {
  if (!AppConstants.MOZ_CRASHREPORTER) {
    return;
  }

  if (!("Add-ons" in gAppInfo.annotations)) {
    Assert.ok(false"Cannot find Add-ons entry in crash annotations");
    return;
  }

  let addons = gAppInfo.annotations["Add-ons"].split(",");
  Assert.ok(
    addons.includes(
      `${encodeURIComponent(aId)}:${encodeURIComponent(aVersion)}`
    )
  );
}

/**
 * Tests that an add-on does not appear in the crash report annotations, if
 * crash reporting is enabled. The test will fail if the add-on is in the
 * annotation.
 * @param  aId
 *         The ID of the add-on
 * @param  aVersion
 *         The version of the add-on
 */

function do_check_not_in_crash_annotation(aId, aVersion) {
  if (!AppConstants.MOZ_CRASHREPORTER) {
    return;
  }

  if (!("Add-ons" in gAppInfo.annotations)) {
    Assert.ok(true);
    return;
  }

  let addons = gAppInfo.annotations["Add-ons"].split(",");
  Assert.ok(
    !addons.includes(
      `${encodeURIComponent(aId)}:${encodeURIComponent(aVersion)}`
    )
  );
}

function do_get_file_hash(aFile, aAlgorithm) {
  if (!aAlgorithm) {
    aAlgorithm = "sha256";
  }

  let crypto = Cc["@mozilla.org/security/hash;1"].createInstance(
    Ci.nsICryptoHash
  );
  crypto.initWithString(aAlgorithm);
  let fis = Cc["@mozilla.org/network/file-input-stream;1"].createInstance(
    Ci.nsIFileInputStream
  );
  fis.init(aFile, -1, -1, false);
  crypto.updateFromStream(fis, aFile.fileSize);

  // return the two-digit hexadecimal code for a byte
  let toHexString = charCode => ("0" + charCode.toString(16)).slice(-2);

  let binary = crypto.finish(false);
  let hash = Array.from(binary, c => toHexString(c.charCodeAt(0)));
  return aAlgorithm + ":" + hash.join("");
}

/**
 * Returns an extension uri spec
 *
 * @param  aProfileDir
 *         The extension install directory
 * @return a uri spec pointing to the root of the extension
 */

function do_get_addon_root_uri(aProfileDir, aId) {
  let path = aProfileDir.clone();
  path.append(aId);
  if (!path.exists()) {
    path.leafName += ".xpi";
    return "jar:" + Services.io.newFileURI(path).spec + "!/";
  }
  return Services.io.newFileURI(path).spec;
}

function do_get_expected_addon_name(aId) {
  if (TEST_UNPACKED) {
    return aId;
  }
  return aId + ".xpi";
}

/**
 * Returns the file containing the add-on. For packed add-ons, this is
 * an XPI file. For unpacked add-ons, it is the add-on's root directory.
 *
 * @param {Addon} addon
 * @returns {nsIFile}
 */

function getAddonFile(addon) {
  let uri = addon.getResourceURI("");
  if (uri instanceof Ci.nsIJARURI) {
    uri = uri.JARFile;
  }
  return uri.QueryInterface(Ci.nsIFileURL).file;
}

/**
 * Check that an array of actual add-ons is the same as an array of
 * expected add-ons.
 *
 * @param  aActualAddons
 *         The array of actual add-ons to check.
 * @param  aExpectedAddons
 *         The array of expected add-ons to check against.
 * @param  aProperties
 *         An array of properties to check.
 */

function do_check_addons(aActualAddons, aExpectedAddons, aProperties) {
  Assert.notEqual(aActualAddons, null);
  Assert.equal(aActualAddons.length, aExpectedAddons.length);
  for (let i = 0; i < aActualAddons.length; i++) {
    do_check_addon(aActualAddons[i], aExpectedAddons[i], aProperties);
  }
}

/**
 * Check that the actual add-on is the same as the expected add-on.
 *
 * @param  aActualAddon
 *         The actual add-on to check.
 * @param  aExpectedAddon
 *         The expected add-on to check against.
 * @param  aProperties
 *         An array of properties to check.
 */

function do_check_addon(aActualAddon, aExpectedAddon, aProperties) {
  Assert.notEqual(aActualAddon, null);

  aProperties.forEach(function (aProperty) {
    let actualValue = aActualAddon[aProperty];
    let expectedValue = aExpectedAddon[aProperty];

    // Check that all undefined expected properties are null on actual add-on
    if (!(aProperty in aExpectedAddon)) {
      if (actualValue !== undefined && actualValue !== null) {
        do_throw(
          "Unexpected defined/non-null property for add-on " +
            aExpectedAddon.id +
            " (addon[" +
            aProperty +
            "] = " +
            actualValue.toSource() +
            ")"
        );
      }

      return;
    } else if (expectedValue && !actualValue) {
      do_throw(
        "Missing property for add-on " +
          aExpectedAddon.id +
          ": expected addon[" +
          aProperty +
          "] = " +
          expectedValue
      );
      return;
    }

    switch (aProperty) {
      case "creator":
        do_check_author(actualValue, expectedValue);
        break;

      case "developers":
        Assert.equal(actualValue.length, expectedValue.length);
        for (let i = 0; i < actualValue.length; i++) {
          do_check_author(actualValue[i], expectedValue[i]);
        }
        break;

      case "screenshots":
        Assert.equal(actualValue.length, expectedValue.length);
        for (let i = 0; i < actualValue.length; i++) {
          do_check_screenshot(actualValue[i], expectedValue[i]);
        }
        break;

      case "sourceURI":
        Assert.equal(actualValue.spec, expectedValue);
        break;

      case "updateDate":
        Assert.equal(actualValue.getTime(), expectedValue.getTime());
        break;

      case "compatibilityOverrides":
        Assert.equal(actualValue.length, expectedValue.length);
        for (let i = 0; i < actualValue.length; i++) {
          do_check_compatibilityoverride(actualValue[i], expectedValue[i]);
        }
        break;

      case "icons":
        do_check_icons(actualValue, expectedValue);
        break;

      default:
        if (actualValue !== expectedValue) {
          do_throw(
            "Failed for " +
              aProperty +
              " for add-on " +
              aExpectedAddon.id +
              " (" +
              actualValue +
              " === " +
              expectedValue +
              ")"
          );
        }
    }
  });
}

/**
 * Check that the actual author is the same as the expected author.
 *
 * @param  aActual
 *         The actual author to check.
 * @param  aExpected
 *         The expected author to check against.
 */

function do_check_author(aActual, aExpected) {
  Assert.equal(aActual.toString(), aExpected.name);
  Assert.equal(aActual.name, aExpected.name);
  Assert.equal(aActual.url, aExpected.url);
}

/**
 * Check that the actual screenshot is the same as the expected screenshot.
 *
 * @param  aActual
 *         The actual screenshot to check.
 * @param  aExpected
 *         The expected screenshot to check against.
 */

function do_check_screenshot(aActual, aExpected) {
  Assert.equal(aActual.toString(), aExpected.url);
  Assert.equal(aActual.url, aExpected.url);
  Assert.equal(aActual.width, aExpected.width);
  Assert.equal(aActual.height, aExpected.height);
  Assert.equal(aActual.thumbnailURL, aExpected.thumbnailURL);
  Assert.equal(aActual.thumbnailWidth, aExpected.thumbnailWidth);
  Assert.equal(aActual.thumbnailHeight, aExpected.thumbnailHeight);
  Assert.equal(aActual.caption, aExpected.caption);
}

/**
 * Check that the actual compatibility override is the same as the expected
 * compatibility override.
 *
 * @param  aAction
 *         The actual compatibility override to check.
 * @param  aExpected
 *         The expected compatibility override to check against.
 */

function do_check_compatibilityoverride(aActual, aExpected) {
  Assert.equal(aActual.type, aExpected.type);
  Assert.equal(aActual.minVersion, aExpected.minVersion);
  Assert.equal(aActual.maxVersion, aExpected.maxVersion);
  Assert.equal(aActual.appID, aExpected.appID);
  Assert.equal(aActual.appMinVersion, aExpected.appMinVersion);
  Assert.equal(aActual.appMaxVersion, aExpected.appMaxVersion);
}

function do_check_icons(aActual, aExpected) {
  for (var size in aExpected) {
    Assert.equal(aActual[size], aExpected[size]);
  }
}

function isThemeInAddonsList(aDir, aId) {
  return AddonTestUtils.addonsList.hasTheme(aDir, aId);
}

function isExtensionInBootstrappedList(aDir, aId) {
  return AddonTestUtils.addonsList.hasExtension(aDir, aId);
}

/**
 * Writes a manifest.json manifest into an extension using the properties passed
 * in a JS object.
 *
 * @param   aManifest
 *          The data to write
 * @param   aDir
 *          The install directory to add the extension to
 * @param   aId
 *          An optional string to override the default installation aId
 * @return  A file pointing to where the extension was installed
 */

function promiseWriteWebManifestForExtension(aData, aDir, aId) {
  let files = {
    "manifest.json": JSON.stringify(aData),
  };
  if (!aId) {
    aId =
      aData?.browser_specific_settings?.gecko?.id ||
      aData?.applications?.gecko?.id;
  }
  return AddonTestUtils.promiseWriteFilesToExtension(aDir.path, aId, files);
}

function hasFlag(aBits, aFlag) {
  return (aBits & aFlag) != 0;
}

class EventChecker {
  constructor(options) {
    this.expectedEvents = options.addonEvents || {};
    this.expectedInstalls = options.installEvents || null;
    this.ignorePlugins = options.ignorePlugins || false;

    this.finished = new Promise(resolve => {
      this.resolveFinished = resolve;
    });

    AddonManager.addAddonListener(this);
    if (this.expectedInstalls) {
      AddonManager.addInstallListener(this);
    }
  }

  cleanup() {
    AddonManager.removeAddonListener(this);
    if (this.expectedInstalls) {
      AddonManager.removeInstallListener(this);
    }
  }

  checkValue(prop, value, flagName) {
    if (Array.isArray(flagName)) {
      let names = flagName.map(name => `AddonManager.${name}`);

      Assert.ok(
        flagName.map(name => AddonManager[name]).includes(value),
        `${prop} value \`${value}\` should be one of [${names.join(", ")}`
      );
    } else {
      Assert.equal(
        value,
        AddonManager[flagName],
        `${prop} should have value AddonManager.${flagName}`
      );
    }
  }

  checkFlag(prop, value, flagName) {
    Assert.equal(
      value & AddonManager[flagName],
      AddonManager[flagName],
      `${prop} should have flag AddonManager.${flagName}`
    );
  }

  checkNoFlag(prop, value, flagName) {
    Assert.ok(
      !(value & AddonManager[flagName]),
      `${prop} should not have flag AddonManager.${flagName}`
    );
  }

  checkComplete() {
    if (this.expectedInstalls && this.expectedInstalls.length) {
      return;
    }

    if (Object.values(this.expectedEvents).some(events => events.length)) {
      return;
    }

    info("Test complete");
    this.cleanup();
    this.resolveFinished();
  }

  ensureComplete() {
    this.cleanup();

    for (let [id, events] of Object.entries(this.expectedEvents)) {
      Assert.equal(
        events.length,
        0,
        `Should have no remaining events for ${id}`
      );
    }
    if (this.expectedInstalls) {
      Assert.deepEqual(
        this.expectedInstalls,
        [],
        "Should have no remaining install events"
      );
    }
  }

  // Add-on listener events
  getExpectedEvent(aId) {
    if (!(aId in this.expectedEvents)) {
      return null;
    }

    let events = this.expectedEvents[aId];
    Assert.ok(!!events.length, `Should be expecting events for ${aId}`);

    return events.shift();
  }

  checkAddonEvent(event, addon, details = {}) {
    info(`Got event "${event}" for add-on ${addon.id}`);

    if ("requiresRestart" in details) {
      Assert.equal(
        details.requiresRestart,
        false,
        "requiresRestart should always be false"
      );
    }

    let expected = this.getExpectedEvent(addon.id);
    if (!expected) {
      return undefined;
    }

    Assert.equal(
      expected.event,
      event,
      `Expecting event "${expected.event}" got "${event}"`
    );

    for (let prop of ["properties"]) {
      if (prop in expected) {
        Assert.deepEqual(
          expected[prop],
          details[prop],
          `Expected value for ${prop}`
        );
      }
    }

    this.checkComplete();

    if ("returnValue" in expected) {
      return expected.returnValue;
    }
    return undefined;
  }

  onPropertyChanged(addon, properties) {
    return this.checkAddonEvent("onPropertyChanged", addon, { properties });
  }

  onEnabling(addon, requiresRestart) {
    let result = this.checkAddonEvent("onEnabling", addon, { requiresRestart });

    this.checkNoFlag("addon.permissions", addon.permissions, "PERM_CAN_ENABLE");

    return result;
  }

  onEnabled(addon) {
    let result = this.checkAddonEvent("onEnabled", addon);

    this.checkNoFlag("addon.permissions", addon.permissions, "PERM_CAN_ENABLE");

    return result;
  }

  onDisabling(addon, requiresRestart) {
    let result = this.checkAddonEvent("onDisabling", addon, {
      requiresRestart,
    });

    this.checkNoFlag(
      "addon.permissions",
      addon.permissions,
      "PERM_CAN_DISABLE"
    );
    return result;
  }

  onDisabled(addon) {
    let result = this.checkAddonEvent("onDisabled", addon);

    this.checkNoFlag(
      "addon.permissions",
      addon.permissions,
      "PERM_CAN_DISABLE"
    );

    return result;
  }

  onInstalling(addon, requiresRestart) {
    return this.checkAddonEvent("onInstalling", addon, { requiresRestart });
  }

  onInstalled(addon) {
    return this.checkAddonEvent("onInstalled", addon);
  }

  onUninstalling(addon) {
    return this.checkAddonEvent("onUninstalling", addon);
  }

  onUninstalled(addon) {
    return this.checkAddonEvent("onUninstalled", addon);
  }

  onOperationCancelled(addon) {
    return this.checkAddonEvent("onOperationCancelled", addon);
  }

  // Install listener events.
  checkInstall(event, install, details = {}) {
    // Lazy initialization of the plugin host means we can get spurious
    // install events for plugins. If we're not looking for plugin
    // installs, ignore them completely. If we *are* looking for plugin
    // installs, the onus is on the individual test to ensure it waits
    // for the plugin host to have done its initial work.
    if (this.ignorePlugins && install.type == "plugin") {
      info(`Ignoring install event for plugin ${install.id}`);
      return undefined;
    }
    info(`Got install event "${event}"`);

    let expected = this.expectedInstalls.shift();
    Assert.ok(expected, "Should be expecting install event");

    Assert.equal(
      expected.event,
      event,
      "Should be expecting onExternalInstall event"
    );

    if ("state" in details) {
      this.checkValue("install.state", install.state, details.state);
    }

    this.checkComplete();

    if ("callback" in expected) {
      expected.callback(install);
    }

    if ("returnValue" in expected) {
      return expected.returnValue;
    }
    return undefined;
  }

  onNewInstall(install) {
    let result = this.checkInstall("onNewInstall", install, {
      state: ["STATE_DOWNLOADED""STATE_DOWNLOAD_FAILED""STATE_AVAILABLE"],
    });

    if (install.state != AddonManager.STATE_DOWNLOAD_FAILED) {
      Assert.equal(install.error, 0, "Should have no error");
    } else {
      Assert.notEqual(install.error, 0, "Should have error");
    }

    return result;
  }

  onDownloadStarted(install) {
    return this.checkInstall("onDownloadStarted", install, {
      state: "STATE_DOWNLOADING",
      error: 0,
    });
  }

  onDownloadEnded(install) {
    return this.checkInstall("onDownloadEnded", install, {
      state: "STATE_DOWNLOADED",
      error: 0,
    });
  }

  onDownloadFailed(install) {
    return this.checkInstall("onDownloadFailed", install, {
      state: "STATE_FAILED",
    });
  }

  onDownloadCancelled(install) {
    return this.checkInstall("onDownloadCancelled", install, {
      state: "STATE_CANCELLED",
      error: 0,
    });
  }

  onInstallStarted(install) {
    return this.checkInstall("onInstallStarted", install, {
      state: "STATE_INSTALLING",
      error: 0,
    });
  }

  onInstallEnded(install) {
    return this.checkInstall("onInstallEnded", install, {
      state: "STATE_INSTALLED",
      error: 0,
    });
  }

  onInstallFailed(install) {
    return this.checkInstall("onInstallFailed", install, {
      state: "STATE_FAILED",
    });
  }

  onInstallCancelled(install) {
    // If the install was cancelled by a listener returning false from
    // onInstallStarted, then the state will revert to STATE_DOWNLOADED.
    return this.checkInstall("onInstallCancelled", install, {
      state: ["STATE_CANCELED""STATE_DOWNLOADED"],
      error: 0,
    });
  }

  onExternalInstall(addon, existingAddon, requiresRestart) {
    if (this.ignorePlugins && addon.type == "plugin") {
      info(`Ignoring install event for plugin ${addon.id}`);
      return undefined;
    }
    let expected = this.expectedInstalls.shift();
    Assert.ok(expected, "Should be expecting install event");

    Assert.equal(
      expected.event,
      "onExternalInstall",
      "Should be expecting onExternalInstall event"
    );
    Assert.ok(!requiresRestart, "Should never require restart");

    this.checkComplete();
    if ("returnValue" in expected) {
      return expected.returnValue;
    }
    return undefined;
  }
}

/**
 * Run the giving callback function, and expect the given set of add-on
 * and install listener events to be emitted, and returns a promise
 * which resolves when they have all been observed.
 *
 * If `callback` returns a promise, all events are expected to be
 * observed by the time the promise resolves. If not, simply waits for
 * all events to be observed before resolving the returned promise.
 *
 * @param {object} details
 * @param {function} callback
 * @returns {Promise}
 */

/* exported expectEvents */
async function expectEvents(details, callback) {
  let checker = new EventChecker(details);

  try {
    let result = callback();

    if (
      result &&
      typeof result === "object" &&
      typeof result.then === "function"
    ) {
      result = await result;
      checker.ensureComplete();
    } else {
      await checker.finished;
    }

    return result;
  } catch (e) {
    do_throw(e);
    return undefined;
  }
}

const EXTENSIONS_DB = "extensions.json";
var gExtensionsJSON = gProfD.clone();
gExtensionsJSON.append(EXTENSIONS_DB);

async function promiseInstallWebExtension(aData) {
  let addonFile = createTempWebExtensionFile(aData);

  let { addon } = await promiseInstallFile(addonFile);
  return addon;
}

// By default use strict compatibility
Services.prefs.setBoolPref("extensions.strictCompatibility"true);

// Ensure signature checks are enabled by default
Services.prefs.setBoolPref(PREF_XPI_SIGNATURES_REQUIRED, true);

Services.prefs.setBoolPref("extensions.experiments.enabled"true);

// Copies blocklistFile (an nsIFile) to gProfD/blocklist.xml.
function copyBlocklistToProfile(blocklistFile) {
  var dest = gProfD.clone();
  dest.append("blocklist.xml");
  if (dest.exists()) {
    dest.remove(false);
  }
  blocklistFile.copyTo(gProfD, "blocklist.xml");
  dest.lastModifiedTime = Date.now();
}

async function mockGfxBlocklistItemsFromDisk(path) {
  let response = await fetch(Services.io.newFileURI(do_get_file(path)).spec);
  let json = await response.json();
  return mockGfxBlocklistItems(json);
}

async function mockGfxBlocklistItems(items) {
  const { generateUUID } = Services.uuid;
  const { BlocklistPrivate } = ChromeUtils.importESModule(
    "resource://gre/modules/Blocklist.sys.mjs"
  );
  const client = RemoteSettings("gfx", {
    bucketName: "blocklists",
  });
  const records = items.map(item => {
    if (item.id && item.last_modified) {
      return item;
    }
    return {
      id: generateUUID().toString().replace(/[{}]/g, ""),
      last_modified: Date.now(),
      ...item,
    };
  });
  const collectionTimestamp = Math.max(...records.map(r => r.last_modified));
  await client.db.importChanges({}, collectionTimestamp, records, {
    clear: true,
  });
  let rv = await BlocklistPrivate.GfxBlocklistRS.checkForEntries();
  return rv;
}

/**
 * Change the schema version of the JSON extensions database
 */

async function changeXPIDBVersion(aNewVersion) {
  let json = await IOUtils.readJSON(gExtensionsJSON.path);
  json.schemaVersion = aNewVersion;
  await IOUtils.writeJSON(gExtensionsJSON.path, json);
}

async function setInitialState(addon, initialState) {
  if (initialState.userDisabled) {
    await addon.disable();
  } else if (initialState.userDisabled === false) {
    await addon.enable();
  }
}

async function setupBuiltinExtension(extensionData, location = "ext-test") {
  let xpi = await AddonTestUtils.createTempWebExtensionFile(extensionData);

  // The built-in location requires a resource: URL that maps to a
  // jar: or file: URL.  This would typically be something bundled
  // into omni.ja but for testing we just use a temp file.
  let base = Services.io.newURI(`jar:file:${xpi.path}!/`);
  let resProto = Services.io
    .getProtocolHandler("resource")
    .QueryInterface(Ci.nsIResProtocolHandler);
  resProto.setSubstitution(location, base);
}

async function installBuiltinExtension(extensionData, waitForStartup = true) {
  await setupBuiltinExtension(extensionData);

  let id =
    extensionData.manifest?.browser_specific_settings?.gecko?.id ||
    extensionData.manifest?.applications?.gecko?.id;
  let wrapper = ExtensionTestUtils.expectExtension(id);
  await AddonManager.installBuiltinAddon("resource://ext-test/");
  if (waitForStartup) {
    await wrapper.awaitStartup();
  }
  return wrapper;
}

function useAMOStageCert() {
  // NOTE: add_task internally calls add_test which mutate the add_task properties object,
  // and so we should not reuse the same object as add_task options passed to multiple
  // add_task calls.
  return { pref_set: [["xpinstall.signatures.dev-root"true]] };
}

Messung V0.5
C=95 H=84 G=89

¤ Dauer der Verarbeitung: 0.13 Sekunden  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.