diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-28 14:29:10 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-28 14:29:10 +0000 |
commit | 2aa4a82499d4becd2284cdb482213d541b8804dd (patch) | |
tree | b80bf8bf13c3766139fbacc530efd0dd9d54394c /dom/tests/mochitest/localstorage | |
parent | Initial commit. (diff) | |
download | firefox-upstream.tar.xz firefox-upstream.zip |
Adding upstream version 86.0.1.upstream/86.0.1upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'dom/tests/mochitest/localstorage')
46 files changed, 3280 insertions, 0 deletions
diff --git a/dom/tests/mochitest/localstorage/chrome.ini b/dom/tests/mochitest/localstorage/chrome.ini new file mode 100644 index 0000000000..6cc5562c00 --- /dev/null +++ b/dom/tests/mochitest/localstorage/chrome.ini @@ -0,0 +1,11 @@ +[DEFAULT] +skip-if = os == 'android' +support-files = + page_blank.html + frameQuota.html + interOriginFrame.js + +[test_localStorageBasePrivateBrowsing_perwindowpb.html] +skip-if = true # bug 1156725 +[test_localStorageFromChrome.xhtml] +[test_localStorageQuotaPrivateBrowsing_perwindowpb.html] diff --git a/dom/tests/mochitest/localstorage/file_tryAccessSessionStorage.html b/dom/tests/mochitest/localstorage/file_tryAccessSessionStorage.html new file mode 100644 index 0000000000..1def32a62a --- /dev/null +++ b/dom/tests/mochitest/localstorage/file_tryAccessSessionStorage.html @@ -0,0 +1,10 @@ +<script> + try { + sessionStorage.setItem("am_i_blocked", "nope"); + window.parent.postMessage('sessionStorage=true', '*'); + document.body.innerHTML += 'yes'; + } catch (ex) { + window.parent.postMessage('sessionStorage=false', '*'); + document.body.innerHTML += 'no'; + } +</script> diff --git a/dom/tests/mochitest/localstorage/frameChromeSlave.html b/dom/tests/mochitest/localstorage/frameChromeSlave.html new file mode 100644 index 0000000000..fd87702e9d --- /dev/null +++ b/dom/tests/mochitest/localstorage/frameChromeSlave.html @@ -0,0 +1,9 @@ +<html> +<head> +<body> + <span id="data"></span> + <script> + var span = document.getElementById("data"); + span.innerHTML = localStorage.chromekey + </script> +</body> diff --git a/dom/tests/mochitest/localstorage/frameKeySync.html b/dom/tests/mochitest/localstorage/frameKeySync.html new file mode 100644 index 0000000000..a6b39d47d7 --- /dev/null +++ b/dom/tests/mochitest/localstorage/frameKeySync.html @@ -0,0 +1,51 @@ +<html xmlns="http://www.w3.org/1999/xhtml"> +<head> +<title>frame for localStorage test</title> + +<script type="text/javascript" src="interOriginFrame.js"></script> +<script type="text/javascript"> + +var currentStep = parseInt(location.search.substring(1)); + +function doStep() +{ + switch (currentStep) + { + case 1: + localStorage.clear(); + break; + + case 2: + localStorage.setItem("a", "1"); + is(localStorage.a, "1", "Value a=1 set"); + break; + + case 3: + try { + is(localStorage.key(0), "a", "Key 'a' present in 'key' array") + } + catch (exc) { + ok(false, "Shouldn't throw when accessing key(0) " + exc); + } + is(localStorage.a, "1", "Value a=1 set"); + break; + + default: + return finishTest(); + } + + // Increase by two to as odd number are executed in a window separate from + // where even step are. + ++currentStep; + ++currentStep; + + return true; +} + +</script> + +</head> + +<body onload="postMsg('frame loaded');"> +</body> +</html> diff --git a/dom/tests/mochitest/localstorage/frameLocalStorageCookieSettings.html b/dom/tests/mochitest/localstorage/frameLocalStorageCookieSettings.html new file mode 100644 index 0000000000..4952a81c44 --- /dev/null +++ b/dom/tests/mochitest/localstorage/frameLocalStorageCookieSettings.html @@ -0,0 +1,26 @@ +<html xmlns="http://www.w3.org/1999/xhtml"> +<head> +<title>localStorage cookies settings test</title> + +</head> +<body> +<script type="text/javascript"> + function ok(what, msg) { + parent.postMessage({ type: "ok", what: !!what, msg }, "*"); + } + + function is(a, b, msg) { + ok(a === b, msg); + } + + try { + localStorage.setItem("contentkey", "test-value"); + ok(false, "Setting localStorageItem should throw a security exception"); + } catch(ex) { + is(ex.name, "SecurityError", "Got security exception"); + } + + parent.postMessage({ type: "finish" }, "*"); +</script> +</body> +</html> diff --git a/dom/tests/mochitest/localstorage/frameLocalStorageSessionOnly.html b/dom/tests/mochitest/localstorage/frameLocalStorageSessionOnly.html new file mode 100644 index 0000000000..f6c7f0291f --- /dev/null +++ b/dom/tests/mochitest/localstorage/frameLocalStorageSessionOnly.html @@ -0,0 +1,8 @@ +<!doctype html> +<html> + <body> + <script> + parent.postMessage(SpecialPowers.wrap(localStorage).isSessionOnly, "*"); + </script> + </body> +</html> diff --git a/dom/tests/mochitest/localstorage/frameMasterEqual.html b/dom/tests/mochitest/localstorage/frameMasterEqual.html new file mode 100644 index 0000000000..4d83c4fef2 --- /dev/null +++ b/dom/tests/mochitest/localstorage/frameMasterEqual.html @@ -0,0 +1,56 @@ +<html xmlns="http://www.w3.org/1999/xhtml"> +<head> +<title>frame for localStorage test</title> + +<script type="text/javascript" src="interOriginFrame.js"></script> +<script type="text/javascript"> + +var currentStep = 1; + +function doStep() +{ + switch (currentStep) + { + case 1: + localStorage.setItem("X", "1"); + is(localStorage.getItem("X"), "1", "X is 1 in the master"); + break; + + case 3: + is(localStorage.getItem("X"), "2", "X set to 2 in the master"); + localStorage.removeItem("X"); + is(localStorage.getItem("X"), null, "X was removed from the master"); + break; + + case 5: + is(localStorage.getItem("Y"), "3", "Y is 3 in the master"); + localStorage.setItem("Z", "4"); + is(localStorage.getItem("Z"), "4", "Z is 4 in the master"); + + localStorage.clear(); + is(localStorage.length, 0, "Master is empty"); + break; + + case 7: + is(localStorage.length, 0, "Master is empty"); + break; + + case 9: + return finishTest(); + } + + // Increase by two to distinguish each test step order + // in both master doStep and slave doStep functions. + ++currentStep; + ++currentStep; + + return true; +} + +</script> + +</head> + +<body onload="postMsg('frame loaded');"> +</body> +</html> diff --git a/dom/tests/mochitest/localstorage/frameMasterNotEqual.html b/dom/tests/mochitest/localstorage/frameMasterNotEqual.html new file mode 100644 index 0000000000..fef476bed3 --- /dev/null +++ b/dom/tests/mochitest/localstorage/frameMasterNotEqual.html @@ -0,0 +1,47 @@ +<html xmlns="http://www.w3.org/1999/xhtml"> +<head> +<title>frame for localStorage test</title> + +<script type="text/javascript" src="interOriginFrame.js"></script> +<script type="text/javascript"> + +var currentStep = 1; + +function doStep() +{ + switch (currentStep) + { + case 1: + localStorage.setItem("X", "1"); + is(localStorage.getItem("X"), "1", "X is 1 in the master"); + break; + + case 3: + is(localStorage.getItem("X"), "1", "X remains 1 in the master"); + localStorage.removeItem("X"); + is(localStorage.getItem("X"), null, "X was removed from the master"); + break; + + case 5: + is(localStorage.getItem("Y"), null, "Y null in the master"); + break; + + case 7: + return finishTest(); + } + + // Increase by two to distinguish each test step order + // in both master doStep and slave doStep functions. + ++currentStep; + ++currentStep; + + return true; +} + +</script> + +</head> + +<body onload="postMsg('frame loaded');"> +</body> +</html> diff --git a/dom/tests/mochitest/localstorage/frameOrder.html b/dom/tests/mochitest/localstorage/frameOrder.html new file mode 100644 index 0000000000..3b3f0ebef8 --- /dev/null +++ b/dom/tests/mochitest/localstorage/frameOrder.html @@ -0,0 +1,27 @@ +<html> +<head> +</head> +<script type="text/javascript"> +function doTest() +{ + var query = location.search.substring(1); + query = unescape(query); + var keyNames = eval(query); + + parent.is(localStorage.a, "10", "a = 10"); + parent.is(localStorage.b, "20", "b = 20"); + parent.is(localStorage.c, "30", "c = 30"); + parent.is(localStorage.d, "40", "d = 40"); + parent.is(localStorage.e, "50", "e = 50"); + parent.is(localStorage.length, 5, "length = 5"); + + for (var i = 0; i < localStorage.length; ++i) + parent.is(keyNames[i], localStorage.key(i), "key "+keyNames[i]+" on same index"); + + parent.SimpleTest.finish(); + localStorage.clear(); +} +</script> +<body onload="doTest();"> +</body> +</html> diff --git a/dom/tests/mochitest/localstorage/frameQuota.html b/dom/tests/mochitest/localstorage/frameQuota.html new file mode 100644 index 0000000000..5ff9855c99 --- /dev/null +++ b/dom/tests/mochitest/localstorage/frameQuota.html @@ -0,0 +1,97 @@ +<html xmlns="http://www.w3.org/1999/xhtml"> +<head> +<title>slave for sessionStorage test</title> + +<script type="text/javascript" src="interOriginFrame.js"></script> +<script type="text/javascript"> + +const DOM_QUOTA_EXCEEDED_ERR = 0x80530016; + +function checkException(func, exc) +{ + var exceptionThrew = false; + try { + func(); + } + catch (ex) { + exceptionThrew = true; + is(ex.result, exc, "Expected "+exc+" exception"); + } + ok(exceptionThrew, "Exception "+exc+" threw at "+location); +} + +function doStep() +{ + var query = location.search.substring(1); + var queries = query.split("&"); + + var operation = queries[0]; + var keyName = queries[1]; + var result = queries[2]; + + switch (result) + { + case "success": + switch (operation) + { + case "add": + // Store 500 bytes long string must succeed + localStorage.setItem(keyName, "12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890"); + is(localStorage.getItem(keyName), "12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890", "500 bytes key "+keyName+" stored"); + break; + + case "remove": + localStorage.removeItem(keyName); + is(localStorage.getItem(keyName), null, "Key "+keyName+" removed"); + break; + } + + break; + + case "failure": + switch (operation) + { + case "add": + // Attempt to store 500 bytes long string that doens't + // fit the quota, have to throw DOM_QUOTA_EXCEEDED_ERR exception + checkException(function() { + localStorage.setItem(keyName, "12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890"); + }, DOM_QUOTA_EXCEEDED_ERR); + is(localStorage.getItem(keyName), null, "500 bytes key "+keyName+" is NOT stored"); + break; + + case "add2": + // Attempt to change a key value to reach the DOM quota and + // check it fails and the old key value is still present. + checkException(function() { + localStorage.setItem(keyName, "123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890"); + }, DOM_QUOTA_EXCEEDED_ERR); + is(localStorage.getItem(keyName), "12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890", "Key "+keyName+" left unchanged"); + break; + } + + break; + + default: + switch (operation) + { + case "clear": + localStorage.clear(); + break; + } + + break; + } + + // Just inform the master we are finished now + postMsg("done"); + return false; +} + +</script> + +</head> + +<body onload="postMsg('frame loaded');"> +</body> +</html> diff --git a/dom/tests/mochitest/localstorage/frameQuotaSessionOnly.html b/dom/tests/mochitest/localstorage/frameQuotaSessionOnly.html new file mode 100644 index 0000000000..754a5b3598 --- /dev/null +++ b/dom/tests/mochitest/localstorage/frameQuotaSessionOnly.html @@ -0,0 +1,101 @@ +<html xmlns="http://www.w3.org/1999/xhtml"> +<head> +<title>slave for sessionStorage test</title> + +<script type="text/javascript" src="interOriginFrame.js"></script> +<script type="text/javascript"> + +const DOM_QUOTA_EXCEEDED_ERR = 0x80530016; + +function checkException(func, exc) +{ + var exceptionThrew = false; + try { + func(); + } + catch (ex) { + exceptionThrew = true; + is(ex.result, exc, "Expected "+exc+" exception"); + } + ok(exceptionThrew, "Exception "+exc+" threw at "+location); +} + +function doStep() +{ + var query = location.search.substring(1); + var queries = query.split("&"); + + var operation = queries[0]; + var keyName = queries[1]; + var result = queries[2]; + + switch (result) + { + case "success": + switch (operation) + { + case "add": + // Store 500 bytes long string must succeed + localStorage.setItem(keyName, "12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890"); + is(localStorage.getItem(keyName), "12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890", "500 bytes key "+keyName+" stored"); + break; + + case "remove": + localStorage.removeItem(keyName); + is(localStorage.getItem(keyName), null, "Key "+keyName+" removed"); + break; + } + + break; + + case "failure": + switch (operation) + { + case "add": + // Attempt to store 500 bytes long string that doens't + // fit the quota, have to throw DOM_QUOTA_EXCEEDED_ERR exception + checkException(function() { + localStorage.setItem(keyName, "12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890"); + }, DOM_QUOTA_EXCEEDED_ERR); + is(localStorage.getItem(keyName), null, "500 bytes key "+keyName+" is NOT stored"); + break; + + case "add2": + // Attempt to change a key value to reach the DOM quota and + // check it fails and the old key value is still present. + checkException(function() { + localStorage.setItem(keyName, "123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890"); + }, DOM_QUOTA_EXCEEDED_ERR); + is(localStorage.getItem(keyName), "12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890", "Key "+keyName+" left unchanged"); + break; + } + + break; + + case "": + default: + switch (operation) + { + case "clear": + localStorage.clear(); + break; + } + + break; + } + + // Just inform the master we are finished now + postMsg("done"); + return false; +} + +function startTest() { + postMsg('frame loaded'); +} +</script> + +</head> + +<body onload="startTest();"> +</body> +</html> diff --git a/dom/tests/mochitest/localstorage/frameReplace.html b/dom/tests/mochitest/localstorage/frameReplace.html new file mode 100644 index 0000000000..145bfe8fce --- /dev/null +++ b/dom/tests/mochitest/localstorage/frameReplace.html @@ -0,0 +1,72 @@ +<html xmlns="http://www.w3.org/1999/xhtml"> +<head> +<title>localStorage replace frame</title> + +<script type="text/javascript"> + +var shell; + +function ok(a, message) +{ + if (!a) + shell.postMessage("FAILURE: " + message, "http://mochi.test:8888"); + else + shell.postMessage(message, "http://mochi.test:8888"); +} + +function is(a, b, message) +{ + if (a != b) + shell.postMessage("FAILURE: " + message + ", expected "+b+" got "+a, "http://mochi.test:8888"); + else + shell.postMessage(message + ", expected "+b+" got "+a, "http://mochi.test:8888"); +} + +function doTest() +{ + var query = location.search.substring(1); + var queries = query.split("&"); + + var action = queries[0]; + shell = queries[1]; + switch (shell) + { + case "frame": + shell = parent; + break; + case "window": + shell = opener; + break; + } + + switch (action) + { + case "init": + localStorage.setItem("A", "1"); + localStorage.setItem("B", "2"); + localStorage.setItem("C", "3"); + is(localStorage.getItem("A"), "1", "'A' is '1'"); + is(localStorage.getItem("B"), "2", "'A' is '2'"); + is(localStorage.getItem("C"), "3", "'A' is '3'"); + break; + + case "check": + is(localStorage.getItem("A"), null, "'A' is null"); + is(localStorage.getItem("B"), null, "'A' is null"); + is(localStorage.getItem("C"), null, "'A' is null"); + break; + + case "clean": + localStorage.clear(); + break; + } + + shell.postMessage(action + "_done", "http://mochi.test:8888"); +} + +</script> + +</head> +<body onload="doTest();"> +</body> +</html> diff --git a/dom/tests/mochitest/localstorage/frameSlaveEqual.html b/dom/tests/mochitest/localstorage/frameSlaveEqual.html new file mode 100644 index 0000000000..b64b8de10a --- /dev/null +++ b/dom/tests/mochitest/localstorage/frameSlaveEqual.html @@ -0,0 +1,51 @@ +<html xmlns="http://www.w3.org/1999/xhtml"> +<head> +<title>frame for localStorage test</title> + +<script type="text/javascript" src="interOriginFrame.js"></script> +<script type="text/javascript"> + +var currentStep = 2; + +function doStep() +{ + switch (currentStep) + { + case 2: + is(localStorage.getItem("X"), "1", "X is 1 in the slave"); + localStorage.setItem("X", "2"); + is(localStorage.getItem("X"), "2", "X set to 2 in the slave"); + break; + + case 4: + is(localStorage.getItem("X"), null, "X was removed from the slave"); + localStorage.setItem("Y", "3"); + is(localStorage.getItem("Y"), "3", "Y set to 3 in the slave"); + break; + + case 6: + is(localStorage.length, 0, "Slave is empty"); + is(localStorage.getItem("X"), null, "X is null in the slave"); + is(localStorage.getItem("Y"), null, "Y is null in the slave"); + is(localStorage.getItem("Z"), null, "Z is null in the slave"); + break; + + case 8: + return finishTest(); + } + + // Increase by two to distinguish each test step order + // in both master doStep and slave doStep functions. + ++currentStep; + ++currentStep; + + return true; +} + +</script> + +</head> + +<body onload="postMsg('frame loaded');"> +</body> +</html> diff --git a/dom/tests/mochitest/localstorage/frameSlaveNotEqual.html b/dom/tests/mochitest/localstorage/frameSlaveNotEqual.html new file mode 100644 index 0000000000..9daf9e9f73 --- /dev/null +++ b/dom/tests/mochitest/localstorage/frameSlaveNotEqual.html @@ -0,0 +1,44 @@ +<html xmlns="http://www.w3.org/1999/xhtml"> +<head> +<title>frame for localStorage test</title> + +<script type="text/javascript" src="interOriginFrame.js"></script> +<script type="text/javascript"> + +var currentStep = 2; + +function doStep() +{ + switch (currentStep) + { + case 2: + is(localStorage.getItem("X"), null, "X not set in the slave"); + localStorage.setItem("X", "2"); + is(localStorage.getItem("X"), "2", "X set to 2 in the slave"); + break; + + case 4: + is(localStorage.getItem("X"), "2", "X still set to 2 in the slave"); + localStorage.setItem("Y", "3"); + is(localStorage.getItem("Y"), "3", "Y set to 4 (MUST FAIL!) in the slave"); + break; + + case 6: + return finishTest(); + } + + // Increase by two to distinguish each test step order + // in both master doStep and slave doStep functions. + ++currentStep; + ++currentStep; + + return true; +} + +</script> + +</head> + +<body onload="postMsg('frame loaded');"> +</body> +</html> diff --git a/dom/tests/mochitest/localstorage/interOriginFrame.js b/dom/tests/mochitest/localstorage/interOriginFrame.js new file mode 100644 index 0000000000..64470c4ef6 --- /dev/null +++ b/dom/tests/mochitest/localstorage/interOriginFrame.js @@ -0,0 +1,53 @@ +function postMsg(message) { + parent.postMessage(message, "http://mochi.test:8888"); +} + +window.addEventListener("message", onMessageReceived); + +function onMessageReceived(event) { + if (event.data == "step") { + var performed = false; + try { + performed = doStep(); + } catch (ex) { + postMsg("FAILURE: exception threw at " + location + ":\n" + ex); + finishTest(); + } + + if (performed) { + postMsg("perf"); + } + + return; + } + + postMsg("Invalid message"); +} + +function ok(a, message) { + if (!a) { + postMsg("FAILURE: " + message); + } else { + postMsg(message); + } +} + +function is(a, b, message) { + if (a != b) { + postMsg("FAILURE: " + message + ", expected " + b + " got " + a); + } else { + postMsg(message + ", expected " + b + " got " + a); + } +} + +function todo(a, b, message) { + postMsg("TODO: " + message + ", expected " + b + " got " + a); +} + +function finishTest() { + try { + localStorage.clear(); + } catch (e) {} + postMsg("done"); + return false; +} diff --git a/dom/tests/mochitest/localstorage/interOriginTest.js b/dom/tests/mochitest/localstorage/interOriginTest.js new file mode 100644 index 0000000000..526b5b0fb1 --- /dev/null +++ b/dom/tests/mochitest/localstorage/interOriginTest.js @@ -0,0 +1,41 @@ +var slaveLoadsPending = 1; + +var slaveOrigin = ""; +var slave = null; + +var failureRegExp = new RegExp("^FAILURE"); +const slavePath = "/tests/dom/tests/mochitest/localstorage/"; + +window.addEventListener("message", onMessageReceived); + +function onMessageReceived(event) { + switch (event.data) { + // Indication of the frame onload event + case "frame loaded": + if (--slaveLoadsPending) { + break; + } + + // Indication of successfully finished step of a test + // fall through + case "perf": + if (event.data == "perf") { + doStep(); + } + + slave.postMessage("step", slaveOrigin); + break; + + // Indication of all test parts finish (from any of the frames) + case "done": + localStorage.clear(); + slaveLoadsPending = 1; + doNextTest(); + break; + + // Any other message indicates error or succes message of a test + default: + SimpleTest.ok(!event.data.match(failureRegExp), event.data); + break; + } +} diff --git a/dom/tests/mochitest/localstorage/interOriginTest2.js b/dom/tests/mochitest/localstorage/interOriginTest2.js new file mode 100644 index 0000000000..ca64cbde22 --- /dev/null +++ b/dom/tests/mochitest/localstorage/interOriginTest2.js @@ -0,0 +1,53 @@ +var t = async_test(document.title); + +var frameLoadsPending = 2; + +var callMasterFrame = true; +var testDone = false; + +var masterFrameOrigin = ""; +var slaveFrameOrigin = ""; + +var failureRegExp = new RegExp("^FAILURE"); + +const framePath = "/tests/dom/tests/mochitest/localstorage/"; + +window.addEventListener("message", onMessageReceived); + +function onMessageReceived(event) { + switch (event.data) { + // Indication of the frame onload event + case "frame loaded": + if (--frameLoadsPending) { + break; + } + + // Indication of successfully finished step of a test + // Just fall through... + case "perf": + if (callMasterFrame) { + masterFrame.postMessage("step", masterFrameOrigin); + } else { + slaveFrame.postMessage("step", slaveFrameOrigin); + } + callMasterFrame = !callMasterFrame; + break; + + // Indication of all test parts finish (from any of the frames) + case "done": + if (testDone) { + break; + } + + testDone = true; + t.done(); + break; + + // Any other message indicates error, succes or todo message of a test + default: + t.step(function() { + assert_true(!event.data.match(failureRegExp), event.data); + }); + break; + } +} diff --git a/dom/tests/mochitest/localstorage/localStorageCommon.js b/dom/tests/mochitest/localstorage/localStorageCommon.js new file mode 100644 index 0000000000..ebe7f64fdd --- /dev/null +++ b/dom/tests/mochitest/localstorage/localStorageCommon.js @@ -0,0 +1,131 @@ +function localStorageFlush(cb) { + if (SpecialPowers.Services.domStorageManager.nextGenLocalStorageEnabled) { + SimpleTest.executeSoon(function() { + cb(); + }); + return; + } + + var ob = { + observe(sub, top, dat) { + os().removeObserver(ob, "domstorage-test-flushed"); + cb(); + }, + }; + os().addObserver(ob, "domstorage-test-flushed"); + notify("domstorage-test-flush-force"); +} + +function localStorageReload(callback) { + if (SpecialPowers.Services.domStorageManager.nextGenLocalStorageEnabled) { + localStorage.close(); + let qms = SpecialPowers.Services.qms; + let principal = SpecialPowers.wrap(document).nodePrincipal; + let request = qms.resetStoragesForPrincipal(principal, "default", "ls"); + request.callback = SpecialPowers.wrapCallback(function() { + localStorage.open(); + callback(); + }); + return; + } + + notify("domstorage-test-reload"); + SimpleTest.executeSoon(function() { + callback(); + }); +} + +function localStorageFlushAndReload(callback) { + if (SpecialPowers.Services.domStorageManager.nextGenLocalStorageEnabled) { + localStorage.close(); + let qms = SpecialPowers.Services.qms; + let principal = SpecialPowers.wrap(document).nodePrincipal; + let request = qms.resetStoragesForPrincipal(principal, "default", "ls"); + request.callback = SpecialPowers.wrapCallback(function() { + localStorage.open(); + callback(); + }); + return; + } + + localStorageFlush(function() { + localStorageReload(callback); + }); +} + +function localStorageClearAll(callback) { + if (SpecialPowers.Services.domStorageManager.nextGenLocalStorageEnabled) { + let qms = SpecialPowers.Services.qms; + let ssm = SpecialPowers.Services.scriptSecurityManager; + + qms.getUsage( + SpecialPowers.wrapCallback(function(request) { + if (request.resultCode != SpecialPowers.Cr.NS_OK) { + callback(); + return; + } + + let clearRequestCount = 0; + for (let item of request.result) { + let principal = ssm.createContentPrincipalFromOrigin(item.origin); + let clearRequest = qms.clearStoragesForPrincipal( + principal, + "default", + "ls" + ); + clearRequestCount++; + clearRequest.callback = SpecialPowers.wrapCallback(function() { + if (--clearRequestCount == 0) { + callback(); + } + }); + } + }) + ); + return; + } + + os().notifyObservers(null, "cookie-changed", "cleared"); + SimpleTest.executeSoon(function() { + callback(); + }); +} + +function localStorageClearDomain(domain, callback) { + if (SpecialPowers.Services.domStorageManager.nextGenLocalStorageEnabled) { + let qms = SpecialPowers.Services.qms; + let principal = SpecialPowers.wrap(document).nodePrincipal; + let request = qms.clearStoragesForPrincipal(principal, "default", "ls"); + let cb = SpecialPowers.wrapCallback(callback); + request.callback = cb; + return; + } + + os().notifyObservers(null, "extension:purge-localStorage", domain); + SimpleTest.executeSoon(function() { + callback(); + }); +} + +function os() { + return SpecialPowers.Services.obs; +} + +function notify(top) { + os().notifyObservers(null, top); +} + +/** + * Enable testing observer notifications in DOMStorageObserver.cpp. + */ +function localStorageEnableTestingMode(cb) { + SpecialPowers.pushPrefEnv( + { + set: [ + ["dom.storage.testing", true], + ["dom.quotaManager.testing", true], + ], + }, + cb + ); +} diff --git a/dom/tests/mochitest/localstorage/mochitest.ini b/dom/tests/mochitest/localstorage/mochitest.ini new file mode 100644 index 0000000000..02fc3b671e --- /dev/null +++ b/dom/tests/mochitest/localstorage/mochitest.ini @@ -0,0 +1,47 @@ +[DEFAULT] +support-files = + frameChromeSlave.html + frameLocalStorageCookieSettings.html + frameKeySync.html + frameMasterEqual.html + frameMasterNotEqual.html + frameOrder.html + frameQuota.html + frameQuotaSessionOnly.html + frameReplace.html + frameSlaveEqual.html + frameSlaveNotEqual.html + interOriginFrame.js + interOriginTest.js + interOriginTest2.js + localStorageCommon.js + frameLocalStorageSessionOnly.html + file_tryAccessSessionStorage.html + windowProxy.html + +[test_brokenUTF-16.html] +[test_bug600307-DBOps.html] +[test_bug746272-1.html] +[test_bug746272-2.html] +skip-if = verify +[test_cookieBlock.html] +[test_embededNulls.html] +[test_keySync.html] +[test_localStorageBase.html] +skip-if = e10s +[test_localStorageBaseSessionOnly.html] +[test_localStorageCookieSettings.html] +[test_localStorageEnablePref.html] +[test_localStorageKeyOrder.html] +[test_localStorageOriginsDiff.html] +[test_localStorageOriginsDomainDiffs.html] +[test_localStorageOriginsEquals.html] +[test_localStorageOriginsPortDiffs.html] +[test_localStorageOriginsSchemaDiffs.html] +[test_localStorageQuota.html] +[test_localStorageQuotaSessionOnly.html] +skip-if = true # bug 1611317 +[test_localStorageQuotaSessionOnly2.html] +skip-if = true # bug 1347690 +[test_localStorageReplace.html] +[test_storageConstructor.html] diff --git a/dom/tests/mochitest/localstorage/page_blank.html b/dom/tests/mochitest/localstorage/page_blank.html new file mode 100644 index 0000000000..157317d64b --- /dev/null +++ b/dom/tests/mochitest/localstorage/page_blank.html @@ -0,0 +1,6 @@ +<!DOCTYPE html> +<html> +<body> + +</body> +</html> diff --git a/dom/tests/mochitest/localstorage/test_brokenUTF-16.html b/dom/tests/mochitest/localstorage/test_brokenUTF-16.html new file mode 100644 index 0000000000..a9289b195c --- /dev/null +++ b/dom/tests/mochitest/localstorage/test_brokenUTF-16.html @@ -0,0 +1,100 @@ +<html xmlns="http://www.w3.org/1999/xhtml"> +<head> +<title>incomplete UTF-16 test</title> +<meta http-equiv="Content-type" content="text/html; charset=UTF-8" /> + +<script src="/tests/SimpleTest/SimpleTest.js"></script> +<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> + +<script type="text/javascript"> + +function startTest() +{ + // Check this works for a diacritics + var k = "valid UTF-16 key"; + var v = "ěščřžýáíéúůĚŠČŘŽÝÁÍÉÚŮ"; + + localStorage.setItem(k, v); + is(localStorage.getItem(k), v, "UTF-16 value results from getItem"); + + localStorage.setItem(v, "a value"); + is(localStorage.getItem(v), "a value", "value result using UTF-16 key from getItem"); + + localStorage.clear(); + + localStorage[k] = v; + is(localStorage[k], v, "UTF-16 value results from []"); + + localStorage[v] = "a value"; + is(localStorage[v], "a value", "value result using UTF-16 key from []"); + + localStorage.clear(); + + localStorage.aKey = v; + is(localStorage.aKey, v, "UTF-16 value results from a dynamic property"); + + localStorage.clear(); + + // Broken UTF-16 + k = "broken UTF-16 key"; + v = "\uD800"; // broken UTF-16 + + localStorage.setItem(k, v); + is(localStorage.getItem(k), v, "broken value results from getItem"); + + localStorage.setItem(v, "a value"); + is(localStorage.getItem(v), "a value", "value result using broken key from getItem"); + + localStorage.clear(); + + localStorage[k] = v; + is(localStorage[k], v, "broken value results from []"); + + localStorage[v] = "a value"; + is(localStorage[v], "a value", "value result using broken key from []"); + + localStorage.clear(); + + localStorage.aKey = v; + is(localStorage.aKey, v, "broken value results from a dynamic property"); + + localStorage.clear(); + + // Another variant + v = "FcK" + + String.fromCharCode(0x8a) + + ".jp"; + + localStorage.setItem(k, v); + is(localStorage.getItem(k), v); + + localStorage.setItem(v, "a value"); + is(localStorage.getItem(v), "a value"); + + localStorage.clear(); + + // And yet another variant + v = "something" + + String.fromCharCode(355, 277, 349, 357, 533, 537, 101, 345); + + localStorage.setItem(k, v); + is(localStorage.getItem(k), v); + + localStorage.setItem(v, "a value"); + is(localStorage.getItem(v), "a value"); + + localStorage.clear(); + + SimpleTest.finish(); +} + +SimpleTest.waitForExplicitFinish(); + +</script> + +</head> + +<body onload="startTest();"> + +</body> +</html> diff --git a/dom/tests/mochitest/localstorage/test_bug600307-DBOps.html b/dom/tests/mochitest/localstorage/test_bug600307-DBOps.html new file mode 100644 index 0000000000..cfce270d5d --- /dev/null +++ b/dom/tests/mochitest/localstorage/test_bug600307-DBOps.html @@ -0,0 +1,178 @@ +<html xmlns="http://www.w3.org/1999/xhtml"> +<head> +<title>bug 600307</title> + +<script src="/tests/SimpleTest/SimpleTest.js"></script> +<script type="text/javascript" src="localStorageCommon.js"></script> +<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> + +<script type="text/javascript"> + +/* eslint-disable max-nested-callbacks */ + +/* +This is strictly implementation specific test for dom storage code from bug 600307. +It exercises code for asynchronous data flushing with regard to cache life time and its preload. + +"flush + reload" means to tell the database to store all pending data then wipe the cached content and reload it from the db + +"reload" only means to simulate situation when there is a pending flush for an origin but a new cache is about to preload +which is a corner case happening rarely ; this helps check the next preload operation will load correct data from the database anyway + +Case 1: set | flush + reload | remove | set | remove | flush + reload | get ?= null + checks coalescing optimization for single key changes does work correctly for repeated removals of a key + +Case 2: set | set | clear | flush + reload | count ?= 0 + checks whether clear operation superseeds setting keys, the database must be empty for the origin + +Case 3: set | set | clear | reload | count ?= 0 + check the corner case when a data clear flush is pending but a new cache is about to preload +*/ + +function startTest() +{ + // Enable testing observer notifications + localStorageEnableTestingMode(function() { + + // Have an untouched land + localStorage.clear(); + + // Initial flush + localStorageFlush(function() { + is(localStorage.length, 0, "localStorage empty at the test start"); + + // Basic test 1 (set a key, check presence after reload): + localStorage.setItem("item", "value"); + localStorageFlushAndReload(function() { + is(localStorage.getItem("item"), "value", "Basic persistance works"); + is(localStorage.length, 1, "1 item in localStorage"); + + // Basic test 2 (set a key twice, check presence of the last value): + localStorage.setItem("item", "value2"); + localStorage.setItem("item", "value3"); + localStorageFlushAndReload(function() { + is(localStorage.getItem("item"), "value3", "Basic persistance 2 works"); + + // Basic test 3 (remove a key, check it has been deleted): + localStorage.removeItem("item"); + localStorageFlushAndReload(function() { + is(localStorage.getItem("item"), null, "Basic delete works"); + + // Basic test 4 (set and remove a key, check it is not present): + localStorage.setItem("item", "value4"); + localStorage.removeItem("item"); + localStorageFlushAndReload(function() { + is(localStorage.getItem("item"), null, "Basic delete 2 works"); + + + // Case 1: + localStorage.setItem("item", "value"); + localStorageFlushAndReload(function() { + localStorage.removeItem("item"); + localStorage.setItem("item", "value2"); + localStorage.removeItem("item"); + localStorageFlushAndReload(function() { + is(localStorage.getItem("item"), null, "Item deleted in case 1"); + + // Case 2: + localStorage.setItem("item", "value"); + localStorage.setItem("item2", "value2"); + localStorage.clear(); + localStorageFlushAndReload(function() { + is(localStorage.length, 0, "localStorage clean in case 2"); + + // Case 3: + localStorageFlush(function() { + localStorage.setItem("item", "value"); + localStorage.setItem("item2", "value2"); + localStorage.clear(); + localStorageReload(function() { + is(localStorage.length, 0, "localStorage clean in case 4"); + + if (!SpecialPowers.Services.domStorageManager.nextGenLocalStorageEnabled && + SpecialPowers.Cc["@mozilla.org/xre/app-info;1"].getService( + SpecialPowers.Ci.nsIXULRuntime).processType != SpecialPowers.Ci.nsIXULRuntime.PROCESS_TYPE_DEFAULT) { + // Following tests cannot be run in a child/plugin process type + SimpleTest.finish(); + return; + } + + // Cookies clean 1 + localStorageFlush(function() { + localStorage.setItem("item", "value"); + localStorageClearAll(function() { + is(localStorage.length, 0, "localStorage clean after cookies deletion"); + localStorage.setItem("item2", "value2"); + is(localStorage.getItem("item"), null, "Unexpected key 1, cookies delete"); + is(localStorage.getItem("item2"), "value2", "Expected key 2, cookies delete"); + localStorageFlushAndReload(function() { + is(localStorage.getItem("item"), null, "Unexpected key 1, cookies delete"); + is(localStorage.getItem("item2"), "value2", "Expected key 2, cookies delete"); + + // Cookies clean 2 + localStorage.clear(); + localStorageFlush(function() { + localStorage.setItem("item", "value"); + localStorageClearAll(function() { + is(localStorage.length, 0, "localStorage clean after cookies deletion 2"); + localStorageFlushAndReload(function() { + is(localStorage.length, 0, "localStorage clean after cookies deletion 2"); + + + // Domain clean 1 + localStorageFlush(function() { + localStorage.setItem("item", "value"); + localStorageClearDomain("test", function() { + is(localStorage.length, 0, "localStorage clean after domain deletion"); + localStorage.setItem("item2", "value2"); + is(localStorage.getItem("item"), null, "Unexpected key 1, domain delete"); + is(localStorage.getItem("item2"), "value2", "Expected key 2, domain delete"); + localStorageFlushAndReload(function() { + is(localStorage.getItem("item"), null, "Unexpected key 1, domain delete"); + is(localStorage.getItem("item2"), "value2", "Expected key 2, domain delete"); + + // Domain clean 2 + localStorage.clear(); + localStorageFlush(function() { + localStorage.setItem("item", "value"); + localStorageClearDomain("test", function() { + is(localStorage.length, 0, "localStorage clean after domain deletion 2"); + localStorageFlushAndReload(function() { + is(localStorage.length, 0, "localStorage clean after domain deletion 2"); + + SimpleTest.finish(); + + }); + }); + }); + }); + }); + }); + }); + }); + }); + }); + }); + }); + }); + }); + }); + }); + }); + }); + }); + }); + }); + }); + }); +} + +SimpleTest.waitForExplicitFinish(); + +</script> + +</head> + +<body onload="startTest();"> +</body> +</html> diff --git a/dom/tests/mochitest/localstorage/test_bug746272-1.html b/dom/tests/mochitest/localstorage/test_bug746272-1.html new file mode 100644 index 0000000000..36612fe79f --- /dev/null +++ b/dom/tests/mochitest/localstorage/test_bug746272-1.html @@ -0,0 +1,32 @@ +<html xmlns="http://www.w3.org/1999/xhtml"> +<head> +<title>incomplete UTF-16 test</title> +<meta http-equiv="Content-type" content="text/html; charset=UTF-8" /> + +<script src="/tests/SimpleTest/SimpleTest.js"></script> +<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> + +<script type="text/javascript"> + +function startTest() +{ + localStorage.clear(); + localStorage.setItem("test1", "value1"); + localStorage.setItem("test2", "value2"); + localStorage.setItem("test3", "value3"); + + is(localStorage.length, 3, "expected number of items"); + + SimpleTest.finish(); +} + +SimpleTest.waitForExplicitFinish(); + +</script> + +</head> + +<body onload="startTest();"> + +</body> +</html> diff --git a/dom/tests/mochitest/localstorage/test_bug746272-2.html b/dom/tests/mochitest/localstorage/test_bug746272-2.html new file mode 100644 index 0000000000..31edbc906a --- /dev/null +++ b/dom/tests/mochitest/localstorage/test_bug746272-2.html @@ -0,0 +1,31 @@ +<html xmlns="http://www.w3.org/1999/xhtml"> +<head> +<title>incomplete UTF-16 test</title> +<meta http-equiv="Content-type" content="text/html; charset=UTF-8" /> + +<script src="/tests/SimpleTest/SimpleTest.js"></script> +<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> + +<script type="text/javascript"> + +function startTest() +{ + var test2 = localStorage.getItem("test2"); + is(test2, "value2", "expected item"); + + localStorage.removeItem("test2"); + is(localStorage.length, 2, "expected number of items"); + + SimpleTest.finish(); +} + +SimpleTest.waitForExplicitFinish(); + +</script> + +</head> + +<body onload="startTest();"> + +</body> +</html> diff --git a/dom/tests/mochitest/localstorage/test_cookieBlock.html b/dom/tests/mochitest/localstorage/test_cookieBlock.html new file mode 100644 index 0000000000..9cc7495d40 --- /dev/null +++ b/dom/tests/mochitest/localstorage/test_cookieBlock.html @@ -0,0 +1,53 @@ +<html xmlns="http://www.w3.org/1999/xhtml"> +<head> +<title>cookie blocking test</title> + +<script src="/tests/SimpleTest/SimpleTest.js"></script> +<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> + +<script type="text/javascript"> + +function startTest() +{ + // Let's use a new window to have the cookie permission applied. + let w = window.open("windowProxy.html"); + w.onload = _ => { + try { + w.localStorage.setItem("blocked", "blockedvalue"); + ok(false, "Exception for localStorage.setItem, ACCESS_DENY"); + } + catch (ex) { + ok(true, "Exception for localStorage.setItem, ACCESS_DENY"); + } + + try { + w.localStorage.getItem("blocked"); + ok(false, "Exception for localStorage.getItem, ACCESS_DENY"); + } + catch (ex) { + ok(true, "Exception for localStorage.getItem, ACCESS_DENY"); + } + + w.close(); + SpecialPowers.popPermissions(() => { + SimpleTest.finish(); + }); + } +} + +SimpleTest.waitForExplicitFinish(); + +// Initialize storage before setting the cookie, otherwise we won't be testing +// the checks in setItem/getItem methods. +var storage = localStorage; + +SpecialPowers.pushPermissions([{'type': 'cookie', 'allow': false, 'context': document}], startTest); + +</script> + +</head> + +<body> + +</body> +</html> diff --git a/dom/tests/mochitest/localstorage/test_embededNulls.html b/dom/tests/mochitest/localstorage/test_embededNulls.html new file mode 100644 index 0000000000..b12a403b85 --- /dev/null +++ b/dom/tests/mochitest/localstorage/test_embededNulls.html @@ -0,0 +1,40 @@ +<html xmlns="http://www.w3.org/1999/xhtml"> +<head> +<title>embeded nulls test</title> + +<script src="/tests/SimpleTest/SimpleTest.js"></script> +<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> + +<script type="text/javascript"> + +function startTest() +{ + var k = "key with\x00null"; + var v = "value with\x00null"; + + localStorage.setItem(k, v); + + is(localStorage.getItem("key with"), null, + "not accessible by truncated key"); + + is(localStorage.getItem(k), "value with\x00null", + "value is identical to what has been stored"); + + isnot(localStorage.getItem(k), "value with", + "value is not truncated"); + + localStorage.clear(); + + SimpleTest.finish(); +} + +SimpleTest.waitForExplicitFinish(); + +</script> + +</head> + +<body onload="startTest();"> + +</body> +</html> diff --git a/dom/tests/mochitest/localstorage/test_keySync.html b/dom/tests/mochitest/localstorage/test_keySync.html new file mode 100644 index 0000000000..3f23945e2f --- /dev/null +++ b/dom/tests/mochitest/localstorage/test_keySync.html @@ -0,0 +1,33 @@ +<html xmlns="http://www.w3.org/1999/xhtml"> +<head> +<title>localStorage equal origins</title> + +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="interOriginTest2.js"></script> + +<!-- + This test loads two frames from the same origin, clears in one frame, + sets a single key in another and then checks key(0) in the first frame. +--> + +<script type="text/javascript"> + +function startTest() +{ + masterFrameOrigin = "http://example.org:80"; + slaveFrameOrigin = "http://example.org:80"; + + masterFrame.location = masterFrameOrigin + framePath + "frameKeySync.html?1"; + slaveFrame.location = slaveFrameOrigin + framePath + "frameKeySync.html?2"; +} + +</script> + +</head> + +<body onload="startTest();"> + <iframe src="" name="masterFrame"></iframe> + <iframe src="" name="slaveFrame"></iframe> +</body> +</html> diff --git a/dom/tests/mochitest/localstorage/test_localStorageBase.html b/dom/tests/mochitest/localstorage/test_localStorageBase.html new file mode 100644 index 0000000000..7c243452a4 --- /dev/null +++ b/dom/tests/mochitest/localstorage/test_localStorageBase.html @@ -0,0 +1,247 @@ +<html xmlns="http://www.w3.org/1999/xhtml"> +<head> +<title>localStorage basic test</title> + +<script src="/tests/SimpleTest/SimpleTest.js"></script> +<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> + +<script type="text/javascript"> + +var expectedEvents = [ + "empty,null,", + "empty,,null", + "key1,null,value1", + "key1,value1,null", + "key1,null,value1", + "key2,null,value2", + "key2,value2,value2-2", + "key1,value1,value1-2", + "key2,value2-2,null", + "testA,null,valueA", + "testA,valueA,valueA2", + "testB,null,valueB", + "testB,valueB,valueB2", + "testC,null,valueC", + "testC,valueC,valueC2", + "testC,valueC2,null", + "testC,null,null", + "testC,null,null", + "null,null,test", + "null,test,null", + "null,null,test", + "null,test,null", + "null,null,null" +]; + +function startTest() +{ + // Initially check the localStorage is empty + is(localStorage.length, 0, "The storage is empty [1]"); + is(localStorage.key(0), null, "key() should return null for out-of-bounds access"); + is(localStorage.key(-1), null, "key() should return null for out-of-bounds access"); + is(localStorage.key(1), null, "key() should return null for out-of-bounds access"); + is(localStorage.getItem("nonexisting"), null, "Nonexisting item is null (getItem())"); + is(localStorage.nonexisting, undefined, "Nonexisting item is undefined (array access)"); + is(localStorage.nonexisting, undefined, "Nonexisting item is undefined (property access)"); + localStorage.removeItem("nonexisting"); // Just check there is no exception + + is(typeof localStorage.getItem("nonexisting"), "object", "getItem('nonexisting') is object"); + is(typeof localStorage.nonexisting, "undefined", "['nonexisting'] is undefined"); + is(typeof localStorage.nonexisting, "undefined", "nonexisting is undefined"); + is(typeof localStorage.getItem("nonexisting2"), "object", "getItem('nonexisting2') is object"); + is(typeof localStorage.nonexisting2, "undefined", "['nonexisting2'] is undefined"); + is(typeof localStorage.nonexisting2, "undefined", "nonexisting2 is undefined"); + + var localStorageCopy = localStorage; + + function onStorageChanged(e) { + if (e.storageArea == localStorageCopy) { + ok(expectedEvents.length > 0, "Not more then expected events encountered"); + var receivedEvent = e.key + "," + e.oldValue + "," + e.newValue; + is(receivedEvent, expectedEvents.shift(), "Expected event data: " + receivedEvent); + } + } + + // Listen for MozLocalStorageChanged + SpecialPowers.addChromeEventListener("MozLocalStorageChanged", onStorageChanged, true); + + // add an empty-value key + localStorage.setItem("empty", ""); + is(localStorage.getItem("empty"), "", "Empty value (getItem())"); + is(localStorage.empty, "", "Empty value (array access)"); + is(localStorage.empty, "", "Empty value (property access)"); + is(typeof localStorage.getItem("empty"), "string", "getItem('empty') is string"); + is(typeof localStorage.empty, "string", "['empty'] is string"); + is(typeof localStorage.empty, "string", "empty is string"); + localStorage.removeItem("empty"); + is(localStorage.length, 0, "The storage has no keys"); + is(localStorage.getItem("empty"), null, "empty item is null (getItem())"); + is(localStorage.empty, undefined, "empty item is undefined (array access)"); + is(localStorage.empty, undefined, "empty item is undefined (property access)"); + is(typeof localStorage.getItem("empty"), "object", "getItem('empty') is object"); + is(typeof localStorage.empty, "undefined", "['empty'] is undefined"); + is(typeof localStorage.empty, "undefined", "empty is undefined"); + + // add one key, check it is there + localStorage.setItem("key1", "value1"); + is(localStorage.length, 1, "The storage has one key-value pair"); + is(localStorage.key(0), "key1"); + is(localStorage.key(-1), null, "key() should return null for out-of-bounds access"); + is(localStorage.key(1), null, "key() should return null for out-of-bounds access"); + + // check all access method give the correct result + // and are of the correct type + is(localStorage.getItem("key1"), "value1", "getItem('key1') == value1"); + is(localStorage.key1, "value1", "['key1'] == value1"); + is(localStorage.key1, "value1", "key1 == value1"); + + is(typeof localStorage.getItem("key1"), "string", "getItem('key1') is string"); + is(typeof localStorage.key1, "string", "['key1'] is string"); + is(typeof localStorage.key1, "string", "key1 is string"); + + // remove the previously added key and check the storage is empty + localStorage.removeItem("key1"); + is(localStorage.length, 0, "The storage is empty [2]"); + is(localStorage.key(0), null, "key() should return null for out-of-bounds access"); + is(localStorage.getItem("key1"), null, "\'key1\' removed"); + + is(typeof localStorage.getItem("key1"), "object", "getItem('key1') is object"); + is(typeof localStorage.key1, "undefined", "['key1'] is object"); + is(typeof localStorage.key1, "undefined", "key1 is object"); + + // add one key, check it is there + localStorage.setItem("key1", "value1"); + is(localStorage.length, 1, "The storage has one key-value pair"); + is(localStorage.key(0), "key1"); + is(localStorage.getItem("key1"), "value1"); + + // add a second key + localStorage.setItem("key2", "value2"); + is(localStorage.length, 2, "The storage has two key-value pairs"); + is(localStorage.getItem("key1"), "value1"); + is(localStorage.getItem("key2"), "value2"); + var firstKey = localStorage.key(0); + var secondKey = localStorage.key(1); + ok((firstKey == 'key1' && secondKey == 'key2') || + (firstKey == 'key2' && secondKey == 'key1'), + 'key() API works.'); + + // change the second key + localStorage.setItem("key2", "value2-2"); + is(localStorage.length, 2, "The storage has two key-value pairs"); + is(localStorage.key(0), firstKey); // After key value changes the order must be preserved + is(localStorage.key(1), secondKey); + is(localStorage.key(-1), null, "key() should return null for out-of-bounds access"); + is(localStorage.key(2), null, "key() should return null for out-of-bounds access"); + is(localStorage.getItem("key1"), "value1"); + is(localStorage.getItem("key2"), "value2-2"); + + // change the first key + localStorage.setItem("key1", "value1-2"); + is(localStorage.length, 2, "The storage has two key-value pairs"); + is(localStorage.key(0), firstKey); // After key value changes the order must be preserved + is(localStorage.key(1), secondKey); + is(localStorage.key(-1), null, "key() should return null for out-of-bounds access"); + is(localStorage.key(2), null, "key() should return null for out-of-bounds access"); + is(localStorage.getItem("key1"), "value1-2"); + is(localStorage.getItem("key2"), "value2-2"); + + // remove the second key + localStorage.removeItem("key2"); + is(localStorage.length, 1, "The storage has one key-value pair"); + is(localStorage.key(0), "key1"); + is(localStorage.key(-1), null, "key() should return null for out-of-bounds access"); + is(localStorage.key(1), null, "key() should return null for out-of-bounds access"); + is(localStorage.getItem("key1"), "value1-2"); + + // JS property test + localStorage.testA = "valueA"; + is(localStorage.testA, "valueA"); + is(localStorage.testA, "valueA"); + is(localStorage.getItem("testA"), "valueA"); + + localStorage.testA = "valueA2"; + is(localStorage.testA, "valueA2"); + is(localStorage.testA, "valueA2"); + is(localStorage.getItem("testA"), "valueA2"); + + localStorage.testB = "valueB"; + is(localStorage.testB, "valueB"); + is(localStorage.testB, "valueB"); + is(localStorage.getItem("testB"), "valueB"); + + localStorage.testB = "valueB2"; + is(localStorage.testB, "valueB2"); + is(localStorage.testB, "valueB2"); + is(localStorage.getItem("testB"), "valueB2"); + + localStorage.setItem("testC", "valueC"); + is(localStorage.testC, "valueC"); + is(localStorage.testC, "valueC"); + is(localStorage.getItem("testC"), "valueC"); + + localStorage.setItem("testC", "valueC2"); + is(localStorage.testC, "valueC2"); + is(localStorage.testC, "valueC2"); + is(localStorage.getItem("testC"), "valueC2"); + + localStorage.setItem("testC", null); + is("testC" in localStorage, true); + is(localStorage.getItem("testC"), "null"); + is(localStorage.testC, "null"); + is(localStorage.testC, "null"); + + localStorage.removeItem("testC"); + localStorage.testC = null; + is("testC" in localStorage, true); + is(localStorage.getItem("testC"), "null"); + is(localStorage.testC, "null"); + is(localStorage.testC, "null"); + + localStorage.setItem(null, "test"); + is("null" in localStorage, true); + is(localStorage.getItem("null"), "test"); + is(localStorage.getItem(null), "test"); + is(localStorage.null, "test"); + localStorage.removeItem(null, "test"); + is("null" in localStorage, false); + + localStorage.setItem(null, "test"); + is("null" in localStorage, true); + localStorage.removeItem("null", "test"); + is("null" in localStorage, false); + + // Clear the storage + localStorage.clear(); + is("testB" in localStorage, false, "Keys are not in the JS scope of the storage"); + is("testC" in localStorage, false, "Keys are not in the JS scope of the storage"); + is(localStorage.length, 0, "The storage is empty [3]"); + is(localStorage.key(0), null, "key() should return null for out-of-bounds access"); + is(localStorage.key(-1), null, "key() should return null for out-of-bounds access"); + is(localStorage.key(1), null, "key() should return null for out-of-bounds access"); + is(localStorage.getItem("nonexisting"), null, "Nonexisting item is null"); + is(localStorage.getItem("key1"), null, "key1 removed"); + is(localStorage.getItem("key2"), null, "key2 removed"); + localStorage.removeItem("nonexisting"); // Just check there is no exception + localStorage.removeItem("key1"); // Just check there is no exception + localStorage.removeItem("key2"); // Just check there is no exception + + SimpleTest.executeSoon(function () { + SpecialPowers.removeChromeEventListener("MozLocalStorageChanged", onStorageChanged, true); + is(expectedEvents.length, 0, "received the correct number of events"); + + localStorage.clear(); + SimpleTest.finish(); + }); +} + +SimpleTest.waitForExplicitFinish(); + +</script> + +</head> + +<body onload="startTest();"> + +</body> +</html> diff --git a/dom/tests/mochitest/localstorage/test_localStorageBasePrivateBrowsing_perwindowpb.html b/dom/tests/mochitest/localstorage/test_localStorageBasePrivateBrowsing_perwindowpb.html new file mode 100644 index 0000000000..ada3c2a6ab --- /dev/null +++ b/dom/tests/mochitest/localstorage/test_localStorageBasePrivateBrowsing_perwindowpb.html @@ -0,0 +1,256 @@ +<html xmlns="http://www.w3.org/1999/xhtml"> +<head> +<title>localStorage basic test, while in sesison only mode</title> + +<script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script> +<link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"?> + +<script type="text/javascript"> + +var mainWindow; + +var prefBranch = Cc["@mozilla.org/preferences-service;1"] + .getService(Ci.nsIPrefBranch); +prefBranch.setIntPref("browser.startup.page", 0); +prefBranch.setCharPref("browser.startup.homepage_override.mstone", "ignore"); + +function startTest() { + mainWindow = window.browsingContext.topChromeWindow; + + doTest(); +} + +var contentPage = "http://mochi.test:8888/chrome/dom/tests/mochitest/localstorage/page_blank.html"; + +function testOnWindow(aIsPrivate, aCallback) { + var win = mainWindow.OpenBrowserWindow({private: aIsPrivate}); + win.addEventListener("load", function() { + win.addEventListener("DOMContentLoaded", function onInnerLoad() { + if (win.content.location.href == "about:privatebrowsing") { + win.gBrowser.loadURI(contentPage); + return; + } + win.removeEventListener("DOMContentLoaded", onInnerLoad, true); + SimpleTest.executeSoon(function() { aCallback(win); }); + }, true); + win.gBrowser.loadURI(contentPage); + }, {capture: true, once: true}); +} + +function doTest() { + testOnWindow(false, function(aWin) { + aWin.content.localStorage.setItem("persistent", "persistent1"); + + testOnWindow(true, function(privateWin) { + is(privateWin.content.localStorage.getItem("persistent"), null, "previous values are inaccessible"); + + // Initially check the privateWin.content.localStorage is empty + is(privateWin.content.localStorage.length, 0, "The storage is empty [1]"); + is(privateWin.content.localStorage.key(0), null, "key() should return null for out-of-bounds access"); + is(privateWin.content.localStorage.key(-1), null, "key() should return null for out-of-bounds access"); + is(privateWin.content.localStorage.key(1), null, "key() should return null for out-of-bounds access"); + is(privateWin.content.localStorage.getItem("nonexisting"), null, "Nonexisting item is null (getItem())"); + is(privateWin.content.localStorage.nonexisting, undefined, "Nonexisting item is null (array access)"); + is(privateWin.content.localStorage.nonexisting, undefined, "Nonexisting item is null (property access)"); + privateWin.content.localStorage.removeItem("nonexisting"); // Just check there is no exception + + is(typeof privateWin.content.localStorage.getItem("nonexisting"), "object", "getItem('nonexisting') is object"); + is(typeof privateWin.content.localStorage.nonexisting, "undefined", "['nonexisting'] is undefined"); + is(typeof privateWin.content.localStorage.nonexisting, "undefined", "nonexisting is undefined"); + is(typeof privateWin.content.localStorage.getItem("nonexisting2"), "object", "getItem('nonexisting2') is object"); + is(typeof privateWin.content.localStorage.nonexisting2, "undefined", "['nonexisting2'] is undefined"); + is(typeof privateWin.content.localStorage.nonexisting2, "undefined", "nonexisting2 is undefined"); + + // add an empty-value key + privateWin.content.localStorage.setItem("empty", ""); + is(privateWin.content.localStorage.getItem("empty"), "", "Empty value (getItem())"); + is(privateWin.content.localStorage.empty, "", "Empty value (array access)"); + is(privateWin.content.localStorage.empty, "", "Empty value (property access)"); + is(typeof privateWin.content.localStorage.getItem("empty"), "string", "getItem('empty') is string"); + is(typeof privateWin.content.localStorage.empty, "string", "['empty'] is string"); + is(typeof privateWin.content.localStorage.empty, "string", "empty is string"); + privateWin.content.localStorage.removeItem("empty"); + is(privateWin.content.localStorage.length, 0, "The storage has no keys"); + is(privateWin.content.localStorage.getItem("empty"), null, "empty item is null (getItem())"); + is(privateWin.content.localStorage.empty, undefined, "empty item is undefined (array access)"); + is(privateWin.content.localStorage.empty, undefined, "empty item is undefined (property access)"); + is(typeof privateWin.content.localStorage.getItem("empty"), "object", "getItem('empty') is object"); + is(typeof privateWin.content.localStorage.empty, "undefined", "['empty'] is undefined"); + is(typeof privateWin.content.localStorage.empty, "undefined", "empty is undefined"); + + // add one key, check it is there + privateWin.content.localStorage.setItem("key1", "value1"); + is(privateWin.content.localStorage.length, 1, "The storage has one key-value pair"); + is(privateWin.content.localStorage.key(0), "key1"); + is(privateWin.content.localStorage.key(-1), null, "key() should return null for out-of-bounds access"); + is(privateWin.content.localStorage.key(1), null, "key() should return null for out-of-bounds access"); + + // check all access method give the correct result + // and are of the correct type + is(privateWin.content.localStorage.getItem("key1"), "value1", "getItem('key1') == value1"); + is(privateWin.content.localStorage.key1, "value1", "['key1'] == value1"); + is(privateWin.content.localStorage.key1, "value1", "key1 == value1"); + + is(typeof privateWin.content.localStorage.getItem("key1"), "string", "getItem('key1') is string"); + is(typeof privateWin.content.localStorage.key1, "string", "['key1'] is string"); + is(typeof privateWin.content.localStorage.key1, "string", "key1 is string"); + + // remove the previously added key and check the storage is empty + privateWin.content.localStorage.removeItem("key1"); + is(privateWin.content.localStorage.length, 0, "The storage is empty [2]"); + is(privateWin.content.localStorage.key(0), null, "key() should return null for out-of-bounds access"); + is(privateWin.content.localStorage.getItem("key1"), null, "\'key1\' removed"); + + is(typeof privateWin.content.localStorage.getItem("key1"), "object", "getItem('key1') is object"); + is(typeof privateWin.content.localStorage.key1, "undefined", "['key1'] is undefined"); + is(typeof privateWin.content.localStorage.key1, "undefined", "key1 is undefined"); + + // add one key, check it is there + privateWin.content.localStorage.setItem("key1", "value1"); + is(privateWin.content.localStorage.length, 1, "The storage has one key-value pair"); + is(privateWin.content.localStorage.key(0), "key1"); + is(privateWin.content.localStorage.getItem("key1"), "value1"); + + // add a second key + privateWin.content.localStorage.setItem("key2", "value2"); + is(privateWin.content.localStorage.length, 2, "The storage has two key-value pairs"); + is(privateWin.content.localStorage.getItem("key1"), "value1"); + is(privateWin.content.localStorage.getItem("key2"), "value2"); + var firstKey = privateWin.content.localStorage.key(0); + var secondKey = privateWin.content.localStorage.key(1); + ok((firstKey == 'key1' && secondKey == 'key2') || + (firstKey == 'key2' && secondKey == 'key1'), + 'key() API works.'); + + // change the second key + privateWin.content.localStorage.setItem("key2", "value2-2"); + is(privateWin.content.localStorage.length, 2, "The storage has two key-value pairs"); + is(privateWin.content.localStorage.key(0), firstKey); // After key value changes the order must be preserved + is(privateWin.content.localStorage.key(1), secondKey); + is(privateWin.content.localStorage.key(-1), null, "key() should return null for out-of-bounds access"); + is(privateWin.content.localStorage.key(2), null, "key() should return null for out-of-bounds access"); + is(privateWin.content.localStorage.getItem("key1"), "value1"); + is(privateWin.content.localStorage.getItem("key2"), "value2-2"); + + // change the first key + privateWin.content.localStorage.setItem("key1", "value1-2"); + is(privateWin.content.localStorage.length, 2, "The storage has two key-value pairs"); + is(privateWin.content.localStorage.key(0), firstKey); // After key value changes the order must be preserved + is(privateWin.content.localStorage.key(1), secondKey); + is(privateWin.content.localStorage.key(-1), null, "key() should return null for out-of-bounds access"); + is(privateWin.content.localStorage.key(2), null, "key() should return null for out-of-bounds access"); + is(privateWin.content.localStorage.getItem("key1"), "value1-2"); + is(privateWin.content.localStorage.getItem("key2"), "value2-2"); + + // remove the second key + privateWin.content.localStorage.removeItem("key2"); + is(privateWin.content.localStorage.length, 1, "The storage has one key-value pair"); + is(privateWin.content.localStorage.key(0), "key1"); + is(privateWin.content.localStorage.key(-1), null, "key() should return null for out-of-bounds access"); + is(privateWin.content.localStorage.key(1), null, "key() should return null for out-of-bounds access"); + is(privateWin.content.localStorage.getItem("key1"), "value1-2"); + + // JS property test + privateWin.content.localStorage.testA = "valueA"; + is(privateWin.content.localStorage.testA, "valueA"); + is(privateWin.content.localStorage.testA, "valueA"); + is(privateWin.content.localStorage.getItem("testA"), "valueA"); + + privateWin.content.localStorage.testA = "valueA2"; + is(privateWin.content.localStorage.testA, "valueA2"); + is(privateWin.content.localStorage.testA, "valueA2"); + is(privateWin.content.localStorage.getItem("testA"), "valueA2"); + + privateWin.content.localStorage.testB = "valueB"; + is(privateWin.content.localStorage.testB, "valueB"); + is(privateWin.content.localStorage.testB, "valueB"); + is(privateWin.content.localStorage.getItem("testB"), "valueB"); + + privateWin.content.localStorage.testB = "valueB2"; + is(privateWin.content.localStorage.testB, "valueB2"); + is(privateWin.content.localStorage.testB, "valueB2"); + is(privateWin.content.localStorage.getItem("testB"), "valueB2"); + + privateWin.content.localStorage.setItem("testC", "valueC"); + is(privateWin.content.localStorage.testC, "valueC"); + is(privateWin.content.localStorage.testC, "valueC"); + is(privateWin.content.localStorage.getItem("testC"), "valueC"); + + privateWin.content.localStorage.setItem("testC", "valueC2"); + is(privateWin.content.localStorage.testC, "valueC2"); + is(privateWin.content.localStorage.testC, "valueC2"); + is(privateWin.content.localStorage.getItem("testC"), "valueC2"); + + privateWin.content.localStorage.setItem("testC", null); + is("testC" in privateWin.content.localStorage, true); + is(privateWin.content.localStorage.getItem("testC"), "null"); + is(privateWin.content.localStorage.testC, "null"); + is(privateWin.content.localStorage.testC, "null"); + + privateWin.content.localStorage.removeItem("testC"); + privateWin.content.localStorage.testC = null; + is("testC" in privateWin.content.localStorage, true); + is(privateWin.content.localStorage.getItem("testC"), "null"); + is(privateWin.content.localStorage.testC, "null"); + is(privateWin.content.localStorage.testC, "null"); + + privateWin.content.localStorage.setItem(null, "test"); + is("null" in privateWin.content.localStorage, true); + is(privateWin.content.localStorage.getItem("null"), "test"); + is(privateWin.content.localStorage.getItem(null), "test"); + is(privateWin.content.localStorage.null, "test"); + privateWin.content.localStorage.removeItem(null, "test"); + is("null" in privateWin.content.localStorage, false); + + privateWin.content.localStorage.setItem(null, "test"); + is("null" in privateWin.content.localStorage, true); + privateWin.content.localStorage.removeItem("null", "test"); + is("null" in privateWin.content.localStorage, false); + + // Clear the storage + privateWin.content.localStorage.clear(); + is(privateWin.content.localStorage.length, 0, "The storage is empty [3]"); + is(privateWin.content.localStorage.key(0), null, "key() should return null for out-of-bounds access"); + is(privateWin.content.localStorage.key(-1), null, "key() should return null for out-of-bounds access"); + is(privateWin.content.localStorage.key(1), null, "key() should return null for out-of-bounds access"); + is(privateWin.content.localStorage.getItem("nonexisting"), null, "Nonexisting item is null"); + is(privateWin.content.localStorage.getItem("key1"), null, "key1 removed"); + is(privateWin.content.localStorage.getItem("key2"), null, "key2 removed"); + privateWin.content.localStorage.removeItem("nonexisting"); // Just check there is no exception + privateWin.content.localStorage.removeItem("key1"); // Just check there is no exception + privateWin.content.localStorage.removeItem("key2"); // Just check there is no exception + + privateWin.content.localStorage.setItem("must disappear", "private browsing value"); + + privateWin.close(); + + // The .close() call above will operate asynchronously, so execute the + // code below asynchronously as well. + function callback(newPrivateWin) { + is(newPrivateWin.content.localStorage.getItem("must disappear"), null, "private browsing values threw away"); + is(newPrivateWin.content.localStorage.length, 0, "No items"); + + newPrivateWin.close(); + is(aWin.content.localStorage.getItem("persistent"), "persistent1", "back in normal mode"); + aWin.content.localStorage.clear(); + aWin.close(); + + prefBranch.clearUserPref("browser.startup.page") + prefBranch.clearUserPref("browser.startup.homepage_override.mstone"); + SimpleTest.finish(); + }; + SimpleTest.executeSoon(() => testOnWindow(true, callback)); + }); + }); +} + +SimpleTest.waitForExplicitFinish(); + +</script> + +</head> + +<body onload="startTest();"> + +</body> +</html> diff --git a/dom/tests/mochitest/localstorage/test_localStorageBaseSessionOnly.html b/dom/tests/mochitest/localstorage/test_localStorageBaseSessionOnly.html new file mode 100644 index 0000000000..39df8ac519 --- /dev/null +++ b/dom/tests/mochitest/localstorage/test_localStorageBaseSessionOnly.html @@ -0,0 +1,211 @@ +<html xmlns="http://www.w3.org/1999/xhtml"> +<head> +<title>localStorage basic test, while in sesison only mode</title> + +<script src="/tests/SimpleTest/SimpleTest.js"></script> +<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> + +<script type="text/javascript"> + +function startTest() +{ + if (SpecialPowers.Services.domStorageManager.nextGenLocalStorageEnabled) { + ok(true, "Test ignored when the next gen local storage is enabled."); + SimpleTest.finish(); + return; + } + + SpecialPowers.pushPermissions([{'type': 'cookie', 'allow': SpecialPowers.Ci.nsICookiePermission.ACCESS_SESSION, 'context': document}], test1); +} + +function test1() { + // Initially check the localStorage is empty + is(localStorage.length, 0, "The storage is empty [1]"); + is(localStorage.key(0), null, "key() should return null for out-of-bounds access"); + is(localStorage.key(-1), null, "key() should return null for out-of-bounds access"); + is(localStorage.key(1), null, "key() should return null for out-of-bounds access"); + is(localStorage.getItem("nonexisting"), null, "Nonexisting item is null (getItem())"); + is(localStorage.nonexisting, undefined, "Nonexisting item is undefined (array access)"); + is(localStorage.nonexisting, undefined, "Nonexisting item is undefined (property access)"); + localStorage.removeItem("nonexisting"); // Just check there is no exception + + is(typeof localStorage.getItem("nonexisting"), "object", "getItem('nonexisting') is object"); + is(typeof localStorage.nonexisting, "undefined", "['nonexisting'] is undefined"); + is(typeof localStorage.nonexisting, "undefined", "nonexisting is undefined"); + is(typeof localStorage.getItem("nonexisting2"), "object", "getItem('nonexisting2') is object"); + is(typeof localStorage.nonexisting2, "undefined", "['nonexisting2'] is undefined"); + is(typeof localStorage.nonexisting2, "undefined", "nonexisting2 is undefined"); + + // add an empty-value key + localStorage.setItem("empty", ""); + is(localStorage.getItem("empty"), "", "Empty value (getItem())"); + is(localStorage.empty, "", "Empty value (array access)"); + is(localStorage.empty, "", "Empty value (property access)"); + is(typeof localStorage.getItem("empty"), "string", "getItem('empty') is string"); + is(typeof localStorage.empty, "string", "['empty'] is string"); + is(typeof localStorage.empty, "string", "empty is string"); + localStorage.removeItem("empty"); + is(localStorage.length, 0, "The storage has no keys"); + is(localStorage.getItem("empty"), null, "empty item is null (getItem())"); + is(localStorage.empty, undefined, "empty item is undefined (array access)"); + is(localStorage.empty, undefined, "empty item is undefined (property access)"); + is(typeof localStorage.getItem("empty"), "object", "getItem('empty') is object"); + is(typeof localStorage.empty, "undefined", "['empty'] is undefined"); + is(typeof localStorage.empty, "undefined", "empty is undefined"); + + // add one key, check it is there + localStorage.setItem("key1", "value1"); + is(localStorage.length, 1, "The storage has one key-value pair"); + is(localStorage.key(0), "key1"); + is(localStorage.key(-1), null, "key() should return null for out-of-bounds access"); + is(localStorage.key(1), null, "key() should return null for out-of-bounds access"); + + // check all access method give the correct result + // and are of the correct type + is(localStorage.getItem("key1"), "value1", "getItem('key1') == value1"); + is(localStorage.key1, "value1", "['key1'] == value1"); + is(localStorage.key1, "value1", "key1 == value1"); + + is(typeof localStorage.getItem("key1"), "string", "getItem('key1') is string"); + is(typeof localStorage.key1, "string", "['key1'] is string"); + is(typeof localStorage.key1, "string", "key1 is string"); + + // remove the previously added key and check the storage is empty + localStorage.removeItem("key1"); + is(localStorage.length, 0, "The storage is empty [2]"); + is(localStorage.key(0), null, "key() should return null for out-of-bounds access"); + is(localStorage.getItem("key1"), null, "\'key1\' removed"); + + is(typeof localStorage.getItem("key1"), "object", "getItem('key1') is object"); + is(typeof localStorage.key1, "undefined", "['key1'] is undefined"); + is(typeof localStorage.key1, "undefined", "key1 is undefined"); + + // add one key, check it is there + localStorage.setItem("key1", "value1"); + is(localStorage.length, 1, "The storage has one key-value pair"); + is(localStorage.key(0), "key1"); + is(localStorage.getItem("key1"), "value1"); + + // add a second key + localStorage.setItem("key2", "value2"); + is(localStorage.length, 2, "The storage has two key-value pairs"); + is(localStorage.getItem("key1"), "value1"); + is(localStorage.getItem("key2"), "value2"); + var firstKey = localStorage.key(0); + var secondKey = localStorage.key(1); + ok((firstKey == 'key1' && secondKey == 'key2') || + (firstKey == 'key2' && secondKey == 'key1'), + 'key() API works.'); + + // change the second key + localStorage.setItem("key2", "value2-2"); + is(localStorage.length, 2, "The storage has two key-value pairs"); + is(localStorage.key(0), firstKey); // After key value changes the order must be preserved + is(localStorage.key(1), secondKey); + is(localStorage.key(-1), null, "key() should return null for out-of-bounds access"); + is(localStorage.key(2), null, "key() should return null for out-of-bounds access"); + is(localStorage.getItem("key1"), "value1"); + is(localStorage.getItem("key2"), "value2-2"); + + // change the first key + localStorage.setItem("key1", "value1-2"); + is(localStorage.length, 2, "The storage has two key-value pairs"); + is(localStorage.key(0), firstKey); // After key value changes the order must be preserved + is(localStorage.key(1), secondKey); + is(localStorage.key(-1), null, "key() should return null for out-of-bounds access"); + is(localStorage.key(2), null, "key() should return null for out-of-bounds access"); + is(localStorage.getItem("key1"), "value1-2"); + is(localStorage.getItem("key2"), "value2-2"); + + // remove the second key + localStorage.removeItem("key2"); + is(localStorage.length, 1, "The storage has one key-value pair"); + is(localStorage.key(0), "key1"); + is(localStorage.key(-1), null, "key() should return null for out-of-bounds access"); + is(localStorage.key(1), null, "key() should return null for out-of-bounds access"); + is(localStorage.getItem("key1"), "value1-2"); + + // JS property test + localStorage.testA = "valueA"; + is(localStorage.testA, "valueA"); + is(localStorage.testA, "valueA"); + is(localStorage.getItem("testA"), "valueA"); + + localStorage.testA = "valueA2"; + is(localStorage.testA, "valueA2"); + is(localStorage.testA, "valueA2"); + is(localStorage.getItem("testA"), "valueA2"); + + localStorage.testB = "valueB"; + is(localStorage.testB, "valueB"); + is(localStorage.testB, "valueB"); + is(localStorage.getItem("testB"), "valueB"); + + localStorage.testB = "valueB2"; + is(localStorage.testB, "valueB2"); + is(localStorage.testB, "valueB2"); + is(localStorage.getItem("testB"), "valueB2"); + + localStorage.setItem("testC", "valueC"); + is(localStorage.testC, "valueC"); + is(localStorage.testC, "valueC"); + is(localStorage.getItem("testC"), "valueC"); + + localStorage.setItem("testC", "valueC2"); + is(localStorage.testC, "valueC2"); + is(localStorage.testC, "valueC2"); + is(localStorage.getItem("testC"), "valueC2"); + + localStorage.setItem("testC", null); + is("testC" in localStorage, true); + is(localStorage.getItem("testC"), "null"); + is(localStorage.testC, "null"); + is(localStorage.testC, "null"); + + localStorage.removeItem("testC"); + localStorage.testC = null; + is("testC" in localStorage, true); + is(localStorage.getItem("testC"), "null"); + is(localStorage.testC, "null"); + is(localStorage.testC, "null"); + + localStorage.setItem(null, "test"); + is("null" in localStorage, true); + is(localStorage.getItem("null"), "test"); + is(localStorage.getItem(null), "test"); + is(localStorage.null, "test"); + localStorage.removeItem(null, "test"); + is("null" in localStorage, false); + + localStorage.setItem(null, "test"); + is("null" in localStorage, true); + localStorage.removeItem("null", "test"); + is("null" in localStorage, false); + + // Clear the storage + localStorage.clear(); + is(localStorage.length, 0, "The storage is empty [3]"); + is(localStorage.key(0), null, "key() should return null for out-of-bounds access"); + is(localStorage.key(-1), null, "key() should return null for out-of-bounds access"); + is(localStorage.key(1), null, "key() should return null for out-of-bounds access"); + is(localStorage.getItem("nonexisting"), null, "Nonexisting item is null"); + is(localStorage.getItem("key1"), null, "key1 removed"); + is(localStorage.getItem("key2"), null, "key2 removed"); + localStorage.removeItem("nonexisting"); // Just check there is no exception + localStorage.removeItem("key1"); // Just check there is no exception + localStorage.removeItem("key2"); // Just check there is no exception + + localStorage.clear(); + SimpleTest.finish(); +} + +SimpleTest.waitForExplicitFinish(); + +</script> + +</head> + +<body onload="startTest();"> + +</body> +</html> diff --git a/dom/tests/mochitest/localstorage/test_localStorageCookieSettings.html b/dom/tests/mochitest/localstorage/test_localStorageCookieSettings.html new file mode 100644 index 0000000000..32f944561d --- /dev/null +++ b/dom/tests/mochitest/localstorage/test_localStorageCookieSettings.html @@ -0,0 +1,77 @@ +<html xmlns="http://www.w3.org/1999/xhtml"> +<head> +<title>localStorage cookies settings test</title> + +<script src="/tests/SimpleTest/SimpleTest.js"></script> +<script type="text/javascript" src="interOriginTest.js"></script> +<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> + +</head> +<body> + +<script type="text/javascript"> + +SimpleTest.waitForExplicitFinish(); + +// Set cookies behavior to "always reject". +SpecialPowers.pushPrefEnv({"set": [ + ["network.cookie.cookieBehavior", 2], +]}, test1); + +function test1() { + let w = window.open("windowProxy.html"); + w.onload = _ => { + try { + w.localStorage.setItem("contentkey", "test-value"); + ok(false, "Setting localStorageItem should throw a security exception"); + } + catch(ex) { + is(ex.name, "SecurityError", "Got security exception"); + } + + w.close(); + + // Set cookies behavior to "reject 3rd party" + SpecialPowers.pushPrefEnv({"set": [["network.cookie.cookieBehavior", 1]], + "clear": [["network.cookie.lifetimePolicy"]]}, + test2); + } +} + +function test2() { + let w = window.open("windowProxy.html"); + w.onload = _ => { + try { + w.localStorage.setItem("contentkey", "test-value"); + ok(true, "Setting localStorageItem should not throw a security exception"); + } + catch(ex) { + ok(false, "Setting localStorageItem should not throw a security exception"); + } + + var fileTest = (location.protocol + "//example.com" + location.pathname) + .replace("test_l", "frameL"); + + var myframe = w.document.createElement("iframe"); + w.document.body.appendChild(myframe); + myframe.src = fileTest; + + w.onmessage = function(e) { + switch (e.data.type || "") { + case "ok": + ok(e.data.what, e.data.msg); + break; + case "finish": + w.close(); + SimpleTest.finish(); + break; + default: + ok(false, "Invalid type."); + } + }; + } +} + +</script> +</body> +</html> diff --git a/dom/tests/mochitest/localstorage/test_localStorageEnablePref.html b/dom/tests/mochitest/localstorage/test_localStorageEnablePref.html new file mode 100644 index 0000000000..485f4e010a --- /dev/null +++ b/dom/tests/mochitest/localstorage/test_localStorageEnablePref.html @@ -0,0 +1,65 @@ +<html xmlns="http://www.w3.org/1999/xhtml"> +<head> +<title>localStorage enable preference test</title> + +<script src="/tests/SimpleTest/SimpleTest.js"></script> +<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> + +<script type="text/javascript"> + +SimpleTest.requestCompleteLog(); + +function checkException(func, exc) +{ + var exceptionThrew = false; + try { + func(); + } + catch (ex) { + exceptionThrew = true; + is(ex.name, exc, "Expected "+exc+" exception"); + if (ex.name != exc) { + info("The exception which was thrown is: " + ex); + } + } + ok(exceptionThrew, "Exception "+exc+" threw"); +} + +var storage; +function test1() { + is(typeof(window.localStorage), "object", "Storage is present"); + storage = window.localStorage; + + SpecialPowers.pushPrefEnv({"set": [["dom.storage.enabled", false]]}, test2); +} + +function test2() { + is(window.localStorage, null, "Storage is null"); + + checkException(function() {storage.setItem("test", "value");}, "SecurityError"); + + SpecialPowers.pushPrefEnv({"set": [["dom.storage.enabled", true]]}, test3); +} + +function test3() { + is(typeof(window.localStorage), "object", "Storage is present again"); + storage.setItem("test", "value"); + is(storage.getItem("test"), "value", "value can be set"); + window.localStorage.clear(); + SimpleTest.finish(); +} + +function doTest() { + SpecialPowers.pushPrefEnv({"set": [["dom.storage.enabled", true]]}, test1); +} + +SimpleTest.waitForExplicitFinish(); + +</script> + +</head> + +<body onload="doTest();"> + +</body> +</html> diff --git a/dom/tests/mochitest/localstorage/test_localStorageFromChrome.xhtml b/dom/tests/mochitest/localstorage/test_localStorageFromChrome.xhtml new file mode 100644 index 0000000000..fe7be443e9 --- /dev/null +++ b/dom/tests/mochitest/localstorage/test_localStorageFromChrome.xhtml @@ -0,0 +1,60 @@ +<html xmlns="http://www.w3.org/1999/xhtml"> +<head> +<title>localStorage basic test</title> + +<script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script> +<link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css" /> + +<script type="text/javascript"> + +async function startTest() +{ + await SpecialPowers.pushPrefEnv({"set": [["dom.storage.client_validation", false]]}); + + var url = "http://example.com/tests/dom/tests/mochitest/localstorage/frameChromeSlave.html"; + var ios = Components.classes["@mozilla.org/network/io-service;1"] + .getService(Components.interfaces.nsIIOService); + var ssm = Components.classes["@mozilla.org/scriptsecuritymanager;1"] + .getService(Components.interfaces.nsIScriptSecurityManager); + var dsm = Components.classes["@mozilla.org/dom/localStorage-manager;1"] + .getService(Components.interfaces.nsIDOMStorageManager); + + var uri = ios.newURI(url); + var principal = ssm.createContentPrincipal(uri, {}); + var storage = dsm.createStorage(window, principal, principal, ""); + + storage.setItem("chromekey", "chromevalue"); + + var aframe = document.getElementById("aframe"); + aframe.onload = function() + { + is(storage.getItem("chromekey"), "chromevalue"); + is(aframe.contentDocument.getElementById("data").innerHTML, "chromevalue"); + SimpleTest.finish(); + } + aframe.src = "http://example.com/tests/dom/tests/mochitest/localstorage/frameChromeSlave.html"; + + // Additionally check that we do not crash when we access the localStorage + // object in the owning chrome window (but we should throw). See bug 485396. + var exceptionCaught = false; + try { + localStorage; + } + catch (e) { + is(e.result, Components.results.NS_ERROR_NOT_AVAILABLE, + "Testing that we get the expected exception."); + exceptionCaught = true; + } + is(exceptionCaught, true, "Testing that an exception was thrown."); +} + +SimpleTest.waitForExplicitFinish(); + +</script> + +</head> + +<body onload="startTest();"> + <iframe src="" id="aframe"></iframe> +</body> +</html> diff --git a/dom/tests/mochitest/localstorage/test_localStorageKeyOrder.html b/dom/tests/mochitest/localstorage/test_localStorageKeyOrder.html new file mode 100644 index 0000000000..a5dbb28b42 --- /dev/null +++ b/dom/tests/mochitest/localstorage/test_localStorageKeyOrder.html @@ -0,0 +1,73 @@ +<html xmlns="http://www.w3.org/1999/xhtml"> +<head> +<title>localStorage key order test</title> + +<script src="/tests/SimpleTest/SimpleTest.js"></script> +<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> + +<!-- + Check we preserve order of keys in localStorage when + keys are just modified. When a new key is added or + a key is removed order is again unspecified. +--> + +<script type="text/javascript"> + +function startTest() +{ + try + { + var keyNames = new Array; + localStorage.a = "1"; + localStorage.b = "2"; + localStorage.c = "3"; + localStorage.d = "4"; + localStorage.e = "5"; + + is(localStorage.a, "1", "a = 1"); + is(localStorage.b, "2", "b = 2"); + is(localStorage.c, "3", "c = 3"); + is(localStorage.d, "4", "d = 4"); + is(localStorage.e, "5", "e = 5"); + is(localStorage.length, 5, "length = 5"); + + for (var i = 0; i < localStorage.length; ++i) + keyNames[i] = localStorage.key(i); + + localStorage.a = "10"; + localStorage.b = "20"; + localStorage.c = "30"; + localStorage.d = "40"; + localStorage.e = "50"; + + is(localStorage.a, "10", "a = 10"); + is(localStorage.b, "20", "b = 20"); + is(localStorage.c, "30", "c = 30"); + is(localStorage.d, "40", "d = 40"); + is(localStorage.e, "50", "e = 50"); + is(localStorage.length, 5, "length = 5"); + + for (var i = 0; i < localStorage.length; ++i) + is(keyNames[i], localStorage.key(i), "key "+keyNames[i]+" on same index"); + + keyNamesStringify = "[\"" + keyNames.join("\",\"") + "\"]"; + frame.location = "http://mochi.test:8888/tests/dom/tests/mochitest/localstorage/frameOrder.html?" + + keyNamesStringify; + } + catch (ex) + { + localStorage.clear(); + throw ex; + } +} + +SimpleTest.waitForExplicitFinish(); + +</script> + +</head> + +<body onload="startTest();"> + <iframe src="" name="frame"></frame> +</body> +</html> diff --git a/dom/tests/mochitest/localstorage/test_localStorageOriginsDiff.html b/dom/tests/mochitest/localstorage/test_localStorageOriginsDiff.html new file mode 100644 index 0000000000..96a93171ca --- /dev/null +++ b/dom/tests/mochitest/localstorage/test_localStorageOriginsDiff.html @@ -0,0 +1,41 @@ +<html xmlns="http://www.w3.org/1999/xhtml"> +<head> +<title>localStorage different origins</title> + +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="interOriginTest2.js"></script> + +<!-- + This test loads two frames from different + origins and checks that entries of localStorage + objects don't leak each between other. + + The subsystem is based on postMessage and addEventListener + to send messages among different origins. The subsystem waits + for both frames be loaded and then alternately calls each frames' + doStep() function that on each call proceeds with a single step + of the test on its side. This way the subsystem alternate between + both frames until both sequences completely finish. +--> + +<script type="text/javascript"> + +function startTest() +{ + masterFrameOrigin = "http://example.org:80"; + slaveFrameOrigin = "http://example.com:80"; + + masterFrame.location = masterFrameOrigin + framePath + "frameMasterNotEqual.html"; + slaveFrame.location = slaveFrameOrigin + framePath + "frameSlaveNotEqual.html"; +} + +</script> + +</head> + +<body onload="startTest();"> + <iframe src="" name="masterFrame"></iframe> + <iframe src="" name="slaveFrame"></iframe> +</body> +</html> diff --git a/dom/tests/mochitest/localstorage/test_localStorageOriginsDomainDiffs.html b/dom/tests/mochitest/localstorage/test_localStorageOriginsDomainDiffs.html new file mode 100644 index 0000000000..c1a4417727 --- /dev/null +++ b/dom/tests/mochitest/localstorage/test_localStorageOriginsDomainDiffs.html @@ -0,0 +1,41 @@ +<html xmlns="http://www.w3.org/1999/xhtml"> +<head> +<title>localStorage different domains</title> + +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="interOriginTest2.js"></script> + +<!-- + This test loads two frames from different + origins and checks that entries of localStorage + objects don't leak each between other. + + The subsystem is based on postMessage and addEventListener + to send messages among different origins. The subsystem waits + for both frames be loaded and then alternately calls each frames' + doStep() function that on each call proceeds with a single step + of the test on its side. This way the subsystem alternate between + both frames until both sequences completely finish. +--> + +<script type="text/javascript"> + +function startTest() +{ + masterFrameOrigin = "http://example.org:80"; + slaveFrameOrigin = "http://test1.example.org:80"; + + masterFrame.location = masterFrameOrigin + framePath + "frameMasterNotEqual.html"; + slaveFrame.location = slaveFrameOrigin + framePath + "frameSlaveNotEqual.html"; +} + +</script> + +</head> + +<body onload="startTest();"> + <iframe src="" name="masterFrame"></iframe> + <iframe src="" name="slaveFrame"></iframe> +</body> +</html> diff --git a/dom/tests/mochitest/localstorage/test_localStorageOriginsEquals.html b/dom/tests/mochitest/localstorage/test_localStorageOriginsEquals.html new file mode 100644 index 0000000000..35cdd86b32 --- /dev/null +++ b/dom/tests/mochitest/localstorage/test_localStorageOriginsEquals.html @@ -0,0 +1,42 @@ +<html xmlns="http://www.w3.org/1999/xhtml"> +<head> +<title>localStorage equal origins</title> + +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="interOriginTest2.js"></script> + +<!-- + This test loads two frames from equal + origins and checks that entries of localStorage + objects are kept up-to-date and synchronized + between both frames. + + The subsystem is based on postMessage and addEventListener + to send messages among different origins. The subsystem waits + for both frames be loaded and then alternately calls each frames' + doStep() function that on each call proceeds with a single step + of the test on its side. This way the subsystem alternate between + both frames until both sequences completely finish. +--> + +<script type="text/javascript"> + +function startTest() +{ + masterFrameOrigin = "http://example.org:80"; + slaveFrameOrigin = "http://example.org:80"; + + masterFrame.location = masterFrameOrigin + framePath + "frameMasterEqual.html"; + slaveFrame.location = slaveFrameOrigin + framePath + "frameSlaveEqual.html"; +} + +</script> + +</head> + +<body onload="startTest();"> + <iframe src="" name="masterFrame"></iframe> + <iframe src="" name="slaveFrame"></iframe> +</body> +</html> diff --git a/dom/tests/mochitest/localstorage/test_localStorageOriginsPortDiffs.html b/dom/tests/mochitest/localstorage/test_localStorageOriginsPortDiffs.html new file mode 100644 index 0000000000..d34e0dbcd1 --- /dev/null +++ b/dom/tests/mochitest/localstorage/test_localStorageOriginsPortDiffs.html @@ -0,0 +1,41 @@ +<html xmlns="http://www.w3.org/1999/xhtml"> +<head> +<title>localStorage different port numbers</title> + +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="interOriginTest2.js"></script> + +<!-- + This test loads two frames from different + origins and checks that entries of localStorage + objects don't leak each between other. + + The subsystem is based on postMessage and addEventListener + to send messages among different origins. The subsystem waits + for both frames be loaded and then alternately calls each frames' + doStep() function that on each call proceeds with a single step + of the test on its side. This way the subsystem alternate between + both frames until both sequences completely finish. +--> + +<script type="text/javascript"> + +function startTest() +{ + masterFrameOrigin = "http://example.org:80"; + slaveFrameOrigin = "http://example.org:8000"; + + masterFrame.location = masterFrameOrigin + framePath + "frameMasterNotEqual.html"; + slaveFrame.location = slaveFrameOrigin + framePath + "frameSlaveNotEqual.html"; +} + +</script> + +</head> + +<body onload="startTest();"> + <iframe src="" name="masterFrame"></iframe> + <iframe src="" name="slaveFrame"></iframe> +</body> +</html> diff --git a/dom/tests/mochitest/localstorage/test_localStorageOriginsSchemaDiffs.html b/dom/tests/mochitest/localstorage/test_localStorageOriginsSchemaDiffs.html new file mode 100644 index 0000000000..57e4fb5ab3 --- /dev/null +++ b/dom/tests/mochitest/localstorage/test_localStorageOriginsSchemaDiffs.html @@ -0,0 +1,41 @@ +<html xmlns="http://www.w3.org/1999/xhtml"> +<head> +<title>localStorage different domains</title> + +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="interOriginTest2.js"></script> + +<!-- + This test loads two frames from different + origins and checks that entries of localStorage + objects don't leak each between other. + + The subsystem is based on postMessage and addEventListener + to send messages among different origins. The subsystem waits + for both frames be loaded and then alternately calls each frames' + doStep() function that on each call proceeds with a single step + of the test on its side. This way the subsystem alternate between + both frames until both sequences completely finish. +--> + +<script type="text/javascript"> + +function startTest() +{ + masterFrameOrigin = "http://example.com"; + slaveFrameOrigin = "https://example.com"; + + masterFrame.location = masterFrameOrigin + framePath + "frameMasterNotEqual.html"; + slaveFrame.location = slaveFrameOrigin + framePath + "frameSlaveNotEqual.html"; +} + +</script> + +</head> + +<body onload="startTest();"> + <iframe src="" name="masterFrame"></iframe> + <iframe src="" name="slaveFrame"></iframe> +</body> +</html> diff --git a/dom/tests/mochitest/localstorage/test_localStorageQuota.html b/dom/tests/mochitest/localstorage/test_localStorageQuota.html new file mode 100644 index 0000000000..a26252b313 --- /dev/null +++ b/dom/tests/mochitest/localstorage/test_localStorageQuota.html @@ -0,0 +1,136 @@ +<html xmlns="http://www.w3.org/1999/xhtml"> +<head> +<title>localStorage and DOM quota test</title> + +<script src="/tests/SimpleTest/SimpleTest.js"></script> +<script type="text/javascript" src="interOriginTest.js"></script> +<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> + +<script type="text/javascript"> +//Note: this test is currently giving failures when running standalone, see bug 914865 + +var currentTest = 1; + +function doNextTest() +{ + slave = frame; + + switch (currentTest) + { + case 1: + if (SpecialPowers.Services.domStorageManager.nextGenLocalStorageEnabled) { + slaveOrigin = "http://test1.example.com"; + } else { + slaveOrigin = "http://example.com"; + } + slave.location = slaveOrigin + slavePath + "frameQuota.html?add&A&success"; + break; + + // Now set another key with length 500 bytes, i.e. allocate 501 bytes + case 2: + slaveOrigin = "http://test1.example.com"; + slave.location = slaveOrigin + slavePath + "frameQuota.html?add&B&success"; + break; + + // Try to set the same key value again to check we don't fail + // even 1002 bytes has already been exhausted from the quota + // We just change the value of an existing key. + case 3: + slaveOrigin = "http://test1.example.com"; + slave.location = slaveOrigin + slavePath + "frameQuota.html?add&B&success"; + break; + + // Try to set the same key to a larger value that would lead to + // quota reach and check that the value is still the old one + case 4: + slaveOrigin = "http://test1.example.com"; + slave.location = slaveOrigin + slavePath + "frameQuota.html?add2&B&failure"; + break; + + // Try to set a new 500 bytes key and check we fail because we are over the + // quota. + case 5: + if (SpecialPowers.Services.domStorageManager.nextGenLocalStorageEnabled) { + slaveOrigin = "http://test1.example.com"; + } else if (SpecialPowers.Services.appinfo.fissionAutostart){ + // Fission makes the "https://test2.example.com" run in the different + // process with the other two and Legacy LS has issues with usage + // synchronization within processes, see Bug 1683299 for more details. + slaveOrigin = "http://test2.example.com"; + } else { + slaveOrigin = "https://test2.example.com"; + } + slave.location = slaveOrigin + slavePath + "frameQuota.html?add&C&failure"; + break; + + // Remove the second key, it must not fail. This should release the + // allocated space of the quota assigned to test1.example.com. + case 6: + slaveOrigin = "http://test1.example.com"; + slave.location = slaveOrigin + slavePath + "frameQuota.html?remove&B&success"; + break; + + // Now try again to set 500 bytes key, it must succeed. + case 7: + if (SpecialPowers.Services.domStorageManager.nextGenLocalStorageEnabled) { + slaveOrigin = "http://test1.example.com"; + } else if (SpecialPowers.Services.appinfo.fissionAutostart){ + slaveOrigin = "http://test2.example.com"; + } else { + slaveOrigin = "https://test2.example.com"; + } + slave.location = slaveOrigin + slavePath + "frameQuota.html?add&C&success"; + break; + + case 8: + if (SpecialPowers.Services.domStorageManager.nextGenLocalStorageEnabled) { + SimpleTest.executeSoon(doNextTest); + } else { + // Do a clean up... + slaveOrigin = "http://example.com"; + slave.location = slaveOrigin + slavePath + "frameQuota.html?clear"; + } + break; + + case 9: + // Do a clean up... + slaveOrigin = "http://test1.example.com"; + slave.location = slaveOrigin + slavePath + "frameQuota.html?clear"; + break; + + case 10: + if (SpecialPowers.Services.domStorageManager.nextGenLocalStorageEnabled) { + SimpleTest.executeSoon(doNextTest); + } else { + // Do a clean up... + slaveOrigin = "https://test2.example.com"; + slave.location = slaveOrigin + slavePath + "frameQuota.html?clear"; + } + break; + + default: // end + SimpleTest.finish(); + } + + ++currentTest; +} + +function doStep() +{ +} + +SimpleTest.waitForExplicitFinish(); + +function startTest() { + // Initialy setup the quota to testing value of 1024B and + // set a 500 bytes key with name length 1 (allocate 501 bytes) + SpecialPowers.pushPrefEnv({"set": [["dom.storage.default_quota", 1], ["dom.storage.default_site_quota", 1], ["security.mixed_content.block_display_content", false], ["security.mixed_content.block_active_content", false]]}, doNextTest); +} +</script> + +</head> + +<body onload="startTest();"> + <iframe src="" name="frame"></iframe> +</body> +</html> diff --git a/dom/tests/mochitest/localstorage/test_localStorageQuotaPrivateBrowsing_perwindowpb.html b/dom/tests/mochitest/localstorage/test_localStorageQuotaPrivateBrowsing_perwindowpb.html new file mode 100644 index 0000000000..71981ffd72 --- /dev/null +++ b/dom/tests/mochitest/localstorage/test_localStorageQuotaPrivateBrowsing_perwindowpb.html @@ -0,0 +1,191 @@ +<html xmlns="http://www.w3.org/1999/xhtml"> +<head> +<title>localStorage and DOM quota test</title> + +<script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script> +<link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"?> + +<script type="text/javascript"> +SimpleTest.waitForExplicitFinish(); + +const {Services} = ChromeUtils.import("resource://gre/modules/Services.jsm"); + +const CONTENT_PAGE = "http://mochi.test:8888/chrome/dom/tests/mochitest/localstorage/page_blank.html"; +const slavePath = "/chrome/dom/tests/mochitest/localstorage/"; +var currentTest = 1; +var quota = Services.prefs.getIntPref("dom.storage.default_quota", 5 * 1024); +var siteQuota = Services.prefs.getIntPref("dom.storage.default_site_quota", 25 * 1024); +Services.prefs.setIntPref("browser.startup.page", 0); +Services.prefs.setIntPref("dom.storage.default_quota", 1); +Services.prefs.setIntPref("dom.storage.default_site_quota", 1); + +var slaveLoadsPending = 1; +var slaveOrigin = ""; +var slave = null; +var failureRegExp = new RegExp("^FAILURE"); + +function startTest() { + testOnWindow(true, function(aWindow) { + info("Private window loaded"); + var frame = aWindow.content.document.createElement("iframe"); + aWindow.content.document.body.appendChild(frame); + aWindow.content.addEventListener("message", function(aEvent) { + onMessageReceived(aEvent, aWindow) + }); + slave = aWindow.content.frames[0]; + + SimpleTest.waitForFocus(() => doNextTest(aWindow), aWindow); + }); +} + +function doNextTest(aWindow) { + info("Running test: " + currentTest); + switch (currentTest) { + // Initialy setup the quota to testing value of 1024B and + // set a 500 bytes key with name length 1 (allocate 501 bytes) + case 1: + if (SpecialPowers.Services.domStorageManager.nextGenLocalStorageEnabled) { + slaveOrigin = "http://test1.example.com"; + } else { + slaveOrigin = "http://example.com"; + } + slave.location = slaveOrigin + slavePath + "frameQuota.html?add&A&success"; + break; + + // Now set another key with length 500 bytes, i.e. allocate 501 bytes + case 2: + slaveOrigin = "http://test1.example.com"; + slave.location = slaveOrigin + slavePath + "frameQuota.html?add&B&success"; + break; + + // Try to set the same key value again to check we don't fail + // even 1002 bytes has already been exhausted from the quota + // We just change the value of an existing key. + case 3: + slaveOrigin = "http://test1.example.com"; + slave.location = slaveOrigin + slavePath + "frameQuota.html?add&B&success"; + break; + + // Try to set the same key to a larger value that would lead to + // quota reach and check that the value is still the old one + case 4: + slaveOrigin = "http://test1.example.com"; + slave.location = slaveOrigin + slavePath + "frameQuota.html?add2&B&failure"; + break; + + // Try to set a new 500 bytes key and check we fail because we are over the + // quota. + case 5: + if (SpecialPowers.Services.domStorageManager.nextGenLocalStorageEnabled) { + slaveOrigin = "http://test1.example.com"; + } else { + slaveOrigin = "https://test2.example.com"; + } + slave.location = slaveOrigin + slavePath + "frameQuota.html?add&C&failure"; + break; + + // Remove the second key, it must not fail. This should release the + // allocated space of the quota assigned to test1.example.com. + case 6: + slaveOrigin = "http://test1.example.com"; + slave.location = slaveOrigin + slavePath + "frameQuota.html?remove&B&success"; + break; + + // Now try again to set 500 bytes key, it must succeed. + case 7: + if (SpecialPowers.Services.domStorageManager.nextGenLocalStorageEnabled) { + slaveOrigin = "http://test1.example.com"; + } else { + slaveOrigin = "https://test2.example.com"; + } + slave.location = slaveOrigin + slavePath + "frameQuota.html?add&C&success"; + break; + + case 8: + if (SpecialPowers.Services.domStorageManager.nextGenLocalStorageEnabled) { + SimpleTest.executeSoon(() => doNextTest(aWindow)); + } else { + // Do a clean up... + slaveOrigin = "http://example.com"; + slave.location = slaveOrigin + slavePath + "frameQuota.html?clear"; + } + break; + + case 9: + // Do a clean up... + slaveOrigin = "http://test1.example.com"; + slave.location = slaveOrigin + slavePath + "frameQuota.html?clear"; + break; + + case 10: + if (SpecialPowers.Services.domStorageManager.nextGenLocalStorageEnabled) { + SimpleTest.executeSoon(() => doNextTest(aWindow)); + } else { + // Do a clean up... + slaveOrigin = "https://test2.example.com"; + slave.location = slaveOrigin + slavePath + "frameQuota.html?clear"; + } + break; + + default: + Services.prefs.clearUserPref("browser.startup.page") + Services.prefs.setIntPref("dom.storage.default_quota", quota); + Services.prefs.setIntPref("dom.storage.default_site_quota", siteQuota); + aWindow.close(); + SimpleTest.finish(); + } + + ++currentTest; +} + +function onMessageReceived(event, aWindow) { + info("Message received: " + event.data); + switch (event.data) { + // Indication of the frame onload event + case "frame loaded": + if (--slaveLoadsPending) + break; + // Indication of successfully finished step of a test + // Just fall through... + case "perf": + // postMessage should send to the slaveOrigin. However with the addition of private + // browsing flags in origin attributes this will cause postMessage to fail. The origin of this + // window has false privatebrowsing, while the recipient is in a private window. + // To fix this issue and preserve the integrity of the test a * is passed to get around origin equality. + slave.postMessage("step", "*"); + break; + // Indication of all test parts finish (from any of the frames) + case "done": + aWindow.content.localStorage.clear(); + slaveLoadsPending = 1; + doNextTest(aWindow); + break; + // Any other message indicates error or succes message of a test + default: + SimpleTest.ok(!event.data.match(failureRegExp), event.data); + break; + } +} + +function whenDelayedStartupFinished(aCallback) { + Services.obs.addObserver(function observer(aSubject, aTopic) { + Services.obs.removeObserver(observer, aTopic); + + aSubject.addEventListener("DOMContentLoaded", function() { + SimpleTest.executeSoon(function() { aCallback(aSubject); }); + }, {capture: true, once: true}); + }, "browser-delayed-startup-finished"); +} + +function testOnWindow(aIsPrivate, callback) { + var mainWindow = window.browsingContext.topChromeWindow; + + mainWindow.openWebLinkIn(CONTENT_PAGE, "window", { + private: aIsPrivate }); + whenDelayedStartupFinished(callback); +}; +</script> +</head> +<body onload="startTest();"> +</body> +</html> diff --git a/dom/tests/mochitest/localstorage/test_localStorageQuotaSessionOnly.html b/dom/tests/mochitest/localstorage/test_localStorageQuotaSessionOnly.html new file mode 100644 index 0000000000..1d32776907 --- /dev/null +++ b/dom/tests/mochitest/localstorage/test_localStorageQuotaSessionOnly.html @@ -0,0 +1,134 @@ +<html xmlns="http://www.w3.org/1999/xhtml"> +<head> +<title>localStorage and DOM quota test</title> + +<script src="/tests/SimpleTest/SimpleTest.js"></script> +<script type="text/javascript" src="interOriginTest.js"></script> +<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> + +<script type="text/javascript"> + +var currentTest = 1; + +function doNextTest() +{ + slave = frame; + + switch (currentTest) + { + case 1: + slaveOrigin = "http://example.com"; + slave.location = slaveOrigin + slavePath + "frameQuotaSessionOnly.html?add&A&success"; + break; + + // In subdomain now set another key with length 500 bytes, i.e. + // allocate 501 bytes + case 2: + slaveOrigin = "http://test1.example.com"; + slave.location = slaveOrigin + slavePath + "frameQuotaSessionOnly.html?add&B&success"; + break; + + // Try to set the same key value again to check we don't fail + // even 1002 bytes has already been exhausted from the quota + // We just change the value of an existing key. + case 3: + slaveOrigin = "http://test1.example.com"; + slave.location = slaveOrigin + slavePath + "frameQuotaSessionOnly.html?add&B&success"; + break; + + // Try to set the same key to a larger value that would lead to + // quota reach and check that the value is still the old one + case 4: + slaveOrigin = "http://test1.example.com"; + slave.location = slaveOrigin + slavePath + "frameQuotaSessionOnly.html?add2&B&failure"; + break; + + // In a different subdomain try to set a new 500 bytes key + // and check we fail because we are over the quota + case 5: + slaveOrigin = "https://test2.example.com"; + slave.location = slaveOrigin + slavePath + "frameQuotaSessionOnly.html?add&C&failure"; + break; + + // Remove from the second subdomain the second key, it must not fail + // This should release the allocated space of the quota assigned to + // example.com. + case 6: + slaveOrigin = "http://test1.example.com"; + slave.location = slaveOrigin + slavePath + "frameQuotaSessionOnly.html?remove&B&success"; + break; + + // Now try again to set 500 bytes key, it must succeed. + case 7: + slaveOrigin = "https://test2.example.com"; + slave.location = slaveOrigin + slavePath + "frameQuotaSessionOnly.html?add&C&success"; + break; + + case 8: + // Do a clean up... + slaveOrigin = "http://example.com"; + slave.location = slaveOrigin + slavePath + "frameQuotaSessionOnly.html?clear"; + break; + + case 9: + // Do a clean up... + slaveOrigin = "http://test1.example.com"; + slave.location = slaveOrigin + slavePath + "frameQuotaSessionOnly.html?clear"; + break; + + case 10: + // Do a clean up... + slaveOrigin = "https://test2.example.com"; + slave.location = slaveOrigin + slavePath + "frameQuotaSessionOnly.html?clear"; + break; + + default: + SimpleTest.finish(); + } + + ++currentTest; +} + +function doStep() +{ +} + +SimpleTest.waitForExplicitFinish(); + +function startTest() { + if (SpecialPowers.Services.domStorageManager.nextGenLocalStorageEnabled) { + ok(true, "Test ignored when the next gen local storage is enabled."); + SimpleTest.finish(); + return; + } + + SpecialPowers.pushPermissions([ + { + type: "cookie", + allow: SpecialPowers.Ci.nsICookiePermission.ACCESS_SESSION, + context: "http://example.com", + }, + { + type: "cookie", + allow: SpecialPowers.Ci.nsICookiePermission.ACCESS_SESSION, + context: "http://test1.example.com", + }, + { + type: "cookie", + allow: SpecialPowers.Ci.nsICookiePermission.ACCESS_SESSION, + context: "https://test2.example.com", + }, + ], function() { + // Initialy setup the quota to testing value of 1024B and + // set a 500 bytes key with name length 1 (allocate 501 bytes) + SpecialPowers.pushPrefEnv({"set": [["dom.storage.default_quota", 1], ["dom.storage.default_site_quota", 1], ["security.mixed_content.block_display_content", false], ["security.mixed_content.block_active_content", false]]}, doNextTest); + }); +} +</script> + +</head> + +<body onload="startTest();"> + <iframe src="" name="frame"></iframe> +</body> +</html> diff --git a/dom/tests/mochitest/localstorage/test_localStorageQuotaSessionOnly2.html b/dom/tests/mochitest/localstorage/test_localStorageQuotaSessionOnly2.html new file mode 100644 index 0000000000..156ff02bf6 --- /dev/null +++ b/dom/tests/mochitest/localstorage/test_localStorageQuotaSessionOnly2.html @@ -0,0 +1,98 @@ +<html xmlns="http://www.w3.org/1999/xhtml"> +<head> +<title>localStorage and DOM quota test</title> + +<script src="/tests/SimpleTest/SimpleTest.js"></script> +<script type="text/javascript" src="interOriginTest.js"></script> +<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> + +<script type="text/javascript"> + +var currentTest = 1; + +function doNextTest() +{ + slave = frame; + + switch (currentTest) + { + case 1: + slaveOrigin = "http://example.com"; + slave.location = slaveOrigin + slavePath + "frameQuotaSessionOnly.html?add&A&success"; + break; + + // In subdomain now set another key with length 500 bytes, i.e. + // allocate 501 bytes + case 2: + slaveOrigin = "http://example.com"; + slave.location = slaveOrigin + slavePath + "frameQuotaSessionOnly.html?add&B&success"; + break; + + // Try to set the same key value again to check we don't fail + // even 1002 bytes has already been exhausted from the quota + // We just change the value of an existing key. + case 3: + slaveOrigin = "http://example.com"; + slave.location = slaveOrigin + slavePath + "frameQuotaSessionOnly.html?add&B&success"; + break; + + // Try to set the same key to a larger value that would lead to + // quota reach and check that the value is still the old one + case 4: + slaveOrigin = "http://example.com"; + slave.location = slaveOrigin + slavePath + "frameQuotaSessionOnly.html?add2&B&failure"; + break; + + // Try to set a new 500 bytes key + // and check we fail because we are over the quota + case 5: + slaveOrigin = "https://example.com"; + slave.location = slaveOrigin + slavePath + "frameQuotaSessionOnly.html?add&C&failure"; + break; + + // Remove the key inherited from the non-session-only database + case 6: + slaveOrigin = "http://example.com"; + slave.location = slaveOrigin + slavePath + "frameQuotaSessionOnly.html?remove&A&success"; + break; + + // Now try again to set 500 bytes key, it must succeed. + case 7: + slaveOrigin = "https://example.com"; + slave.location = slaveOrigin + slavePath + "frameQuotaSessionOnly.html?add&C&success"; + break; + + case 8: + // Do a clean up... + slaveOrigin = "http://example.com"; + slave.location = slaveOrigin + slavePath + "frameQuotaSessionOnly.html?clear"; + break; + + default: + SimpleTest.finish(); + } + + ++currentTest; +} + +function doStep() +{ +} + +SimpleTest.waitForExplicitFinish(); + +function startTest() { + // Initialy setup the quota to testing value of 1024B and + // set a 500 bytes key with name length 1 (allocate 501 bytes) + SpecialPowers.pushPrefEnv({"set": [["dom.storage.default_quota", 1], ["dom.storage.default_site_quota", 1], ["security.mixed_content.block_display_content", false], ["security.mixed_content.block_active_content", false]]}, function() { + SpecialPowers.pushPermissions([{'type': 'cookie', 'allow': SpecialPowers.Ci.nsICookiePermission.ACCESS_SESSION, 'context': document}], doNextTest); + }); +} +</script> + +</head> + +<body onload="startTest();"> + <iframe src="" name="frame"></iframe> +</body> +</html> diff --git a/dom/tests/mochitest/localstorage/test_localStorageReplace.html b/dom/tests/mochitest/localstorage/test_localStorageReplace.html new file mode 100644 index 0000000000..b80c35dbc5 --- /dev/null +++ b/dom/tests/mochitest/localstorage/test_localStorageReplace.html @@ -0,0 +1,80 @@ +<html xmlns="http://www.w3.org/1999/xhtml"> +<head> +<title>localStorage replace test</title> + +<!-- + This test checks that localStorage object doesn't leak + in a window that changes its location. We do this by switching + frame location inside of this window and then by changing location + of a top level window. +--> + +<script src="/tests/SimpleTest/SimpleTest.js"></script> +<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> + +<script type="text/javascript"> + +var shell; +var shellType; +var failureRegExp = new RegExp("^FAILURE"); + +window.addEventListener("message", onMessageReceived); + +function onMessageReceived(event) +{ + switch (event.data) + { + case "init_done": + // This is frame with different origin in the same browsing context + // as the first frame adding data to localStorage of the first origin. + shell.location = "http://example.com:80/tests/dom/tests/mochitest/localstorage/frameReplace.html?check&" + shellType; + break; + + case "check_done": + // Clean the localStorage of the first origin. + shell.location = "http://example.org:80/tests/dom/tests/mochitest/localstorage/frameReplace.html?clean&" + shellType; + break; + + case "clean_done": + switch (shellType) + { + case "frame": + // We finished testing in a frame + // proceed with test in a separate window + shellType = "window"; + shell = window.open("http://example.org:80/tests/dom/tests/mochitest/localstorage/frameReplace.html?init&" + shellType); + break; + + case "window": + shell.close(); + window.setTimeout(function() {SimpleTest.finish();}, 0); + break; + } + break; + + default: + SimpleTest.ok(!event.data.match(failureRegExp), event.data); + break; + } +} + +function startTest() { + SpecialPowers.pushPrefEnv({"set": [["security.mixed_content.block_display_content", false], ["security.mixed_content.block_active_content", false]]}, test1); +} + +function test1() { + shellType = "frame"; + shell = frame; + shell.location = "http://example.org:80/tests/dom/tests/mochitest/localstorage/frameReplace.html?init&" + shellType; +} + +SimpleTest.waitForExplicitFinish(); + +</script> + +</head> + +<body onload="startTest();"> + <iframe src="" name="frame"></iframe> +</body> +</html> diff --git a/dom/tests/mochitest/localstorage/test_storageConstructor.html b/dom/tests/mochitest/localstorage/test_storageConstructor.html new file mode 100644 index 0000000000..e0aa4e11dc --- /dev/null +++ b/dom/tests/mochitest/localstorage/test_storageConstructor.html @@ -0,0 +1,35 @@ +<html xmlns="http://www.w3.org/1999/xhtml"> +<head> +<title>Storage interface</title> + +<script src="/tests/SimpleTest/SimpleTest.js"></script> +<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> + +<script type="text/javascript"> + +function startTest() +{ + var functionCalled = false; + is(localStorage instanceof Storage, true, "localStorage is instance of Storage"); + Storage.prototype.exists = function(key) { + functionCalled = true; + return this.getItem(key) != null; + } + localStorage.setItem("test_prototype", "value"); + is(functionCalled, false, "Overridden function not called"); + is(localStorage.exists("test_prototype"), true, "Prototype overridden"); + is(functionCalled, true, "Overridden function called"); + localStorage.clear(); + + SimpleTest.finish(); +} + +SimpleTest.waitForExplicitFinish(); + +</script> + +</head> + +<body onload="startTest();"> +</body> +</html> diff --git a/dom/tests/mochitest/localstorage/windowProxy.html b/dom/tests/mochitest/localstorage/windowProxy.html new file mode 100644 index 0000000000..39ba8eab0f --- /dev/null +++ b/dom/tests/mochitest/localstorage/windowProxy.html @@ -0,0 +1,3 @@ +<html xmlns="http://www.w3.org/1999/xhtml"> +<body></body> +</html> |