Bug 1575625 - Make Cache API available to webextensions (moz-extension:// schemas) r=asuth,rpl

Make Cache API available to webextensions (moz-extension:// schemas)

Differential Revision: https://phabricator.services.mozilla.com/D114054
This commit is contained in:
Andre Natal 2021-05-06 19:41:39 +00:00
Родитель a1d5820111
Коммит e437b1394b
6 изменённых файлов: 157 добавлений и 16 удалений

6
dom/cache/CacheStorage.cpp поставляемый
Просмотреть файл

@ -112,11 +112,7 @@ bool IsTrusted(const PrincipalInfo& aPrincipalInfo, bool aTestingPrefEnabled) {
const nsAutoCString scheme(Substring(flatURL, schemePos, schemeLen));
if (scheme.LowerCaseEqualsLiteral("https") ||
scheme.LowerCaseEqualsLiteral("file")) {
return true;
}
if (StaticPrefs::extensions_backgroundServiceWorker_enabled_AtStartup() &&
scheme.LowerCaseEqualsLiteral("file") ||
scheme.LowerCaseEqualsLiteral("moz-extension")) {
return true;
}

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

@ -379,7 +379,7 @@ var ExtensionAddonObserver = {
ExtensionStorage.clear(addon.id, { shouldNotifyListeners: false })
);
// Clear any IndexedDB storage created by the extension
// Clear any IndexedDB and Cache API storage created by the extension.
// If LSNG is enabled, this also clears localStorage.
Services.qms.clearStoragesForPrincipal(principal);

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

@ -105,8 +105,8 @@ add_task(async function test_serviceWorker_register_guarded_by_pref() {
});
add_task(async function test_cache_api_allowed() {
// Verify that Cache API support for moz-extension url availability is also
// conditioned by the extensions.backgroundServiceWorker.enabled pref.
// Verify that Cache API support for moz-extension url availability is
// conditioned only by the extensions.backgroundServiceWorker.enabled pref.
// NOTE: the scenario with backgroundServiceWorkeEnable set to false
// is part of "browser_ext_background_serviceworker_pref_disabled.js".
const extension = ExtensionTestUtils.loadExtension({

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

@ -100,20 +100,23 @@ add_task(async function test_cache_api_disallowed() {
const extension = ExtensionTestUtils.loadExtension({
async background() {
try {
await window.caches.open("test-cache-api");
browser.test.fail(
`An extension page should not be allowed to use the Cache API successfully`
const cache = await window.caches.open("test-cache-api");
let url = browser.runtime.getURL("file.txt");
await browser.test.assertRejects(
cache.add(url),
new RegExp(`Cache.add: Request URL ${url} must be either`),
"Got the expected rejections on calling cache.add with a moz-extension:// url"
);
} catch (err) {
browser.test.assertEq(
String(err),
"SecurityError: The operation is insecure.",
"Got the expected error on registering a service worker from a script"
);
browser.test.fail(`Unexpected error on using Cache API: ${err}`);
throw err;
} finally {
browser.test.sendMessage("test-cache-api-disallowed");
}
},
files: {
"file.txt": "file content",
},
});
await extension.startup();

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

@ -0,0 +1,141 @@
/* -*- Mode: indent-tabs-mode: nil; js-indent-level: 2 -*- */
/* vim: set sts=2 sw=2 et tw=80: */
"use strict";
AddonTestUtils.init(this);
AddonTestUtils.createAppInfo(
"xpcshell@tests.mozilla.org",
"XPCShell",
"1",
"42"
);
const server = createHttpServer({
hosts: ["example.com", "anotherdomain.com"],
});
server.registerPathHandler("/dummy", (request, response) => {
response.setStatusLine(request.httpVersion, 200, "OK");
response.setHeader("Content-Type", "text/html", false);
response.write("test_ext_cache_api.js");
});
add_task(async function test_cache_api_http_resource_allowed() {
async function background() {
try {
const BASE_URL = `http://example.com/dummy`;
const cache = await window.caches.open("test-cache-api");
browser.test.assertTrue(
await window.caches.has("test-cache-api"),
"CacheStorage.has should resolve to true"
);
// Test that adding and requesting cached http urls
// works as well.
await cache.add(BASE_URL);
browser.test.assertEq(
"test_ext_cache_api.js",
await cache.match(BASE_URL).then(res => res.text()),
"Got the expected content from the cached http url"
);
// Test that the http urls that the cache API is allowed
// to fetch and cache are limited by the host permissions
// associated to the extensions (same as when the extension
// for fetch from those urls using fetch or XHR).
await browser.test.assertRejects(
cache.add(`http://anotherdomain.com/dummy`),
"NetworkError when attempting to fetch resource.",
"Got the expected rejection of requesting an http not allowed by host permissions"
);
// Test that deleting the cache storage works as expected.
browser.test.assertTrue(
await window.caches.delete("test-cache-api"),
"Cache deleted successfully"
);
browser.test.assertTrue(
!(await window.caches.has("test-cache-api")),
"CacheStorage.has should resolve to false"
);
} catch (err) {
browser.test.fail(`Unexpected error on using Cache API: ${err}`);
throw err;
} finally {
browser.test.sendMessage("test-cache-api-allowed");
}
}
// Verify that Cache API support for http urls is available
// regardless of extensions.backgroundServiceWorker.enabled pref.
const extension = ExtensionTestUtils.loadExtension({
manifest: { permissions: ["http://example.com/*"] },
background,
});
await extension.startup();
await extension.awaitMessage("test-cache-api-allowed");
await extension.unload();
});
add_task(async function test_cache_storage_evicted_on_addon_uninstalled() {
async function background() {
try {
const BASE_URL = `http://example.com/dummy`;
const cache = await window.caches.open("test-cache-api");
browser.test.assertTrue(
await window.caches.has("test-cache-api"),
"CacheStorage.has should resolve to true"
);
// Test that adding and requesting cached http urls
// works as well.
await cache.add(BASE_URL);
browser.test.assertEq(
"test_ext_cache_api.js",
await cache.match(BASE_URL).then(res => res.text()),
"Got the expected content from the cached http url"
);
} catch (err) {
browser.test.fail(`Unexpected error on using Cache API: ${err}`);
throw err;
} finally {
browser.test.sendMessage("cache-storage-created");
}
}
const extension = ExtensionTestUtils.loadExtension({
manifest: { permissions: ["http://example.com/*"] },
background,
// Necessary to be sure the expected extension stored data cleanup callback
// will be called when the extension is uninstalled from an AddonManager
// perspective.
useAddonManager: "temporary",
});
await AddonTestUtils.promiseStartupManager();
await extension.startup();
await extension.awaitMessage("cache-storage-created");
const extURL = `moz-extension://${extension.extension.uuid}`;
const extPrincipal = Services.scriptSecurityManager.createContentPrincipal(
Services.io.newURI(extURL),
{}
);
let extCacheStorage = new CacheStorage("content", extPrincipal);
ok(
await extCacheStorage.has("test-cache-api"),
"Got the expected extension cache storage"
);
await extension.unload();
ok(
!(await extCacheStorage.has("test-cache-api")),
"The extension cache storage data should have been evicted on addon uninstall"
);
});

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

@ -34,6 +34,7 @@ skip-if = appname == "thunderbird" || os == "android"
[test_ext_browsingData.js]
[test_ext_browsingData_cookies_cache.js]
[test_ext_browsingData_cookies_cookieStoreId.js]
[test_ext_cache_api.js]
[test_ext_captivePortal.js]
# As with test_captive_portal_service.js, we use the same limits here.
skip-if = appname == "thunderbird" || os == "android" || (os == "mac" && debug) # CP service is disabled on Android, macosx1014/debug due to 1564534