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
|
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
const PAGE =
"http://mochi.test:8888/browser/browser/components/extensions/test/browser/context.html";
add_task(async function menuInShadowDOM() {
Services.prefs.setBoolPref("security.allow_eval_with_system_principal", true);
registerCleanupFunction(() => {
Services.prefs.clearUserPref("security.allow_eval_with_system_principal");
});
let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, PAGE);
gBrowser.selectedTab = tab;
async function background() {
browser.menus.onShown.addListener(async (info, tab) => {
browser.test.assertTrue(
Number.isInteger(info.targetElementId),
`${info.targetElementId} should be an integer`
);
browser.test.assertEq(
"all,link",
info.contexts.sort().join(","),
"Expected context"
);
browser.test.assertEq(
"http://example.com/?shadowlink",
info.linkUrl,
"Menu target should be a link in the shadow DOM"
);
let code = `{
try {
let elem = browser.menus.getTargetElement(${info.targetElementId});
browser.test.assertTrue(elem, "Shadow element must be found");
browser.test.assertEq("http://example.com/?shadowlink", elem.href, "Element is a link in shadow DOM " - elem.outerHTML);
} catch (e) {
browser.test.fail("Unexpected error in getTargetElement: " + e);
}
}`;
await browser.tabs.executeScript(tab.id, { code });
browser.test.sendMessage(
"onShownMenuAndCheckedInfo",
info.targetElementId
);
});
// Ensure that onShown is registered (workaround for bug 1300234):
await browser.menus.removeAll();
browser.test.sendMessage("ready");
}
let extension = ExtensionTestUtils.loadExtension({
manifest: {
permissions: ["menus", "http://mochi.test/*"],
},
background,
});
await extension.startup();
await extension.awaitMessage("ready");
async function testShadowMenu(setupMenuTarget) {
await openContextMenu(setupMenuTarget);
await extension.awaitMessage("onShownMenuAndCheckedInfo");
await closeContextMenu();
}
info("Clicking in open shadow root");
await testShadowMenu(() => {
let doc = this.document;
doc.body.innerHTML = `<div></div>`;
let host = doc.body.firstElementChild.attachShadow({ mode: "open" });
host.innerHTML = `<a href="http://example.com/?shadowlink">Test open</a>`;
this.document.testTarget = host.firstElementChild;
return this.document.testTarget;
});
info("Clicking in closed shadow root");
await testShadowMenu(() => {
let doc = this.document;
doc.body.innerHTML = `<div></div>`;
let host = doc.body.firstElementChild.attachShadow({ mode: "closed" });
host.innerHTML = `<a href="http://example.com/?shadowlink">Test closed</a>`;
this.document.testTarget = host.firstElementChild;
return this.document.testTarget;
});
info("Clicking in nested shadow DOM");
await testShadowMenu(() => {
let doc = this.document;
let host;
for (let container = doc.body, i = 0; i < 10; ++i) {
container.innerHTML = `<div id="level"></div>`;
host = container.firstElementChild.attachShadow({ mode: "open" });
container = host;
}
host.innerHTML = `<a href="http://example.com/?shadowlink">Test nested</a>`;
this.document.testTarget = host.firstElementChild;
return this.document.testTarget;
});
await extension.unload();
BrowserTestUtils.removeTab(tab);
});
|