зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1711168 support extension matching in webAccessibleResources r=zombie,smaug,rpl
Differential Revision: https://phabricator.services.mozilla.com/D115114
This commit is contained in:
Родитель
180d0769a9
Коммит
a73cd6df49
|
@ -18,6 +18,7 @@
|
|||
#include "nsAboutProtocolUtils.h"
|
||||
#include "ThirdPartyUtil.h"
|
||||
#include "mozilla/ContentPrincipal.h"
|
||||
#include "mozilla/ExtensionPolicyService.h"
|
||||
#include "mozilla/NullPrincipal.h"
|
||||
#include "mozilla/dom/BlobURLProtocolHandler.h"
|
||||
#include "mozilla/dom/ChromeUtils.h"
|
||||
|
@ -596,6 +597,8 @@ nsresult BasePrincipal::CheckMayLoadHelper(nsIURI* aURI,
|
|||
}
|
||||
}
|
||||
|
||||
// Web Accessible Resources in MV2 Extensions are marked with
|
||||
// URI_FETCHABLE_BY_ANYONE
|
||||
bool fetchableByAnyone;
|
||||
rv = NS_URIChainHasFlags(aURI, nsIProtocolHandler::URI_FETCHABLE_BY_ANYONE,
|
||||
&fetchableByAnyone);
|
||||
|
@ -603,16 +606,34 @@ nsresult BasePrincipal::CheckMayLoadHelper(nsIURI* aURI,
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
if (aReport) {
|
||||
nsCOMPtr<nsIURI> prinURI;
|
||||
rv = GetURI(getter_AddRefs(prinURI));
|
||||
if (NS_SUCCEEDED(rv) && prinURI) {
|
||||
nsScriptSecurityManager::ReportError(
|
||||
"CheckSameOriginError", prinURI, aURI,
|
||||
mOriginAttributes.mPrivateBrowsingId > 0, aInnerWindowID);
|
||||
// Get the principal uri for the last flag check or error.
|
||||
nsCOMPtr<nsIURI> prinURI;
|
||||
rv = GetURI(getter_AddRefs(prinURI));
|
||||
if (!(NS_SUCCEEDED(rv) && prinURI)) {
|
||||
return NS_ERROR_DOM_BAD_URI;
|
||||
}
|
||||
|
||||
// If MV3 Extension uris are web accessible by this principal it is allowed to
|
||||
// load.
|
||||
bool maybeWebAccessible = false;
|
||||
NS_URIChainHasFlags(aURI, nsIProtocolHandler::WEBEXT_URI_WEB_ACCESSIBLE,
|
||||
&maybeWebAccessible);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
if (maybeWebAccessible) {
|
||||
bool isWebAccessible = false;
|
||||
rv = ExtensionPolicyService::GetSingleton().SourceMayLoadExtensionURI(
|
||||
prinURI, aURI, &isWebAccessible);
|
||||
if (NS_SUCCEEDED(rv) && isWebAccessible) {
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
|
||||
if (aReport) {
|
||||
nsScriptSecurityManager::ReportError(
|
||||
"CheckSameOriginError", prinURI, aURI,
|
||||
mOriginAttributes.mPrivateBrowsingId > 0, aInnerWindowID);
|
||||
}
|
||||
|
||||
return NS_ERROR_DOM_BAD_URI;
|
||||
}
|
||||
|
||||
|
|
|
@ -741,21 +741,6 @@ nsScriptSecurityManager::CheckLoadURIWithPrincipal(nsIPrincipal* aPrincipal,
|
|||
return NS_ERROR_DOM_BAD_URI;
|
||||
}
|
||||
|
||||
// Extensions may allow access to a web accessible resource.
|
||||
bool maybeWebAccessible = false;
|
||||
NS_URIChainHasFlags(targetBaseURI,
|
||||
nsIProtocolHandler::WEBEXT_URI_WEB_ACCESSIBLE,
|
||||
&maybeWebAccessible);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
if (maybeWebAccessible) {
|
||||
bool isWebAccessible = false;
|
||||
rv = ExtensionPolicyService::GetSingleton().SourceMayLoadExtensionURI(
|
||||
sourceURI, targetBaseURI, &isWebAccessible);
|
||||
if (!(NS_SUCCEEDED(rv) && isWebAccessible)) {
|
||||
return NS_ERROR_DOM_BAD_URI;
|
||||
}
|
||||
}
|
||||
|
||||
// Check for uris that are only loadable by principals that subsume them
|
||||
bool targetURIIsLoadableBySubsumers = false;
|
||||
rv = NS_URIChainHasFlags(targetBaseURI,
|
||||
|
@ -829,6 +814,7 @@ nsScriptSecurityManager::CheckLoadURIWithPrincipal(nsIPrincipal* aPrincipal,
|
|||
bool schemesMatch =
|
||||
scheme.Equals(otherScheme, nsCaseInsensitiveCStringComparator);
|
||||
bool isSamePage = false;
|
||||
bool isExtensionMismatch = false;
|
||||
// about: URIs are special snowflakes.
|
||||
if (scheme.EqualsLiteral("about") && schemesMatch) {
|
||||
nsAutoCString moduleName, otherModuleName;
|
||||
|
@ -876,6 +862,13 @@ nsScriptSecurityManager::CheckLoadURIWithPrincipal(nsIPrincipal* aPrincipal,
|
|||
}
|
||||
}
|
||||
}
|
||||
} else if (schemesMatch && scheme.EqualsLiteral("moz-extension")) {
|
||||
// If it is not the same exension, we want to ensure we end up
|
||||
// calling CheckLoadURIFlags
|
||||
nsAutoCString host, otherHost;
|
||||
currentURI->GetHost(host);
|
||||
currentOtherURI->GetHost(otherHost);
|
||||
isExtensionMismatch = !host.Equals(otherHost);
|
||||
} else {
|
||||
bool equalExceptRef = false;
|
||||
rv = currentURI->EqualsExceptRef(currentOtherURI, &equalExceptRef);
|
||||
|
@ -884,10 +877,12 @@ nsScriptSecurityManager::CheckLoadURIWithPrincipal(nsIPrincipal* aPrincipal,
|
|||
|
||||
// If schemes are not equal, or they're equal but the target URI
|
||||
// is different from the source URI and doesn't always allow linking
|
||||
// from the same scheme, check if the URI flags of the current target
|
||||
// URI allow the current source URI to link to it.
|
||||
// from the same scheme, or this is two different extensions, check
|
||||
// if the URI flags of the current target URI allow the current
|
||||
// source URI to link to it.
|
||||
// The policy is specified by the protocol flags on both URIs.
|
||||
if (!schemesMatch || (denySameSchemeLinks && !isSamePage)) {
|
||||
if (!schemesMatch || (denySameSchemeLinks && !isSamePage) ||
|
||||
isExtensionMismatch) {
|
||||
return CheckLoadURIFlags(
|
||||
currentURI, currentOtherURI, sourceBaseURI, targetBaseURI, aFlags,
|
||||
aPrincipal->OriginAttributesRef().mPrivateBrowsingId > 0,
|
||||
|
@ -936,7 +931,8 @@ nsresult nsScriptSecurityManager::CheckLoadURIFlags(
|
|||
nsresult rv = aTargetBaseURI->GetScheme(targetScheme);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
// Check for system target URI
|
||||
// Check for system target URI. Regular (non web accessible) extension
|
||||
// URIs will also have URI_DANGEROUS_TO_LOAD.
|
||||
rv = DenyAccessIfURIHasFlags(aTargetURI,
|
||||
nsIProtocolHandler::URI_DANGEROUS_TO_LOAD);
|
||||
if (NS_FAILED(rv)) {
|
||||
|
@ -962,6 +958,26 @@ nsresult nsScriptSecurityManager::CheckLoadURIFlags(
|
|||
}
|
||||
}
|
||||
|
||||
// If MV3 Extension uris are web accessible they have
|
||||
// WEBEXT_URI_WEB_ACCESSIBLE.
|
||||
bool maybeWebAccessible = false;
|
||||
NS_URIChainHasFlags(aTargetURI, nsIProtocolHandler::WEBEXT_URI_WEB_ACCESSIBLE,
|
||||
&maybeWebAccessible);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
if (maybeWebAccessible) {
|
||||
bool isWebAccessible = false;
|
||||
rv = ExtensionPolicyService::GetSingleton().SourceMayLoadExtensionURI(
|
||||
aSourceURI, aTargetURI, &isWebAccessible);
|
||||
if (NS_SUCCEEDED(rv) && isWebAccessible) {
|
||||
return NS_OK;
|
||||
}
|
||||
if (reportErrors) {
|
||||
ReportError(errorTag, aSourceURI, aTargetURI, aFromPrivateWindow,
|
||||
aInnerWindowID);
|
||||
}
|
||||
return NS_ERROR_DOM_BAD_URI;
|
||||
}
|
||||
|
||||
// Check for chrome target URI
|
||||
bool targetURIIsUIResource = false;
|
||||
rv = NS_URIChainHasFlags(aTargetURI, nsIProtocolHandler::URI_IS_UI_RESOURCE,
|
||||
|
|
|
@ -274,7 +274,8 @@ interface WebExtensionPolicy {
|
|||
|
||||
dictionary WebAccessibleResourceInit {
|
||||
required sequence<MatchGlobOrString> resources;
|
||||
MatchPatternSetOrStringSequence matches;
|
||||
MatchPatternSetOrStringSequence? matches = null;
|
||||
sequence<DOMString>? extension_ids = null;
|
||||
};
|
||||
|
||||
dictionary WebExtensionInit {
|
||||
|
|
|
@ -1248,7 +1248,7 @@ nsresult nsContentSecurityManager::CheckAllowLoadInPrivilegedAboutContext(
|
|||
}
|
||||
|
||||
/*
|
||||
* Every protocol handler must set one of the five security flags
|
||||
* Every protocol handler must set one of the six security flags
|
||||
* defined in nsIProtocolHandler - if not - deny the load.
|
||||
*/
|
||||
nsresult nsContentSecurityManager::CheckChannelHasProtocolSecurityFlag(
|
||||
|
@ -1273,6 +1273,9 @@ nsresult nsContentSecurityManager::CheckChannelHasProtocolSecurityFlag(
|
|||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
uint32_t securityFlagsSet = 0;
|
||||
if (flags & nsIProtocolHandler::WEBEXT_URI_WEB_ACCESSIBLE) {
|
||||
securityFlagsSet += 1;
|
||||
}
|
||||
if (flags & nsIProtocolHandler::URI_LOADABLE_BY_ANYONE) {
|
||||
securityFlagsSet += 1;
|
||||
}
|
||||
|
|
|
@ -275,7 +275,8 @@ interface nsIProtocolHandler : nsISupports
|
|||
/**
|
||||
* This URI may be fetched and the contents are visible to anyone. This is
|
||||
* semantically equivalent to the resource being served with all-access CORS
|
||||
* headers.
|
||||
* headers. This is only used in MV2 Extensions and should not otherwise
|
||||
* be used.
|
||||
*/
|
||||
const unsigned long URI_FETCHABLE_BY_ANYONE = (1 << 18);
|
||||
|
||||
|
@ -312,7 +313,7 @@ interface nsIProtocolHandler : nsISupports
|
|||
|
||||
/**
|
||||
* This is an extension web accessible uri that is loadable if checked
|
||||
* against an allow whitelist.
|
||||
* against an allowlist using ExtensionPolicyService::SourceMayLoadExtensionURI.
|
||||
*/
|
||||
const unsigned long WEBEXT_URI_WEB_ACCESSIBLE = (1 << 24);
|
||||
};
|
||||
|
|
|
@ -416,15 +416,16 @@ nsresult ExtensionProtocolHandler::GetFlagsForURI(nsIURI* aURI,
|
|||
|
||||
URLInfo url(aURI);
|
||||
if (auto* policy = EPS().GetByURL(url)) {
|
||||
// In general a moz-extension URI is only loadable by chrome, but a
|
||||
// whitelisted subset are web-accessible (and cross-origin fetchable). Check
|
||||
// that whitelist. For Manifest V3 extensions, an additional whitelist
|
||||
// for the source loading the url must be checked so we add the flag
|
||||
// WEBEXT_URI_WEB_ACCESSIBLE, which is then checked in
|
||||
// nsScriptSecurityManager.
|
||||
// In general a moz-extension URI is only loadable by chrome, but an
|
||||
// allowlist subset are web-accessible (and cross-origin fetchable).
|
||||
// The allowlist is checked using EPS.SourceMayLoadExtensionURI in
|
||||
// BasePrincipal and nsScriptSecurityManager.
|
||||
if (policy->IsWebAccessiblePath(url.FilePath())) {
|
||||
flags |= URI_LOADABLE_BY_ANYONE | URI_FETCHABLE_BY_ANYONE |
|
||||
WEBEXT_URI_WEB_ACCESSIBLE;
|
||||
if (policy->ManifestVersion() < 3) {
|
||||
flags |= URI_LOADABLE_BY_ANYONE | URI_FETCHABLE_BY_ANYONE;
|
||||
} else {
|
||||
flags |= WEBEXT_URI_WEB_ACCESSIBLE;
|
||||
}
|
||||
} else {
|
||||
flags |= URI_DANGEROUS_TO_LOAD;
|
||||
}
|
||||
|
|
|
@ -304,6 +304,18 @@ const POSTPROCESSORS = {
|
|||
context.logError(context.makeError(msg));
|
||||
throw new Error(msg);
|
||||
},
|
||||
|
||||
webAccessibleMatching(value, context) {
|
||||
// Ensure each object has at least one of matches or extension_ids array.
|
||||
for (let obj of value) {
|
||||
if (!obj.matches && !obj.extension_ids) {
|
||||
const msg = `web_accessible_resources requires one of "matches" or "extension_ids"`;
|
||||
context.logError(context.makeError(msg));
|
||||
throw new Error(msg);
|
||||
}
|
||||
}
|
||||
return value;
|
||||
},
|
||||
};
|
||||
|
||||
// Parses a regular expression, with support for the Python extended
|
||||
|
|
|
@ -143,12 +143,24 @@ WebAccessibleResource::WebAccessibleResource(
|
|||
return;
|
||||
}
|
||||
|
||||
if (aInit.mMatches.WasPassed()) {
|
||||
if (!aInit.mMatches.IsNull()) {
|
||||
MatchPatternOptions options;
|
||||
options.mRestrictSchemes = true;
|
||||
mMatches = ParseMatches(aGlobal, aInit.mMatches.Value(), options,
|
||||
ErrorBehavior::CreateEmptyPattern, aRv);
|
||||
}
|
||||
|
||||
if (!aInit.mExtension_ids.IsNull()) {
|
||||
mExtensionIDs = new AtomSet(aInit.mExtension_ids.Value());
|
||||
}
|
||||
}
|
||||
|
||||
bool WebAccessibleResource::IsExtensionMatch(const URLInfo& aURI) {
|
||||
if (!mExtensionIDs) {
|
||||
return false;
|
||||
}
|
||||
WebExtensionPolicy* policy = EPS().GetByHost(aURI.Host());
|
||||
return policy && mExtensionIDs->Contains(policy->Id());
|
||||
}
|
||||
|
||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(WebAccessibleResource)
|
||||
|
|
|
@ -50,16 +50,23 @@ class WebAccessibleResource final : public nsISupports {
|
|||
}
|
||||
|
||||
bool SourceMayAccessPath(const URLInfo& aURI, const nsAString& aPath) {
|
||||
return mWebAccessiblePaths.Matches(aPath) && mMatches &&
|
||||
mMatches->Matches(aURI);
|
||||
return mWebAccessiblePaths.Matches(aPath) &&
|
||||
(IsHostMatch(aURI) || IsExtensionMatch(aURI));
|
||||
}
|
||||
|
||||
bool IsHostMatch(const URLInfo& aURI) {
|
||||
return mMatches && mMatches->Matches(aURI);
|
||||
}
|
||||
|
||||
bool IsExtensionMatch(const URLInfo& aURI);
|
||||
|
||||
protected:
|
||||
virtual ~WebAccessibleResource() = default;
|
||||
|
||||
private:
|
||||
MatchGlobSet mWebAccessiblePaths;
|
||||
RefPtr<MatchPatternSet> mMatches;
|
||||
RefPtr<AtomSet> mExtensionIDs;
|
||||
};
|
||||
|
||||
class WebExtensionPolicy final : public nsISupports,
|
||||
|
|
|
@ -288,16 +288,27 @@
|
|||
{
|
||||
"min_manifest_version": 3,
|
||||
"type": "array",
|
||||
"postprocess": "webAccessibleMatching",
|
||||
"minItems": 1,
|
||||
"items": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"resources": {
|
||||
"type": "array",
|
||||
"minItems": 1,
|
||||
"items": { "type": "string" }
|
||||
},
|
||||
"matches": {
|
||||
"optional": true,
|
||||
"type": "array",
|
||||
"minItems": 1,
|
||||
"items": { "$ref": "MatchPattern" }
|
||||
},
|
||||
"extension_ids": {
|
||||
"optional": true,
|
||||
"type": "array",
|
||||
"minItems": 1,
|
||||
"items": { "$ref": "ExtensionID" }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
"use strict";
|
||||
|
||||
Services.prefs.setBoolPref("extensions.manifestV3.enabled", true);
|
||||
|
||||
const server = createHttpServer({ hosts: ["example.com", "example.org"] });
|
||||
|
@ -11,10 +12,77 @@ let image = atob(
|
|||
const IMAGE_ARRAYBUFFER = Uint8Array.from(image, byte => byte.charCodeAt(0))
|
||||
.buffer;
|
||||
|
||||
add_task(async function test_web_accessible_resources_matching() {
|
||||
let extension = await ExtensionTestUtils.loadExtension({
|
||||
manifest: {
|
||||
manifest_version: 3,
|
||||
web_accessible_resources: [
|
||||
{
|
||||
resources: ["/accessible.html"],
|
||||
},
|
||||
],
|
||||
},
|
||||
});
|
||||
|
||||
await Assert.rejects(
|
||||
extension.startup(),
|
||||
/web_accessible_resources requires one of "matches" or "extension_ids"/,
|
||||
"web_accessible_resources object format incorrect"
|
||||
);
|
||||
|
||||
extension = await ExtensionTestUtils.loadExtension({
|
||||
manifest: {
|
||||
manifest_version: 3,
|
||||
web_accessible_resources: [
|
||||
{
|
||||
resources: ["/accessible.html"],
|
||||
matches: ["http://example.com/data/*"],
|
||||
},
|
||||
],
|
||||
},
|
||||
});
|
||||
|
||||
await extension.startup();
|
||||
ok(true, "web_accessible_resources with matches loads");
|
||||
await extension.unload();
|
||||
|
||||
extension = await ExtensionTestUtils.loadExtension({
|
||||
manifest: {
|
||||
manifest_version: 3,
|
||||
web_accessible_resources: [
|
||||
{
|
||||
resources: ["/accessible.html"],
|
||||
extension_ids: ["foo@mochitest"],
|
||||
},
|
||||
],
|
||||
},
|
||||
});
|
||||
|
||||
await extension.startup();
|
||||
ok(true, "web_accessible_resources with extensions loads");
|
||||
await extension.unload();
|
||||
|
||||
extension = await ExtensionTestUtils.loadExtension({
|
||||
manifest: {
|
||||
manifest_version: 3,
|
||||
web_accessible_resources: [
|
||||
{
|
||||
resources: ["/accessible.html"],
|
||||
matches: ["http://example.com/data/*"],
|
||||
extension_ids: ["foo@mochitest"],
|
||||
},
|
||||
],
|
||||
},
|
||||
});
|
||||
|
||||
await extension.startup();
|
||||
ok(true, "web_accessible_resources with matches and extensions loads");
|
||||
await extension.unload();
|
||||
});
|
||||
|
||||
add_task(async function test_web_accessible_resources() {
|
||||
async function contentScript() {
|
||||
let canLoad = window.location.href.startsWith("http://example.com");
|
||||
|
||||
let urls = [
|
||||
{
|
||||
name: "iframe",
|
||||
|
@ -136,3 +204,178 @@ add_task(async function test_web_accessible_resources() {
|
|||
await page.close();
|
||||
await extension.unload();
|
||||
});
|
||||
|
||||
async function pageScript() {
|
||||
function test_element_src(data) {
|
||||
return new Promise(resolve => {
|
||||
let elem = document.createElement(data.elem);
|
||||
let elemContext =
|
||||
data.content_context && elem.wrappedJSObject
|
||||
? elem.wrappedJSObject
|
||||
: elem;
|
||||
elemContext.setAttribute("src", data.url);
|
||||
elem.addEventListener(
|
||||
"load",
|
||||
() => {
|
||||
browser.test.log(`got load event for ${data.url}`);
|
||||
resolve(true);
|
||||
},
|
||||
{ once: true }
|
||||
);
|
||||
elem.addEventListener(
|
||||
"error",
|
||||
() => {
|
||||
browser.test.log(`got error event for ${data.url}`);
|
||||
resolve(false);
|
||||
},
|
||||
{ once: true }
|
||||
);
|
||||
document.body.appendChild(elem);
|
||||
});
|
||||
}
|
||||
browser.test.onMessage.addListener(async msg => {
|
||||
browser.test.log(`testing ${JSON.stringify(msg)}`);
|
||||
let loaded = await test_element_src(msg);
|
||||
browser.test.assertEq(loaded, msg.shouldLoad, `${msg.name} loaded`);
|
||||
browser.test.sendMessage("web-accessible-resources");
|
||||
});
|
||||
browser.test.sendMessage("page-loaded");
|
||||
}
|
||||
|
||||
add_task(async function test_web_accessible_resources_extensions() {
|
||||
let other = ExtensionTestUtils.loadExtension({
|
||||
manifest: {
|
||||
applications: { gecko: { id: "other@mochitest" } },
|
||||
},
|
||||
files: {
|
||||
"page.js": pageScript,
|
||||
|
||||
"page.html": `<html><head>
|
||||
<meta charset="utf-8">
|
||||
<script src="page.js"></script>
|
||||
</head></html>`,
|
||||
},
|
||||
});
|
||||
|
||||
let extension = ExtensionTestUtils.loadExtension({
|
||||
manifest: {
|
||||
manifest_version: 3,
|
||||
applications: { gecko: { id: "this@mochitest" } },
|
||||
web_accessible_resources: [
|
||||
{
|
||||
resources: ["/image.png"],
|
||||
extension_ids: ["other@mochitest"],
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
files: {
|
||||
"image.png": IMAGE_ARRAYBUFFER,
|
||||
"inaccessible.png": IMAGE_ARRAYBUFFER,
|
||||
"page.js": pageScript,
|
||||
|
||||
"page.html": `<html><head>
|
||||
<meta charset="utf-8">
|
||||
<script src="page.js"></script>
|
||||
</head></html>`,
|
||||
},
|
||||
});
|
||||
|
||||
await extension.startup();
|
||||
let extensionUrl = `moz-extension://${extension.uuid}/`;
|
||||
|
||||
await other.startup();
|
||||
let pageUrl = `moz-extension://${other.uuid}/page.html`;
|
||||
|
||||
let page = await ExtensionTestUtils.loadContentPage(pageUrl);
|
||||
await other.awaitMessage("page-loaded");
|
||||
|
||||
other.sendMessage({
|
||||
name: "accessible resource",
|
||||
elem: "img",
|
||||
url: `${extensionUrl}image.png`,
|
||||
shouldLoad: true,
|
||||
});
|
||||
await other.awaitMessage("web-accessible-resources");
|
||||
|
||||
other.sendMessage({
|
||||
name: "inaccessible resource",
|
||||
elem: "img",
|
||||
url: `${extensionUrl}inaccessible.png`,
|
||||
shouldLoad: false,
|
||||
});
|
||||
await other.awaitMessage("web-accessible-resources");
|
||||
|
||||
await page.close();
|
||||
|
||||
// test that the extension may load it's own web accessible resource
|
||||
page = await ExtensionTestUtils.loadContentPage(`${extensionUrl}page.html`);
|
||||
await extension.awaitMessage("page-loaded");
|
||||
|
||||
extension.sendMessage({
|
||||
name: "accessible resource",
|
||||
elem: "img",
|
||||
url: `${extensionUrl}image.png`,
|
||||
shouldLoad: true,
|
||||
});
|
||||
await extension.awaitMessage("web-accessible-resources");
|
||||
|
||||
await page.close();
|
||||
await extension.unload();
|
||||
await other.unload();
|
||||
});
|
||||
|
||||
// test that a web page not in matches cannot load the resource
|
||||
add_task(async function test_web_accessible_resources_inaccessible() {
|
||||
let extension = ExtensionTestUtils.loadExtension({
|
||||
temporarilyInstalled: true,
|
||||
manifest: {
|
||||
manifest_version: 3,
|
||||
applications: { gecko: { id: "web@mochitest" } },
|
||||
content_scripts: [
|
||||
{
|
||||
matches: ["http://example.com/data/*"],
|
||||
js: ["page.js"],
|
||||
run_at: "document_idle",
|
||||
},
|
||||
],
|
||||
web_accessible_resources: [
|
||||
{
|
||||
resources: ["/image.png"],
|
||||
extension_ids: ["some_other_ext@mochitest"],
|
||||
},
|
||||
],
|
||||
host_permissions: ["*://example.com/*"],
|
||||
granted_host_permissions: true,
|
||||
},
|
||||
|
||||
files: {
|
||||
"image.png": IMAGE_ARRAYBUFFER,
|
||||
"page.js": pageScript,
|
||||
|
||||
"page.html": `<html><head>
|
||||
<meta charset="utf-8">
|
||||
<script src="page.js"></script>
|
||||
</head></html>`,
|
||||
},
|
||||
});
|
||||
|
||||
await extension.startup();
|
||||
let extensionUrl = `moz-extension://${extension.uuid}/`;
|
||||
let page = await ExtensionTestUtils.loadContentPage(
|
||||
"http://example.com/data/"
|
||||
);
|
||||
await extension.awaitMessage("page-loaded");
|
||||
|
||||
extension.sendMessage({
|
||||
name: "cannot access resource",
|
||||
elem: "img",
|
||||
url: `${extensionUrl}image.png`,
|
||||
content_context: true,
|
||||
shouldLoad: false,
|
||||
});
|
||||
await extension.awaitMessage("web-accessible-resources");
|
||||
|
||||
await page.close();
|
||||
await extension.unload();
|
||||
});
|
||||
|
|
Загрузка…
Ссылка в новой задаче