mirror of
https://github.com/ManchildProductions/UXP-Fixed.git
synced 2026-06-14 20:49:05 +00:00
335 lines
12 KiB
JavaScript
335 lines
12 KiB
JavaScript
/* -*- Mode: indent-tabs-mode: nil; js-indent-level: 2 -*- */
|
|
/* vim: set sts=2 sw=2 et tw=80: */
|
|
"use strict";
|
|
|
|
const STORAGE_SYNC_PREF = "webextensions.storage.sync.enabled";
|
|
Cu.import("resource://gre/modules/Preferences.jsm");
|
|
|
|
/**
|
|
* Utility function to ensure that all supported APIs for getting are
|
|
* tested.
|
|
*
|
|
* @param {string} areaName
|
|
* either "local" or "sync" according to what we want to test
|
|
* @param {string} prop
|
|
* "key" to look up using the storage API
|
|
* @param {Object} value
|
|
* "value" to compare against
|
|
*/
|
|
async function checkGetImpl(areaName, prop, value) {
|
|
let storage = browser.storage[areaName];
|
|
|
|
let data = await storage.get(null);
|
|
browser.test.assertEq(value, data[prop], `null getter worked for ${prop} in ${areaName}`);
|
|
|
|
data = await storage.get(prop);
|
|
browser.test.assertEq(value, data[prop], `string getter worked for ${prop} in ${areaName}`);
|
|
|
|
data = await storage.get([prop]);
|
|
browser.test.assertEq(value, data[prop], `array getter worked for ${prop} in ${areaName}`);
|
|
|
|
data = await storage.get({[prop]: undefined});
|
|
browser.test.assertEq(value, data[prop], `object getter worked for ${prop} in ${areaName}`);
|
|
}
|
|
|
|
add_task(function* test_local_cache_invalidation() {
|
|
function background(checkGet) {
|
|
browser.test.onMessage.addListener(async msg => {
|
|
if (msg === "set-initial") {
|
|
await browser.storage.local.set({"test-prop1": "value1", "test-prop2": "value2"});
|
|
browser.test.sendMessage("set-initial-done");
|
|
} else if (msg === "check") {
|
|
await checkGet("local", "test-prop1", "value1");
|
|
await checkGet("local", "test-prop2", "value2");
|
|
browser.test.sendMessage("check-done");
|
|
}
|
|
});
|
|
|
|
browser.test.sendMessage("ready");
|
|
}
|
|
|
|
let extension = ExtensionTestUtils.loadExtension({
|
|
manifest: {
|
|
permissions: ["storage"],
|
|
},
|
|
background: `(${background})(${checkGetImpl})`,
|
|
});
|
|
|
|
yield extension.startup();
|
|
yield extension.awaitMessage("ready");
|
|
|
|
extension.sendMessage("set-initial");
|
|
yield extension.awaitMessage("set-initial-done");
|
|
|
|
Services.obs.notifyObservers(null, "extension-invalidate-storage-cache", "");
|
|
|
|
extension.sendMessage("check");
|
|
yield extension.awaitMessage("check-done");
|
|
|
|
yield extension.unload();
|
|
});
|
|
|
|
add_task(function* test_config_flag_needed() {
|
|
function background() {
|
|
let promises = [];
|
|
let apiTests = [
|
|
{method: "get", args: ["foo"]},
|
|
{method: "set", args: [{foo: "bar"}]},
|
|
{method: "remove", args: ["foo"]},
|
|
{method: "clear", args: []},
|
|
];
|
|
apiTests.forEach(testDef => {
|
|
promises.push(browser.test.assertRejects(
|
|
browser.storage.sync[testDef.method](...testDef.args),
|
|
"Please set webextensions.storage.sync.enabled to true in about:config",
|
|
`storage.sync.${testDef.method} is behind a flag`));
|
|
});
|
|
|
|
Promise.all(promises).then(() => browser.test.notifyPass("flag needed"));
|
|
}
|
|
|
|
ok(!Preferences.get(STORAGE_SYNC_PREF));
|
|
let extension = ExtensionTestUtils.loadExtension({
|
|
manifest: {
|
|
permissions: ["storage"],
|
|
},
|
|
background: `(${background})(${checkGetImpl})`,
|
|
});
|
|
|
|
yield extension.startup();
|
|
yield extension.awaitFinish("flag needed");
|
|
yield extension.unload();
|
|
});
|
|
|
|
add_task(function* test_reloading_extensions_works() {
|
|
// Just some random extension ID that we can re-use
|
|
const extensionId = "my-extension-id@1";
|
|
|
|
function loadExtension() {
|
|
function background() {
|
|
browser.storage.sync.set({"a": "b"}).then(() => {
|
|
browser.test.notifyPass("set-works");
|
|
});
|
|
}
|
|
|
|
return ExtensionTestUtils.loadExtension({
|
|
manifest: {
|
|
permissions: ["storage"],
|
|
},
|
|
background: `(${background})()`,
|
|
}, extensionId);
|
|
}
|
|
|
|
Preferences.set(STORAGE_SYNC_PREF, true);
|
|
|
|
let extension1 = loadExtension();
|
|
|
|
yield extension1.startup();
|
|
yield extension1.awaitFinish("set-works");
|
|
yield extension1.unload();
|
|
|
|
let extension2 = loadExtension();
|
|
|
|
yield extension2.startup();
|
|
yield extension2.awaitFinish("set-works");
|
|
yield extension2.unload();
|
|
|
|
Preferences.reset(STORAGE_SYNC_PREF);
|
|
});
|
|
|
|
do_register_cleanup(() => {
|
|
Preferences.reset(STORAGE_SYNC_PREF);
|
|
});
|
|
|
|
add_task(function* test_backgroundScript() {
|
|
async function backgroundScript(checkGet) {
|
|
let globalChanges, gResolve;
|
|
function clearGlobalChanges() {
|
|
globalChanges = new Promise(resolve => { gResolve = resolve; });
|
|
}
|
|
clearGlobalChanges();
|
|
let expectedAreaName;
|
|
|
|
browser.storage.onChanged.addListener((changes, areaName) => {
|
|
browser.test.assertEq(expectedAreaName, areaName,
|
|
"Expected area name received by listener");
|
|
gResolve(changes);
|
|
});
|
|
|
|
async function checkChanges(areaName, changes, message) {
|
|
function checkSub(obj1, obj2) {
|
|
for (let prop in obj1) {
|
|
browser.test.assertTrue(obj1[prop] !== undefined,
|
|
`checkChanges ${areaName} ${prop} is missing (${message})`);
|
|
browser.test.assertTrue(obj2[prop] !== undefined,
|
|
`checkChanges ${areaName} ${prop} is missing (${message})`);
|
|
browser.test.assertEq(obj1[prop].oldValue, obj2[prop].oldValue,
|
|
`checkChanges ${areaName} ${prop} old (${message})`);
|
|
browser.test.assertEq(obj1[prop].newValue, obj2[prop].newValue,
|
|
`checkChanges ${areaName} ${prop} new (${message})`);
|
|
}
|
|
}
|
|
|
|
const recentChanges = await globalChanges;
|
|
checkSub(changes, recentChanges);
|
|
checkSub(recentChanges, changes);
|
|
clearGlobalChanges();
|
|
}
|
|
|
|
/* eslint-disable dot-notation */
|
|
async function runTests(areaName) {
|
|
expectedAreaName = areaName;
|
|
let storage = browser.storage[areaName];
|
|
// Set some data and then test getters.
|
|
try {
|
|
await storage.set({"test-prop1": "value1", "test-prop2": "value2"});
|
|
await checkChanges(areaName,
|
|
{"test-prop1": {newValue: "value1"}, "test-prop2": {newValue: "value2"}},
|
|
"set (a)");
|
|
|
|
await checkGet(areaName, "test-prop1", "value1");
|
|
await checkGet(areaName, "test-prop2", "value2");
|
|
|
|
let data = await storage.get({"test-prop1": undefined, "test-prop2": undefined, "other": "default"});
|
|
browser.test.assertEq("value1", data["test-prop1"], "prop1 correct (a)");
|
|
browser.test.assertEq("value2", data["test-prop2"], "prop2 correct (a)");
|
|
browser.test.assertEq("default", data["other"], "other correct");
|
|
|
|
data = await storage.get(["test-prop1", "test-prop2", "other"]);
|
|
browser.test.assertEq("value1", data["test-prop1"], "prop1 correct (b)");
|
|
browser.test.assertEq("value2", data["test-prop2"], "prop2 correct (b)");
|
|
browser.test.assertFalse("other" in data, "other correct");
|
|
|
|
// Remove data in various ways.
|
|
await storage.remove("test-prop1");
|
|
await checkChanges(areaName, {"test-prop1": {oldValue: "value1"}}, "remove string");
|
|
|
|
data = await storage.get(["test-prop1", "test-prop2"]);
|
|
browser.test.assertFalse("test-prop1" in data, "prop1 absent (remove string)");
|
|
browser.test.assertTrue("test-prop2" in data, "prop2 present (remove string)");
|
|
|
|
await storage.set({"test-prop1": "value1"});
|
|
await checkChanges(areaName, {"test-prop1": {newValue: "value1"}}, "set (c)");
|
|
|
|
data = await storage.get(["test-prop1", "test-prop2"]);
|
|
browser.test.assertEq(data["test-prop1"], "value1", "prop1 correct (c)");
|
|
browser.test.assertEq(data["test-prop2"], "value2", "prop2 correct (c)");
|
|
|
|
await storage.remove(["test-prop1", "test-prop2"]);
|
|
await checkChanges(areaName,
|
|
{"test-prop1": {oldValue: "value1"}, "test-prop2": {oldValue: "value2"}},
|
|
"remove array");
|
|
|
|
data = await storage.get(["test-prop1", "test-prop2"]);
|
|
browser.test.assertFalse("test-prop1" in data, "prop1 absent (remove array)");
|
|
browser.test.assertFalse("test-prop2" in data, "prop2 absent (remove array)");
|
|
|
|
// test storage.clear
|
|
await storage.set({"test-prop1": "value1", "test-prop2": "value2"});
|
|
// Make sure that set() handler happened before we clear the
|
|
// promise again.
|
|
await globalChanges;
|
|
|
|
clearGlobalChanges();
|
|
await storage.clear();
|
|
|
|
await checkChanges(areaName,
|
|
{"test-prop1": {oldValue: "value1"}, "test-prop2": {oldValue: "value2"}},
|
|
"clear");
|
|
data = await storage.get(["test-prop1", "test-prop2"]);
|
|
browser.test.assertFalse("test-prop1" in data, "prop1 absent (clear)");
|
|
browser.test.assertFalse("test-prop2" in data, "prop2 absent (clear)");
|
|
|
|
// Make sure we can store complex JSON data.
|
|
// known previous values
|
|
await storage.set({"test-prop1": "value1", "test-prop2": "value2"});
|
|
|
|
// Make sure the set() handler landed.
|
|
await globalChanges;
|
|
|
|
clearGlobalChanges();
|
|
await storage.set({
|
|
"test-prop1": {
|
|
str: "hello",
|
|
bool: true,
|
|
null: null,
|
|
undef: undefined,
|
|
obj: {},
|
|
arr: [1, 2],
|
|
date: new Date(0),
|
|
regexp: /regexp/,
|
|
func: function func() {},
|
|
window,
|
|
},
|
|
});
|
|
|
|
await storage.set({"test-prop2": function func() {}});
|
|
const recentChanges = await globalChanges;
|
|
|
|
browser.test.assertEq("value1", recentChanges["test-prop1"].oldValue, "oldValue correct");
|
|
browser.test.assertEq("object", typeof(recentChanges["test-prop1"].newValue), "newValue is obj");
|
|
clearGlobalChanges();
|
|
|
|
data = await storage.get({"test-prop1": undefined, "test-prop2": undefined});
|
|
let obj = data["test-prop1"];
|
|
|
|
browser.test.assertEq("hello", obj.str, "string part correct");
|
|
browser.test.assertEq(true, obj.bool, "bool part correct");
|
|
browser.test.assertEq(null, obj.null, "null part correct");
|
|
browser.test.assertEq(undefined, obj.undef, "undefined part correct");
|
|
browser.test.assertEq(undefined, obj.func, "function part correct");
|
|
browser.test.assertEq(undefined, obj.window, "window part correct");
|
|
browser.test.assertEq("1970-01-01T00:00:00.000Z", obj.date, "date part correct");
|
|
browser.test.assertEq("/regexp/", obj.regexp, "regexp part correct");
|
|
browser.test.assertEq("object", typeof(obj.obj), "object part correct");
|
|
browser.test.assertTrue(Array.isArray(obj.arr), "array part present");
|
|
browser.test.assertEq(1, obj.arr[0], "arr[0] part correct");
|
|
browser.test.assertEq(2, obj.arr[1], "arr[1] part correct");
|
|
browser.test.assertEq(2, obj.arr.length, "arr.length part correct");
|
|
|
|
obj = data["test-prop2"];
|
|
|
|
browser.test.assertEq("[object Object]", {}.toString.call(obj), "function serialized as a plain object");
|
|
browser.test.assertEq(0, Object.keys(obj).length, "function serialized as an empty object");
|
|
} catch (e) {
|
|
browser.test.fail(`Error: ${e} :: ${e.stack}`);
|
|
browser.test.notifyFail("storage");
|
|
}
|
|
}
|
|
|
|
browser.test.onMessage.addListener(msg => {
|
|
let promise;
|
|
if (msg === "test-local") {
|
|
promise = runTests("local");
|
|
} else if (msg === "test-sync") {
|
|
promise = runTests("sync");
|
|
}
|
|
promise.then(() => browser.test.sendMessage("test-finished"));
|
|
});
|
|
|
|
browser.test.sendMessage("ready");
|
|
}
|
|
|
|
let extensionData = {
|
|
background: `(${backgroundScript})(${checkGetImpl})`,
|
|
manifest: {
|
|
permissions: ["storage"],
|
|
},
|
|
};
|
|
|
|
Preferences.set(STORAGE_SYNC_PREF, true);
|
|
|
|
let extension = ExtensionTestUtils.loadExtension(extensionData);
|
|
yield extension.startup();
|
|
yield extension.awaitMessage("ready");
|
|
|
|
extension.sendMessage("test-local");
|
|
yield extension.awaitMessage("test-finished");
|
|
|
|
extension.sendMessage("test-sync");
|
|
yield extension.awaitMessage("test-finished");
|
|
|
|
Preferences.reset(STORAGE_SYNC_PREF);
|
|
yield extension.unload();
|
|
});
|