summaryrefslogtreecommitdiffstats
path: root/toolkit/components/webextensions/test/mochitest/test_chrome_ext_background_debug_global.html
blob: 0edf5ea86a934a920e5639456b2345039bfab823 (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
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
<!DOCTYPE HTML>
<html>
<head>
  <title>WebExtension test</title>
  <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
  <script src="chrome://mochikit/content/tests/SimpleTest/SpawnTask.js"></script>
  <script src="chrome://mochikit/content/tests/SimpleTest/ExtensionTestUtils.js"></script>
  <script type="text/javascript" src="chrome_head.js"></script>
  <script type="text/javascript" src="head.js"></script>
  <link rel="stylesheet" href="chrome://mochikit/contents/tests/SimpleTest/test.css"/>
</head>
<body>

<script type="text/javascript">
"use strict";

Cu.import("resource://devtools/client/framework/ToolboxProcess.jsm");
Cu.import("resource://gre/modules/AddonManager.jsm");

const {
  XPIProvider,
} = Components.utils.import("resource://gre/modules/addons/XPIProvider.jsm");

/**
 * This test is asserting that ext-backgroundPage.js successfully sets its
 * debug global in the AddonWrapper provided by XPIProvider.jsm
 *
 * It does _not_ test any functionality in devtools and does not guarantee
 * debugging is actually working correctly end-to-end.
 */

function background() {
  window.testThing = "test!";
  browser.test.notifyPass("background script ran");
}

const ID = "debug@tests.mozilla.org";
let extensionData = {
  useAddonManager: "temporary",
  background,
  manifest: {
    applications: {gecko: {id: ID}},
  },
};

add_task(function* () {
  let extension = ExtensionTestUtils.loadExtension(extensionData);
  yield extension.startup();

  yield extension.awaitFinish("background script ran");

  yield new Promise(function(resolve) {
    window.BrowserToolboxProcess.emit("connectionchange", "opened", {
      setAddonOptions(id, options) {
        if (id === ID) {
          let context = Cu.waiveXrays(options.global);
          ok(context.chrome, "global context has a chrome object");
          ok(context.browser, "global context has a browser object");
          is("test!", context.testThing, "global context is the background script context");
          resolve();
        }
      },
    });
  });

  let addon = yield new Promise((resolve, reject) => {
    AddonManager.getAddonByID(ID, addon => addon ? resolve(addon) : reject());
  });

  ok(addon, `Got the addon wrapper for ${addon.id}`);

  function waitForDebugGlobalChanges(times, initialAddonInstanceID) {
    return new Promise((resolve) => {
      AddonManager.addAddonListener({
        count: 0,
        notNullGlobalsCount: 0,
        undefinedPrivateWrappersCount: 0,
        lastAddonInstanceID: initialAddonInstanceID,
        onPropertyChanged(newAddon, changedPropNames) {
          if (newAddon.id != addon.id ||
              !changedPropNames.includes("debugGlobal")) {
            return;
          }

          ok(!(newAddon.setDebugGlobal) && !(newAddon.getDebugGlobal),
             "The addon wrapper should not be a PrivateWrapper");

          let activeAddon = XPIProvider.activeAddons.get(addon.id);

          let addonInstanceID;

          if (!activeAddon) {
            // The addon has been disable, the preferred global should be null
            addonInstanceID = this.lastAddonInstanceID;
            delete this.lastAddonInstanceID;
          } else {
            addonInstanceID = activeAddon.instanceID;
            this.lastAddonInstanceID = addonInstanceID;
          }

          ok(addonInstanceID, `Got the addon instanceID for ${addon.id}`);

          AddonManager.getAddonByInstanceID(addonInstanceID).then((privateWrapper) => {
            this.count += 1;

            if (!privateWrapper) {
              // The addon has been uninstalled
              this.undefinedPrivateWrappersCount += 1;
            } else {
              ok((privateWrapper.getDebugGlobal), "Got the addon PrivateWrapper");

              if (privateWrapper.getDebugGlobal()) {
                this.notNullGlobalsCount += 1;
              }
            }

            if (this.count == times) {
              AddonManager.removeAddonListener(this);
              resolve({
                counters: {
                  count: this.count,
                  notNullGlobalsCount: this.notNullGlobalsCount,
                  undefinedPrivateWrappersCount: this.undefinedPrivateWrappersCount,
                },
                lastAddonInstanceID: this.lastAddonInstanceID,
              });
            }
          });
        },
      });
    });
  }

  // two calls expected, one for the shutdown and one for the startup
  // of the background page.
  let waitForDebugGlobalChangesOnReload = waitForDebugGlobalChanges(2);

  info("Addon reload...");
  yield addon.reload();

  info("Addon completed startup after reload");

  let {
    counters: reloadCounters,
    lastAddonInstanceID,
  } = yield waitForDebugGlobalChangesOnReload;

  isDeeply(reloadCounters, {count: 2, notNullGlobalsCount: 1, undefinedPrivateWrappersCount: 0},
           "Got the expected number of onPropertyChanged calls on reload");

  // one more call expected for the shutdown.
  let waitForDebugGlobalChangesOnShutdown = waitForDebugGlobalChanges(1, lastAddonInstanceID);

  info("extension unloading...");
  yield extension.unload();
  info("extension unloaded");

  let {counters: unloadCounters} = yield waitForDebugGlobalChangesOnShutdown;

  isDeeply(unloadCounters, {count: 1, notNullGlobalsCount: 0, undefinedPrivateWrappersCount: 1},
           "Got the expected number of onPropertyChanged calls on shutdown");
});
</script>

</body>
</html>