Bug 1439153 - Make WebExtensions work with Shadow DOM/WebComponents, r=kmag

--HG--
extra : rebase_source : 83638cba42eea1523d32d06a2eb14df20cbab404
This commit is contained in:
Olli Pettay 2018-07-14 05:26:15 +03:00
Родитель 001ad997b8
Коммит de99e4460b
9 изменённых файлов: 110 добавлений и 1 удалений

Просмотреть файл

@ -282,6 +282,13 @@ BasePrincipal::GetIsSystemPrincipal(bool* aResult)
return NS_OK;
}
NS_IMETHODIMP
BasePrincipal::GetIsAddonOrExpandedAddonPrincipal(bool* aResult)
{
*aResult = AddonPolicy() || ContentScriptAddonPolicy();
return NS_OK;
}
NS_IMETHODIMP
BasePrincipal::GetOriginAttributes(JSContext* aCx, JS::MutableHandle<JS::Value> aVal)
{

Просмотреть файл

@ -79,6 +79,7 @@ public:
NS_IMETHOD GetIsCodebasePrincipal(bool* aResult) override;
NS_IMETHOD GetIsExpandedPrincipal(bool* aResult) override;
NS_IMETHOD GetIsSystemPrincipal(bool* aResult) override;
NS_IMETHOD GetIsAddonOrExpandedAddonPrincipal(bool* aResult) override;
NS_IMETHOD GetOriginAttributes(JSContext* aCx, JS::MutableHandle<JS::Value> aVal) final;
NS_IMETHOD GetOriginSuffix(nsACString& aOriginSuffix) final;
NS_IMETHOD GetAppId(uint32_t* aAppId) final;

Просмотреть файл

@ -320,6 +320,12 @@ interface nsIPrincipal : nsISerializable
* Returns true iff this is the system principal.
*/
[infallible] readonly attribute boolean isSystemPrincipal;
/**
* Returns true iff the principal is either an addon principal or
* an expanded principal, which contains at least one addon principal.
*/
[infallible] readonly attribute boolean isAddonOrExpandedAddonPrincipal;
};
/**

Просмотреть файл

@ -2612,6 +2612,21 @@ nsDocument::IsShadowDOMEnabled(JSContext* aCx, JSObject* aGlobal)
return doc->IsShadowDOMEnabled();
}
// static
bool
nsDocument::IsShadowDOMEnabledAndCallerIsChromeOrAddon(JSContext* aCx,
JSObject* aObject)
{
if (IsShadowDOMEnabled(aCx, aObject)) {
nsIPrincipal* principal = nsContentUtils::SubjectPrincipal(aCx);
return principal &&
(nsContentUtils::IsSystemPrincipal(principal) ||
principal->GetIsAddonOrExpandedAddonPrincipal());
}
return false;
}
bool
nsDocument::IsShadowDOMEnabled(const nsINode* aNode)
{

Просмотреть файл

@ -196,6 +196,8 @@ public:
// Check whether shadow DOM is enabled for aGlobal.
static bool IsShadowDOMEnabled(JSContext* aCx, JSObject* aGlobal);
// Check whether shadow DOM is enabled for the document this node belongs to.
// Same as above, but also checks that the caller is either chrome or some addon.
static bool IsShadowDOMEnabledAndCallerIsChromeOrAddon(JSContext* aCx, JSObject* aObject);
static bool IsShadowDOMEnabled(const nsINode* aNode);
public:

Просмотреть файл

@ -261,7 +261,7 @@ partial interface Element {
[BinaryName="shadowRootByMode", Func="nsDocument::IsShadowDOMEnabled"]
readonly attribute ShadowRoot? shadowRoot;
[ChromeOnly, Func="nsDocument::IsShadowDOMEnabled", BinaryName="shadowRoot"]
[Func="nsDocument::IsShadowDOMEnabledAndCallerIsChromeOrAddon", BinaryName="shadowRoot"]
readonly attribute ShadowRoot? openOrClosedShadowRoot;
[BinaryName="assignedSlotByMode", Func="nsDocument::IsShadowDOMEnabled"]

Просмотреть файл

@ -0,0 +1,12 @@
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
</head>
<body>
<div id="host">host</div>
<script>
document.getElementById("host").attachShadow({mode: "closed"});
</script>
</body>
</html>

Просмотреть файл

@ -0,0 +1,65 @@
"use strict";
ChromeUtils.defineModuleGetter(this, "Preferences",
"resource://gre/modules/Preferences.jsm");
// ExtensionContent.jsm needs to know when it's running from xpcshell,
// to use the right timeout for content scripts executed at document_idle.
ExtensionTestUtils.mockAppInfo();
const server = createHttpServer();
server.registerDirectory("/data/", do_get_file("data"));
const BASE_URL = `http://localhost:${server.identity.primaryPort}/data`;
add_task(async function test_contentscript_shadowDOM() {
const PREFS = {
"dom.webcomponents.shadowdom.enabled": true
};
// Set prefs to our initial values.
for (let pref in PREFS) {
Preferences.set(pref, PREFS[pref]);
}
registerCleanupFunction(() => {
// Reset the prefs.
for (let pref in PREFS) {
Preferences.reset(pref);
}
});
function backgroundScript() {
browser.test.assertTrue("openOrClosedShadowRoot" in document.documentElement,
"Should have openOrClosedShadowRoot in Element in background script.");
}
function contentScript() {
var host = document.getElementById("host");
browser.test.assertTrue("openOrClosedShadowRoot" in host, "Should have openOrClosedShadowRoot in Element.");
var shadowRoot = host.openOrClosedShadowRoot;
browser.test.assertEq(shadowRoot.mode, "closed", "Should have closed ShadowRoot.");
browser.test.sendMessage("contentScript");
}
let extension = ExtensionTestUtils.loadExtension({
manifest: {
content_scripts: [{
"matches": ["http://*/*/file_shadowdom.html"],
"js": ["content_script.js"],
}],
},
background: backgroundScript,
files: {
"content_script.js": contentScript,
},
});
await extension.startup();
let contentPage = await ExtensionTestUtils.loadContentPage(`${BASE_URL}/file_shadowdom.html`);
await extension.awaitMessage("contentScript");
await contentPage.close();
await extension.unload();
});

Просмотреть файл

@ -10,3 +10,4 @@ skip-if = (os == "android" && debug) || (os == "win" && debug) # Windows: Bug 14
[test_ext_contentScripts_register.js]
skip-if = os == "android"
[test_ext_adoption_with_xrays.js]
[test_ext_shadowdom.js]