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
|
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
const { AddonTestUtils } = ChromeUtils.importESModule(
"resource://testing-common/AddonTestUtils.sys.mjs"
);
const { ExtensionProcessCrashObserver, Management } =
ChromeUtils.importESModule("resource://gre/modules/Extension.sys.mjs");
AddonTestUtils.initMochitest(this);
add_task(async function test_ExtensionProcessCrashObserver() {
let mv2Extension = ExtensionTestUtils.loadExtension({
useAddonManager: "temporary",
manifest: {
manifest_version: 2,
},
background() {
browser.test.sendMessage("background_running");
},
});
await mv2Extension.startup();
await mv2Extension.awaitMessage("background_running");
let { currentProcessChildID, lastCrashedProcessChildID } =
ExtensionProcessCrashObserver;
Assert.notEqual(
currentProcessChildID,
undefined,
"Expect ExtensionProcessCrashObserver.currentProcessChildID to be set"
);
Assert.equal(
ChromeUtils.getAllDOMProcesses().find(
pp => pp.childID == currentProcessChildID
)?.remoteType,
"extension",
"Expect a child process with remoteType extension to be found for the process childID set"
);
Assert.notEqual(
lastCrashedProcessChildID,
currentProcessChildID,
"Expect lastCrashedProcessChildID to not be set to the same value that currentProcessChildID is set"
);
let mv3Extension = ExtensionTestUtils.loadExtension({
useAddonManager: "temporary",
manifest: {
manifest_version: 3,
},
background() {
browser.test.sendMessage("background_running");
},
});
const waitForExtensionBrowserInserted = () =>
new Promise(resolve => {
const listener = (_eventName, browser) => {
if (!browser.getAttribute("webextension-view-type") === "background") {
return;
}
Management.off("extension-browser-inserted", listener);
resolve(browser);
};
Management.on("extension-browser-inserted", listener);
});
const waitForExtensionProcessCrashNotified = () =>
new Promise(resolve => {
Management.once("extension-process-crash", (_evt, data) => resolve(data));
});
const promiseBackgroundBrowser = waitForExtensionBrowserInserted();
const promiseExtensionProcessCrashNotified =
waitForExtensionProcessCrashNotified();
await mv3Extension.startup();
await mv3Extension.awaitMessage("background_running");
const bgPageBrowser = await promiseBackgroundBrowser;
info("Force extension process crash");
// NOTE: shouldShowTabCrashPage option needs to be set to false
// to make sure crashFrame method resolves without waiting for a
// tab crash page (which is not going to be shown for a background
// page browser element).
await BrowserTestUtils.crashFrame(
bgPageBrowser,
/* shouldShowTabCrashPage */ false
);
info("Verify ExtensionProcessCrashObserver after extension process crash");
Assert.equal(
ExtensionProcessCrashObserver.lastCrashedProcessChildID,
currentProcessChildID,
"Expect ExtensionProcessCrashObserver.lastCrashedProcessChildID to be set to the expected childID"
);
info("Expect the same childID to have been notified as a Management event");
Assert.deepEqual(
await promiseExtensionProcessCrashNotified,
{ childID: currentProcessChildID },
"Got the expected childID notified as part of the extension-process-crash Management event"
);
info("Wait for mv3 extension shutdown");
await mv3Extension.unload();
info("Wait for mv2 extension shutdown");
await mv2Extension.unload();
});
|