summaryrefslogtreecommitdiffstats
path: root/browser/components/extensions/test/xpcshell/test_ext_settings_overrides_shutdown.js
blob: fdb9baf25ae9d7d2132bf76b2145227cc0c29f7e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
/* -*- Mode: indent-tabs-mode: nil; js-indent-level: 2 -*- */
/* vim: set sts=2 sw=2 et tw=80: */

"use strict";

const { AddonTestUtils } = ChromeUtils.importESModule(
  "resource://testing-common/AddonTestUtils.sys.mjs"
);
// Lazily import ExtensionParent to allow AddonTestUtils.createAppInfo to
// override Services.appinfo.
ChromeUtils.defineESModuleGetters(this, {
  ExtensionParent: "resource://gre/modules/ExtensionParent.sys.mjs",
});

AddonTestUtils.init(this);
AddonTestUtils.overrideCertDB();
AddonTestUtils.createAppInfo(
  "xpcshell@tests.mozilla.org",
  "XPCShell",
  "42",
  "42"
);

add_task(async function shutdown_during_search_provider_startup() {
  await AddonTestUtils.promiseStartupManager();

  let extension = ExtensionTestUtils.loadExtension({
    useAddonManager: "permanent",
    manifest: {
      chrome_settings_overrides: {
        search_provider: {
          is_default: true,
          name: "dummy name",
          search_url: "https://example.com/",
        },
      },
    },
  });

  info("Starting up search extension");
  await extension.startup();
  let extStartPromise = AddonTestUtils.waitForSearchProviderStartup(extension, {
    // Search provider registration is expected to be pending because the search
    // service has not been initialized yet.
    expectPending: true,
  });

  let initialized = false;
  ExtensionParent.apiManager.global.searchInitialized.then(() => {
    initialized = true;
  });

  await extension.addon.disable();

  info("Extension managed to shut down despite the uninitialized search");
  // Initialize search after extension shutdown to check that it does not cause
  // any problems, and that the test can continue to test uninstall behavior.
  Assert.ok(!initialized, "Search service should not have been initialized");

  extension.addon.enable();
  await extension.awaitStartup();

  // Check that uninstall is blocked until the search registration at startup
  // has finished. This registration only finished once the search service is
  // initialized.
  let uninstallingPromise = new Promise(resolve => {
    let Management = ExtensionParent.apiManager;
    Management.on("uninstall", function listener(eventName, { id }) {
      Management.off("uninstall", listener);
      Assert.equal(id, extension.id, "Expected extension");
      resolve();
    });
  });

  let extRestartPromise = AddonTestUtils.waitForSearchProviderStartup(
    extension,
    {
      // Search provider registration is expected to be pending again,
      // because the search service has still not been initialized yet.
      expectPending: true,
    }
  );

  let uninstalledPromise = extension.addon.uninstall();
  let uninstalled = false;
  uninstalledPromise.then(() => {
    uninstalled = true;
  });

  await uninstallingPromise;
  Assert.ok(!uninstalled, "Uninstall should not be finished yet");
  Assert.ok(!initialized, "Search service should still be uninitialized");
  await Services.search.init();
  Assert.ok(initialized, "Search service should be initialized");

  // After initializing the search service, the search provider registration
  // promises should settle eventually.

  // Despite the interrupted startup, the promise should still resolve without
  // an error.
  await extStartPromise;
  // The extension that is still active. The promise should just resolve.
  await extRestartPromise;

  // After initializing the search service, uninstall should eventually finish.
  await uninstalledPromise;

  await AddonTestUtils.promiseShutdownManager();
});