mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-28 23:31:56 +00:00
Bug 1331618 - allow persistent indexedDB on unlimitedStorage permission. r=aswan
MozReview-Commit-ID: 6VYqywMgSoU --HG-- extra : rebase_source : 39cd28f5085335e8e1eb6ff39a4f5af2c0d9c2c7
This commit is contained in:
parent
93e3a7df66
commit
c9af23586a
@ -111,6 +111,7 @@ webextPerms.description.privacy=Read and modify privacy settings
|
||||
webextPerms.description.sessions=Access recently closed tabs
|
||||
webextPerms.description.tabs=Access browser tabs
|
||||
webextPerms.description.topSites=Access browsing history
|
||||
webextPerms.description.unlimitedStorage=Store unlimited amount of client-side data
|
||||
webextPerms.description.webNavigation=Access browser activity during navigation
|
||||
|
||||
webextPerms.hostDescription.allUrls=Access your data for all websites
|
||||
|
@ -282,6 +282,12 @@ var UninstallObserver = {
|
||||
if (storage) {
|
||||
storage.clear();
|
||||
}
|
||||
|
||||
// Remove any permissions related to the unlimitedStorage permission
|
||||
// if we are also removing all the data stored by the extension.
|
||||
Services.perms.removeFromPrincipal(principal, "WebExtensions-unlimitedStorage");
|
||||
Services.perms.removeFromPrincipal(principal, "indexedDB");
|
||||
Services.perms.removeFromPrincipal(principal, "persistent-storage");
|
||||
}
|
||||
|
||||
if (!this.leaveUuid) {
|
||||
@ -996,6 +1002,31 @@ this.Extension = class extends ExtensionData {
|
||||
return super.initLocale(locale);
|
||||
}
|
||||
|
||||
initUnlimitedStoragePermission() {
|
||||
const principal = this.principal;
|
||||
|
||||
// Check if the site permission has already been set for the extension by the WebExtensions
|
||||
// internals (instead of being manually allowed by the user).
|
||||
const hasSitePermission = Services.perms.testPermissionFromPrincipal(
|
||||
principal, "WebExtensions-unlimitedStorage"
|
||||
);
|
||||
|
||||
if (this.hasPermission("unlimitedStorage")) {
|
||||
// Set the indexedDB permission and a custom "WebExtensions-unlimitedStorage" to remember
|
||||
// that the permission hasn't been selected manually by the user.
|
||||
Services.perms.addFromPrincipal(principal, "WebExtensions-unlimitedStorage",
|
||||
Services.perms.ALLOW_ACTION);
|
||||
Services.perms.addFromPrincipal(principal, "indexedDB", Services.perms.ALLOW_ACTION);
|
||||
Services.perms.addFromPrincipal(principal, "persistent-storage", Services.perms.ALLOW_ACTION);
|
||||
} else if (hasSitePermission) {
|
||||
// Remove the indexedDB permission if it has been enabled using the
|
||||
// unlimitedStorage WebExtensions permissions.
|
||||
Services.perms.removeFromPrincipal(principal, "WebExtensions-unlimitedStorage");
|
||||
Services.perms.removeFromPrincipal(principal, "indexedDB");
|
||||
Services.perms.removeFromPrincipal(principal, "persistent-storage");
|
||||
}
|
||||
}
|
||||
|
||||
startup() {
|
||||
this.startupPromise = this._startup();
|
||||
return this.startupPromise;
|
||||
@ -1058,6 +1089,8 @@ this.Extension = class extends ExtensionData {
|
||||
this.policy.active = false;
|
||||
this.policy = processScript.initExtension(this.serialize(), this);
|
||||
|
||||
this.initUnlimitedStoragePermission();
|
||||
|
||||
// The "startup" Management event sent on the extension instance itself
|
||||
// is emitted just before the Management "startup" event,
|
||||
// and it is used to run code that needs to be executed before
|
||||
|
@ -245,7 +245,8 @@
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"alarms",
|
||||
"storage"
|
||||
"storage",
|
||||
"unlimitedStorage"
|
||||
]
|
||||
}
|
||||
]
|
||||
|
@ -0,0 +1,34 @@
|
||||
/* -*- Mode: indent-tabs-mode: nil; js-indent-level: 2 -*- */
|
||||
/* vim: set sts=2 sw=2 et tw=80: */
|
||||
"use strict";
|
||||
|
||||
/* exported checkSitePermissions */
|
||||
|
||||
const {Services, Cu} = SpecialPowers;
|
||||
const {NetUtil} = Cu.import("resource://gre/modules/NetUtil.jsm", {});
|
||||
|
||||
function checkSitePermissions(uuid, expectedPermAction, assertMessage) {
|
||||
if (!uuid) {
|
||||
throw new Error("checkSitePermissions should not be called with an undefined uuid");
|
||||
}
|
||||
|
||||
const baseURI = NetUtil.newURI(`moz-extension://${uuid}/`);
|
||||
const principal = Services.scriptSecurityManager.createCodebasePrincipal(baseURI, {});
|
||||
|
||||
const sitePermissions = {
|
||||
webextUnlimitedStorage: Services.perms.testPermissionFromPrincipal(
|
||||
principal, "WebExtensions-unlimitedStorage"
|
||||
),
|
||||
indexedDB: Services.perms.testPermissionFromPrincipal(
|
||||
principal, "indexedDB"
|
||||
),
|
||||
persistentStorage: Services.perms.testPermissionFromPrincipal(
|
||||
principal, "WebExtensions-unlimitedStorage"
|
||||
),
|
||||
};
|
||||
|
||||
for (const [sitePermissionName, actualPermAction] of Object.entries(sitePermissions)) {
|
||||
is(actualPermAction, expectedPermAction,
|
||||
`The extension "${sitePermissionName}" SitePermission ${assertMessage} as expected`);
|
||||
}
|
||||
}
|
@ -2,8 +2,9 @@
|
||||
support-files =
|
||||
chrome_cleanup_script.js
|
||||
head.js
|
||||
file_mixed.html
|
||||
head_unlimitedStorage.js
|
||||
head_webrequest.js
|
||||
file_mixed.html
|
||||
file_csp.html
|
||||
file_csp.html^headers^
|
||||
file_to_drawWindow.html
|
||||
@ -102,6 +103,11 @@ scheme=https
|
||||
[test_ext_background_teardown.html]
|
||||
[test_ext_tab_teardown.html]
|
||||
skip-if = os == 'android' # Bug 1258975 on android.
|
||||
[test_ext_unlimitedStorage.html]
|
||||
[test_ext_unlimitedStorage_legacy_persistent_indexedDB.html]
|
||||
# IndexedDB persistent storage mode is not allowed on Fennec from a non-chrome privileged code
|
||||
# (it has only been enabled for apps and privileged code). See Bug 1119462 for additional info.
|
||||
skip-if = os == 'android'
|
||||
[test_ext_unload_frame.html]
|
||||
[test_ext_listener_proxies.html]
|
||||
[test_ext_web_accessible_resources.html]
|
||||
@ -120,4 +126,4 @@ skip-if = os == 'android' # Currently fails in emulator tests
|
||||
[test_ext_webnavigation_filters.html]
|
||||
[test_ext_window_postMessage.html]
|
||||
[test_ext_subframes_privileges.html]
|
||||
[test_ext_xhr_capabilities.html]
|
||||
[test_ext_xhr_capabilities.html]
|
@ -0,0 +1,140 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<title>Test for simple WebExtension</title>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SpawnTask.js"></script>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/ExtensionTestUtils.js"></script>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
|
||||
<script type="text/javascript" src="head.js"></script>
|
||||
<script type="text/javascript" src="head_unlimitedStorage.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<script type="text/javascript">
|
||||
|
||||
"use strict";
|
||||
|
||||
add_task(async function test_background_storagePersist() {
|
||||
await SpecialPowers.pushPrefEnv({
|
||||
"set": [
|
||||
["dom.storageManager.enabled", true],
|
||||
// Enable the storageManager permission prompt.
|
||||
["browser.storageManager.enabled", true],
|
||||
["dom.storageManager.prompt.testing", false],
|
||||
["dom.storageManager.prompt.testing.allow", false],
|
||||
],
|
||||
});
|
||||
|
||||
const EXTENSION_ID = "test-storagePersist@mozilla";
|
||||
|
||||
const extension = ExtensionTestUtils.loadExtension({
|
||||
useAddonManager: "permanent",
|
||||
|
||||
manifest: {
|
||||
permissions: ["unlimitedStorage"],
|
||||
applications: {
|
||||
gecko: {
|
||||
id: EXTENSION_ID,
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
background: async function() {
|
||||
const PROMISE_RACE_TIMEOUT = 2000;
|
||||
|
||||
browser.test.sendMessage("extension-uuid", window.location.host);
|
||||
|
||||
const requestStoragePersist = async () => {
|
||||
const persistAllowed = await navigator.storage.persist();
|
||||
if (!persistAllowed) {
|
||||
throw new Error("navigator.storage.persist() has been denied");
|
||||
}
|
||||
};
|
||||
|
||||
await Promise.race([
|
||||
requestStoragePersist(),
|
||||
new Promise((resolve, reject) => {
|
||||
setTimeout(() => {
|
||||
reject(new Error("Timeout opening persistent db from background page"));
|
||||
}, PROMISE_RACE_TIMEOUT);
|
||||
}),
|
||||
]).then(
|
||||
() => {
|
||||
browser.test.notifyPass("indexeddb-storagePersistent-unlimitedStorage-done");
|
||||
},
|
||||
(error) => {
|
||||
browser.test.fail(`error while testing persistent IndexedDB storage: ${error}`);
|
||||
browser.test.notifyFail("indexeddb-storagePersistent-unlimitedStorage-done");
|
||||
}
|
||||
);
|
||||
},
|
||||
});
|
||||
|
||||
await extension.startup();
|
||||
|
||||
const uuid = await extension.awaitMessage("extension-uuid");
|
||||
|
||||
await extension.awaitFinish("indexeddb-storagePersistent-unlimitedStorage-done");
|
||||
await extension.unload();
|
||||
|
||||
checkSitePermissions(uuid, Services.perms.UNKNOWN_ACTION, "has been cleared");
|
||||
});
|
||||
|
||||
add_task(async function test_unlimitedStorage_removed_on_update() {
|
||||
const EXTENSION_ID = "test-unlimitedStorage-removed-on-update@mozilla";
|
||||
|
||||
let extension = ExtensionTestUtils.loadExtension({
|
||||
manifest: {
|
||||
permissions: ["unlimitedStorage"],
|
||||
applications: {
|
||||
gecko: {
|
||||
id: EXTENSION_ID,
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
background: async function() {
|
||||
browser.test.sendMessage("extension-uuid", window.location.host);
|
||||
},
|
||||
});
|
||||
|
||||
await extension.startup();
|
||||
|
||||
const uuid = await extension.awaitMessage("extension-uuid");
|
||||
|
||||
checkSitePermissions(uuid, Services.perms.ALLOW_ACTION, "has been allowed");
|
||||
|
||||
await extension.unload();
|
||||
|
||||
// Simulate an update which do not require the unlimitedStorage permission.
|
||||
let updatedExtension = ExtensionTestUtils.loadExtension({
|
||||
manifest: {
|
||||
applications: {
|
||||
gecko: {
|
||||
id: EXTENSION_ID,
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
background: async function() {
|
||||
browser.test.sendMessage("updated-extension-uuid", window.location.host);
|
||||
},
|
||||
});
|
||||
|
||||
updatedExtension.startup();
|
||||
|
||||
const updatedExtensionUUID = await updatedExtension.awaitMessage("updated-extension-uuid");
|
||||
|
||||
is(uuid, updatedExtensionUUID, "The updated extension has the same uuid");
|
||||
|
||||
checkSitePermissions(uuid, Services.perms.UNKNOWN_ACTION, "has been cleared");
|
||||
|
||||
await updatedExtension.unload();
|
||||
});
|
||||
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
@ -0,0 +1,82 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<title>Test for simple WebExtension</title>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SpawnTask.js"></script>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/ExtensionTestUtils.js"></script>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
|
||||
<script type="text/javascript" src="head.js"></script>
|
||||
<script type="text/javascript" src="head_unlimitedStorage.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<script type="text/javascript">
|
||||
|
||||
"use strict";
|
||||
|
||||
add_task(async function test_legacy_indexedDB_storagePersistent_unlimitedStorage() {
|
||||
const EXTENSION_ID = "test-idbStoragePersistent@mozilla";
|
||||
|
||||
const extension = ExtensionTestUtils.loadExtension({
|
||||
useAddonManager: "permanent",
|
||||
|
||||
manifest: {
|
||||
permissions: ["unlimitedStorage"],
|
||||
applications: {
|
||||
gecko: {
|
||||
id: EXTENSION_ID,
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
background: async function() {
|
||||
const PROMISE_RACE_TIMEOUT = 2000;
|
||||
|
||||
browser.test.sendMessage("extension-uuid", window.location.host);
|
||||
|
||||
try {
|
||||
await Promise.race([
|
||||
new Promise((resolve, reject) => {
|
||||
const dbReq = indexedDB.open("test-persistent-idb", {version: 1.0, storage: "persistent"});
|
||||
|
||||
dbReq.onerror = evt => {
|
||||
reject(evt.target.error);
|
||||
};
|
||||
|
||||
dbReq.onsuccess = () => {
|
||||
resolve();
|
||||
};
|
||||
}),
|
||||
new Promise((resolve, reject) => {
|
||||
setTimeout(() => {
|
||||
reject(new Error("Timeout opening persistent db from background page"));
|
||||
}, PROMISE_RACE_TIMEOUT);
|
||||
}),
|
||||
]);
|
||||
|
||||
browser.test.notifyPass("indexeddb-storagePersistent-unlimitedStorage-done");
|
||||
} catch (error) {
|
||||
const loggedError = error instanceof DOMError ? error.message : error;
|
||||
browser.test.fail(`error while testing persistent IndexedDB storage: ${loggedError}`);
|
||||
browser.test.notifyFail("indexeddb-storagePersistent-unlimitedStorage-done");
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
await extension.startup();
|
||||
|
||||
const uuid = await extension.awaitMessage("extension-uuid");
|
||||
|
||||
await extension.awaitFinish("indexeddb-storagePersistent-unlimitedStorage-done");
|
||||
|
||||
await extension.unload();
|
||||
|
||||
checkSitePermissions(uuid, Services.perms.UNKNOWN_ACTION, "has been cleared");
|
||||
});
|
||||
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
Loading…
Reference in New Issue
Block a user