Commit 43518b0a authored by Thomas Wisniewski's avatar Thomas Wisniewski Committed by twisniewski@mozilla.com
Browse files

Bug 1966735 - fix some logic with the webcompat addon related to...

Bug 1966735 - fix some logic with the webcompat addon related to enabling/disabling inteventions; r=denschub,webcompat-reviewers

Differential Revision: https://phabricator.services.mozilla.com/D249820
parent efd4a9b4
Loading
Loading
Loading
Loading
+9 −1
Changes for browser/extensions/webcompat/lib/interventions.js: 9 added lines, 1 removed line.
Original line number Diff line number Diff line
@@ -246,6 +246,10 @@ class Interventions {
      .filter(v => v !== undefined);

    for (const intervention of config.interventions) {
      if (!intervention.enabled) {
        continue;
      }

      await this._changeCustomFuncs("enable", label, intervention, config);
      if (intervention.content_scripts) {
        await this._enableContentScripts(
@@ -287,6 +291,10 @@ class Interventions {
    }

    for (const intervention of interventions) {
      if (!intervention.enabled) {
        continue;
      }

      await this._changeCustomFuncs("disable", label, intervention, config);
      if (intervention.content_scripts) {
        await this._disableContentScripts(label, intervention);
@@ -461,7 +469,7 @@ class Interventions {

  _buildContentScriptRegistrations(label, intervention, matches) {
    const registration = {
      id: `webcompat intervention for ${label}`,
      id: `webcompat intervention for ${label}: ${JSON.stringify(intervention.content_scripts)}`,
      matches,
      persistAcrossSessions: false,
    };
+3 −0
Changes for browser/extensions/webcompat/tests/browser/browser.toml: 3 added lines, 0 removed lines.
Original line number Diff line number Diff line
@@ -18,6 +18,9 @@ skip-if = ["debug"] # disabled until bug 1961939 is fixed.
["browser_custom_functions.js"]
support-files = ["download_server.sjs"]

["browser_intervention_gating.js"]
skip-if = ["debug"] # disabled until bug 1961939 is fixed.

["browser_interventions.js"]

["browser_pref_check.js"]
+1 −1
Changes for browser/extensions/webcompat/tests/browser/browser_aboutcompat.js: 1 added line, 1 removed line.
Original line number Diff line number Diff line
@@ -38,7 +38,7 @@ add_task(async function test_about_compat_loads_properly() {
    }

    // both should have their content scripts registered at startup
    const interventionRCSId = `webcompat intervention for ${interventionWithContentScripts.label}`;
    const interventionRCSId = `webcompat intervention for ${interventionWithContentScripts.label}: ${JSON.stringify(interventionWithContentScripts.interventions[0].content_scripts)}`;
    const shimRCSId = `shim-${shimWithContentScripts.id}-0`;
    ok(
      await findRegisteredScript(interventionRCSId),
+85 −0
Changes for browser/extensions/webcompat/tests/browser/browser_intervention_gating.js: 85 added lines, 0 removed lines.
Original line number Diff line number Diff line
"use strict";

add_setup(async function () {
  // We don't send events or call official addon APIs while running
  // these tests, so there a good chance that test-verify mode may
  // end up seeing the addon as "idle". This pref should avoid that.
  await SpecialPowers.pushPrefEnv({
    set: [["extensions.background.idle.timeout", 300_000]],
  });
});

function getConfig(id, interventions) {
  return {
    id,
    label: id,
    bugs: {
      issue1: {
        matches: ["*://example.com/*"],
      },
    },
    interventions: interventions.map(i => {
      if (!i.platforms) {
        i.platforms = "all";
      }
      const { css, js } = i;
      delete i.css;
      delete i.js;
      i.content_scripts = { css, js };
      return i;
    }),
  };
}

add_task(async function test_that_only_intended_interventions_are_activated() {
  const runningVersion = parseInt(
    navigator.userAgent.match("Firefox/([0-9]*)")[1]
  );

  // If we have multiple parts to an intervention, where only some of them are meant to
  // apply (like ones for different Firefox versions), we want to make sure that only the
  // intended ones are activated. Otherwise when we try to deactivate them in about:compat,
  // it will fail, and we also run the risk of enabling more than we intended to.
  const config = getConfig("test", [
    {
      min_version: runningVersion + 1,
      js: ["lib/intervention_helpers.js"],
    },
    {
      max_version: runningVersion,
      js: ["lib/ua_helpers.js"],
    },
    {
      js: ["lib/shim_messaging_helper.js"],
    },
    {
      platforms: ["invalid"],
      js: ["lib/messaging_helper.js"],
    },
  ]);

  const [{ interventions }] = await WebCompatExtension.updateInterventions([
    config,
  ]);
  Assert.deepEqual(
    interventions.map(i => i.enabled),
    [false, true, true, false],
    "The correct parts of the intervention were chosen to be enabled"
  );

  let reg = await WebCompatExtension.getRegisteredContentScriptsFor("test");
  Assert.deepEqual(
    reg.map(r => r.js).flat(),
    ["lib/ua_helpers.js", "lib/shim_messaging_helper.js"],
    "Content scripts were properly registered"
  );

  await WebCompatExtension.disableInterventions(["test"]);

  reg = await WebCompatExtension.getRegisteredContentScriptsFor(["test"]);
  Assert.deepEqual(
    reg.map(r => r.js).flat(),
    [],
    "Content scripts were properly unregistered"
  );
});
+22 −0
Changes for browser/extensions/webcompat/tests/browser/head.js: 22 added lines, 0 removed lines.
Original line number Diff line number Diff line
@@ -97,6 +97,28 @@ const WebCompatExtension = new (class WebCompatExtension {
    });
  }

  async getRegisteredContentScriptsFor(_id) {
    return this.#run(async function (id) {
      const scripts =
        await content.wrappedJSObject.browser.scripting.getRegisteredContentScripts();
      return scripts.filter(script =>
        script.id.startsWith(`webcompat intervention for ${id}`)
      );
    }, _id);
  }

  async disableInterventions(_ids) {
    return this.#run(async function (ids) {
      const which =
        content.wrappedJSObject.interventions._availableInterventions.filter(
          i => ids.includes(i.id)
        );
      return await content.wrappedJSObject.interventions.disableInterventions(
        Cu.cloneInto(which, content)
      );
    }, _ids);
  }

  async updateInterventions(_config) {
    return this.#run(async function (config) {
      return await content.wrappedJSObject.interventions.updateInterventions(