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
167
168
169
170
171
172
173
174
175
176
177
|
"use strict";
add_task(async function test_autoDiscardable() {
let files = {
"schema.json": JSON.stringify([
{
namespace: "experiments",
functions: [
{
name: "unload",
type: "function",
async: true,
description:
"Unload the least recently used tab using Firefox's built-in tab unloader mechanism",
parameters: [],
},
],
},
]),
"parent.js": () => {
const { TabUnloader } = ChromeUtils.importESModule(
"resource:///modules/TabUnloader.sys.mjs"
);
const { ExtensionError } = ExtensionUtils;
this.experiments = class extends ExtensionAPI {
getAPI(context) {
return {
experiments: {
async unload() {
try {
await TabUnloader.unloadLeastRecentlyUsedTab(null);
} catch (error) {
// We need to do this, otherwise failures won't bubble up to the test properly.
throw ExtensionError(error);
}
},
},
};
}
};
},
};
async function background() {
let firstTab = await browser.tabs.create({
active: false,
url: "https://example.org/",
});
// Make sure setting and getting works properly
browser.test.assertTrue(
firstTab.autoDiscardable,
"autoDiscardable should always be true by default"
);
let result = await browser.tabs.update(firstTab.id, {
autoDiscardable: false,
});
browser.test.assertFalse(
result.autoDiscardable,
"autoDiscardable should be false after setting it as such"
);
result = await browser.tabs.update(firstTab.id, {
autoDiscardable: true,
});
browser.test.assertTrue(
result.autoDiscardable,
"autoDiscardable should be true after setting it as such"
);
result = await browser.tabs.update(firstTab.id, {
autoDiscardable: false,
});
browser.test.assertFalse(
result.autoDiscardable,
"autoDiscardable should be false after setting it as such"
);
// Make sure the tab can't be unloaded when autoDiscardable is false
await browser.experiments.unload();
result = await browser.tabs.get(firstTab.id);
browser.test.assertFalse(
result.discarded,
"Tab should not unload when autoDiscardable is false"
);
// Make sure the tab CAN be unloaded when autoDiscardable is true
await browser.tabs.update(firstTab.id, {
autoDiscardable: true,
});
await browser.experiments.unload();
result = await browser.tabs.get(firstTab.id);
browser.test.assertTrue(
result.discarded,
"Tab should unload when autoDiscardable is true"
);
// Make sure filtering for discardable tabs works properly
result = await browser.tabs.query({ autoDiscardable: true });
browser.test.assertEq(
2,
result.length,
"tabs.query should return 2 when autoDiscardable is true "
);
await browser.tabs.update(firstTab.id, {
autoDiscardable: false,
});
result = await browser.tabs.query({ autoDiscardable: true });
browser.test.assertEq(
1,
result.length,
"tabs.query should return 1 when autoDiscardable is false"
);
let onUpdatedPromise = {};
onUpdatedPromise.promise = new Promise(
resolve => (onUpdatedPromise.resolve = resolve)
);
// Make sure onUpdated works
async function testOnUpdatedEvent(autoDiscardable) {
browser.test.log(`Testing autoDiscardable = ${autoDiscardable}`);
let onUpdated;
let promise = new Promise(resolve => {
onUpdated = (tabId, changeInfo, tabInfo) => {
browser.test.assertEq(
firstTab.id,
tabId,
"The updated tab's ID should match the correct tab"
);
browser.test.assertDeepEq(
{ autoDiscardable },
changeInfo,
"The updated tab's changeInfo should be correct"
);
browser.test.assertEq(
tabInfo.autoDiscardable,
autoDiscardable,
"The updated tab's tabInfo should be correct"
);
resolve();
};
});
browser.tabs.onUpdated.addListener(onUpdated, {
properties: ["autoDiscardable"],
});
await browser.tabs.update(firstTab.id, { autoDiscardable });
await promise;
browser.tabs.onUpdated.removeListener(onUpdated);
}
await testOnUpdatedEvent(true);
await testOnUpdatedEvent(false);
await browser.tabs.remove(firstTab.id); // Cleanup
browser.test.notifyPass("autoDiscardable");
}
let extension = ExtensionTestUtils.loadExtension({
isPrivileged: true,
manifest: {
permissions: ["tabs"],
experiment_apis: {
experiments: {
schema: "schema.json",
parent: {
scopes: ["addon_parent"],
script: "parent.js",
paths: [["experiments"]],
},
},
},
},
background,
files,
});
await extension.startup();
await extension.awaitFinish("autoDiscardable");
await extension.unload();
});
|