diff options
Diffstat (limited to 'testing/web-platform/tests/webstorage')
76 files changed, 3011 insertions, 0 deletions
diff --git a/testing/web-platform/tests/webstorage/META.yml b/testing/web-platform/tests/webstorage/META.yml new file mode 100644 index 0000000000..a3853105f8 --- /dev/null +++ b/testing/web-platform/tests/webstorage/META.yml @@ -0,0 +1,5 @@ +spec: https://html.spec.whatwg.org/multipage/webstorage.html +suggested_reviewers: + - siusin + - inexorabletash + - jdm diff --git a/testing/web-platform/tests/webstorage/README.md b/testing/web-platform/tests/webstorage/README.md new file mode 100644 index 0000000000..2bbc5fbfb6 --- /dev/null +++ b/testing/web-platform/tests/webstorage/README.md @@ -0,0 +1,4 @@ +These are the storage (`localStorage`, `sessionStorage`) tests for the +[Web storage chapter of the HTML Standard](https://html.spec.whatwg.org/multipage/webstorage.html). + +IDL is covered by `/html/dom/idlharness.https.html`. diff --git a/testing/web-platform/tests/webstorage/defineProperty.window.js b/testing/web-platform/tests/webstorage/defineProperty.window.js new file mode 100644 index 0000000000..d8ab163df6 --- /dev/null +++ b/testing/web-platform/tests/webstorage/defineProperty.window.js @@ -0,0 +1,57 @@ +["localStorage", "sessionStorage"].forEach(function(name) { + [9, "x"].forEach(function(key) { + test(function() { + var desc = { + value: "value", + }; + + var storage = window[name]; + storage.clear(); + + assert_equals(storage[key], undefined); + assert_equals(storage.getItem(key), null); + assert_equals(Object.defineProperty(storage, key, desc), storage); + assert_equals(storage[key], "value"); + assert_equals(storage.getItem(key), "value"); + }, "Defining data property for key " + key + " on " + name); + + test(function() { + var desc1 = { + value: "value", + }; + var desc2 = { + value: "new value", + }; + + var storage = window[name]; + storage.clear(); + + assert_equals(storage[key], undefined); + assert_equals(storage.getItem(key), null); + assert_equals(Object.defineProperty(storage, key, desc1), storage); + assert_equals(storage[key], "value"); + assert_equals(storage.getItem(key), "value"); + + assert_equals(Object.defineProperty(storage, key, desc2), storage); + assert_equals(storage[key], "new value"); + assert_equals(storage.getItem(key), "new value"); + }, "Defining data property for key " + key + " on " + name + " twice"); + + test(function() { + var desc = { + value: { + toString: function() { return "value"; } + }, + }; + + var storage = window[name]; + storage.clear(); + + assert_equals(storage[key], undefined); + assert_equals(storage.getItem(key), null); + assert_equals(Object.defineProperty(storage, key, desc), storage); + assert_equals(storage[key], "value"); + assert_equals(storage.getItem(key), "value"); + }, "Defining data property with toString for key " + key + " on " + name); + }); +}); diff --git a/testing/web-platform/tests/webstorage/document-domain.html b/testing/web-platform/tests/webstorage/document-domain.html new file mode 100644 index 0000000000..3232b0d508 --- /dev/null +++ b/testing/web-platform/tests/webstorage/document-domain.html @@ -0,0 +1,20 @@ +<!doctype html> +<title>localStorage and document.domain</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +</head> +<body> +<div id="log"></div> +<iframe></iframe> +<script> + async_test(function(t) { + frames[0].addEventListener("storage", function(e) { + t.step(function() { + localStorage.clear() + t.done() + }) + }) + frames[0].document.domain = document.domain + localStorage.setItem("test", "test") + }) +</script> diff --git a/testing/web-platform/tests/webstorage/eventTestHarness.js b/testing/web-platform/tests/webstorage/eventTestHarness.js new file mode 100644 index 0000000000..0a98546ace --- /dev/null +++ b/testing/web-platform/tests/webstorage/eventTestHarness.js @@ -0,0 +1,54 @@ +storageEventList = []; +iframe = document.createElement("IFRAME"); +document.body.appendChild(iframe); + +function runAfterNStorageEvents(callback, expectedNumEvents) +{ + countStorageEvents(callback, expectedNumEvents, 0) +} + +function countStorageEvents(callback, expectedNumEvents, times) +{ + function onTimeout() + { + var currentCount = storageEventList.length; + if (currentCount == expectedNumEvents) { + callback(); + } else if (currentCount > expectedNumEvents) { + msg = "got at least " + currentCount + ", expected only " + expectedNumEvents + " events"; + callback(msg); + } else if (times > 50) { + msg = "Timeout: only got " + currentCount + ", expected " + expectedNumEvents + " events"; + callback(msg); + } else { + countStorageEvents(callback, expectedNumEvents, times+1); + } + } + setTimeout(onTimeout, 20); +} + +function clearStorage(storageName, callback) +{ + if (window[storageName].length === 0) { + storageEventList = []; + setTimeout(callback, 0); + } else { + window[storageName].clear(); + runAfterNStorageEvents(function() { + storageEventList = []; + callback(); + }, 1); + } +} + +function testStorages(testCallback) +{ + testCallback("sessionStorage"); + var hit = false; + add_result_callback(function() { + if (!hit) { + hit = true; + testCallback("localStorage"); + } + }); +} diff --git a/testing/web-platform/tests/webstorage/event_basic.html b/testing/web-platform/tests/webstorage/event_basic.html new file mode 100644 index 0000000000..407e41c4b1 --- /dev/null +++ b/testing/web-platform/tests/webstorage/event_basic.html @@ -0,0 +1,15 @@ +<!DOCTYPE HTML> +<html> +<head> +<meta name="timeout" content="long"> +<title>WebStorage Test: StorageEvent - window.onstorage</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +</head> +<body> +<div id="log"></div> +<script src="eventTestHarness.js"></script> +<script src="event_basic.js"></script> +</body> +</html> + diff --git a/testing/web-platform/tests/webstorage/event_basic.js b/testing/web-platform/tests/webstorage/event_basic.js new file mode 100644 index 0000000000..09f5f1bfb9 --- /dev/null +++ b/testing/web-platform/tests/webstorage/event_basic.js @@ -0,0 +1,128 @@ +testStorages(function(storageString) { + async_test(function(t) { + assert_true(storageString in window, storageString + " exist"); + var storage = window[storageString]; + t.add_cleanup(function() { storage.clear() }); + + clearStorage(storageString, t.step_func(loadiframe)); + assert_equals(storage.length, 0, "storage.length"); + + function loadiframe(msg) + { + iframe.onload = t.step_func(step1); + iframe.src = "resources/event_basic.html"; + } + + function step1(msg) + { + storage.setItem('FOO', 'BAR'); + + runAfterNStorageEvents(t.step_func(step2), 1); + } + + function step2(msg) + { + if(msg != undefined) { + assert_unreached(msg); + } + assert_equals(storageEventList.length, 1); + assert_equals(storageEventList[0].storageAreaString, storageString, + "Storage event came from wrong storage type."); + assert_equals(storageEventList[0].key, "FOO"); + assert_equals(storageEventList[0].oldValue, null); + assert_equals(storageEventList[0].newValue, "BAR"); + + storage.setItem('FU', 'BAR'); + storage.setItem('a', '1'); + storage.setItem('b', '2'); + storage.setItem('b', '3'); + + runAfterNStorageEvents(t.step_func(step3), 5); + } + + function step3(msg) + { + if(msg != undefined) { + assert_unreached(msg); + } + assert_equals(storageEventList.length, 5); + assert_equals(storageEventList[1].storageAreaString, storageString, + "Storage event came from wrong storage type."); + assert_equals(storageEventList[1].key, "FU"); + assert_equals(storageEventList[1].oldValue, null); + assert_equals(storageEventList[1].newValue, "BAR"); + + assert_equals(storageEventList[2].storageAreaString, storageString, + "Storage event came from wrong storage type."); + assert_equals(storageEventList[2].key, "a"); + assert_equals(storageEventList[2].oldValue, null); + assert_equals(storageEventList[2].newValue, "1"); + + assert_equals(storageEventList[3].storageAreaString, storageString, + "Storage event came from wrong storage type."); + assert_equals(storageEventList[3].key, "b"); + assert_equals(storageEventList[3].oldValue, null); + assert_equals(storageEventList[3].newValue, "2"); + + assert_equals(storageEventList[4].storageAreaString, storageString, + "Storage event came from wrong storage type."); + assert_equals(storageEventList[4].key, "b"); + assert_equals(storageEventList[4].oldValue, "2"); + assert_equals(storageEventList[4].newValue, "3"); + + storage.removeItem('FOO'); + + runAfterNStorageEvents(t.step_func(step4), 6); + } + + function step4(msg) + { + if(msg != undefined) { + assert_unreached(msg); + } + assert_equals(storageEventList.length, 6); + assert_equals(storageEventList[5].storageAreaString, storageString, + "Storage event came from wrong storage type."); + assert_equals(storageEventList[5].key, "FOO"); + assert_equals(storageEventList[5].oldValue, "BAR"); + assert_equals(storageEventList[5].newValue, null); + + storage.removeItem('FU'); + + runAfterNStorageEvents(t.step_func(step5), 7); + } + + function step5(msg) + { + if(msg != undefined) { + assert_unreached(msg); + } + assert_equals(storageEventList.length, 7); + assert_equals(storageEventList[6].storageAreaString, storageString, + "Storage event came from wrong storage type."); + assert_equals(storageEventList[6].key, "FU"); + assert_equals(storageEventList[6].oldValue, "BAR"); + assert_equals(storageEventList[6].newValue, null); + + storage.clear(); + + runAfterNStorageEvents(t.step_func(step6), 8); + } + + function step6(msg) + { + if(msg != undefined) { + assert_unreached(msg); + } + assert_equals(storageEventList.length, 8); + assert_equals(storageEventList[7].storageAreaString, storageString, + "Storage event came from wrong storage type."); + assert_equals(storageEventList[7].key, null); + assert_equals(storageEventList[7].oldValue, null); + assert_equals(storageEventList[7].newValue, null); + + t.done(); + } + + }, storageString + " mutations fire StorageEvents that are caught by the event listener set via window.onstorage."); +}); diff --git a/testing/web-platform/tests/webstorage/event_body_attribute.html b/testing/web-platform/tests/webstorage/event_body_attribute.html new file mode 100644 index 0000000000..80ec676186 --- /dev/null +++ b/testing/web-platform/tests/webstorage/event_body_attribute.html @@ -0,0 +1,15 @@ +<!DOCTYPE HTML> +<html> +<head> +<meta name="timeout" content="long"> +<title>WebStorage Test: StorageEvent - set onstorage as body attribute</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +</head> +<body> +<div id="log"></div> +<script src="eventTestHarness.js"></script> +<script src="event_body_attribute.js"></script> +</body> +</html> + diff --git a/testing/web-platform/tests/webstorage/event_body_attribute.js b/testing/web-platform/tests/webstorage/event_body_attribute.js new file mode 100644 index 0000000000..a0e596da95 --- /dev/null +++ b/testing/web-platform/tests/webstorage/event_body_attribute.js @@ -0,0 +1,116 @@ +testStorages(function(storageString) { + async_test(function(t) { + assert_true(storageString in window, storageString + " exist"); + var storage = window[storageString]; + t.add_cleanup(function() { storage.clear() }); + + clearStorage(storageString, t.step_func(step0)); + assert_equals(storage.length, 0, "storage.length"); + + function step0(msg) + { + iframe.onload = t.step_func(step1); + // Null out the existing handler eventTestHarness.js set up; + // otherwise this test won't be testing much of anything useful. + iframe.contentWindow.onstorage = null; + iframe.src = "resources/event_body_handler.html"; + } + + function step1(msg) + { + storageEventList = new Array(); + storage.setItem('FOO', 'BAR'); + + runAfterNStorageEvents(t.step_func(step2), 1); + } + + function step2(msg) + { + if (msg != undefined) { + assert_unreached(msg); + } + assert_equals(storageEventList.length, 1); + assert_equals(storageEventList[0].key, "FOO"); + assert_equals(storageEventList[0].oldValue, null); + assert_equals(storageEventList[0].newValue, "BAR"); + + storage.setItem('FU', 'BAR'); + storage.setItem('a', '1'); + storage.setItem('b', '2'); + storage.setItem('b', '3'); + + runAfterNStorageEvents(t.step_func(step3), 5); + } + + function step3(msg) + { + if (msg != undefined) { + assert_unreached(msg); + } + assert_equals(storageEventList.length, 5); + assert_equals(storageEventList[1].key, "FU"); + assert_equals(storageEventList[1].oldValue, null); + assert_equals(storageEventList[1].newValue, "BAR"); + + assert_equals(storageEventList[2].key, "a"); + assert_equals(storageEventList[2].oldValue, null); + assert_equals(storageEventList[2].newValue, "1"); + + assert_equals(storageEventList[3].key, "b"); + assert_equals(storageEventList[3].oldValue, null); + assert_equals(storageEventList[3].newValue, "2"); + + assert_equals(storageEventList[4].key, "b"); + assert_equals(storageEventList[4].oldValue, "2"); + assert_equals(storageEventList[4].newValue, "3"); + + storage.removeItem('FOO'); + + runAfterNStorageEvents(t.step_func(step4), 6); + } + + function step4(msg) + { + if(msg != undefined) { + assert_unreached(msg); + } + assert_equals(storageEventList.length, 6); + assert_equals(storageEventList[5].key, "FOO"); + assert_equals(storageEventList[5].oldValue, "BAR"); + assert_equals(storageEventList[5].newValue, null); + + storage.removeItem('FU'); + + runAfterNStorageEvents(t.step_func(step5), 7); + } + + function step5(msg) + { + if(msg != undefined) { + assert_unreached(msg); + } + assert_equals(storageEventList.length, 7); + assert_equals(storageEventList[6].key, "FU"); + assert_equals(storageEventList[6].oldValue, "BAR"); + assert_equals(storageEventList[6].newValue, null); + + storage.clear(); + + runAfterNStorageEvents(t.step_func(step6), 8); + } + + function step6(msg) + { + if(msg != undefined) { + assert_unreached(msg); + } + assert_equals(storageEventList.length, 8); + assert_equals(storageEventList[7].key, null); + assert_equals(storageEventList[7].oldValue, null); + assert_equals(storageEventList[7].newValue, null); + + t.done(); + } + + }, storageString + " mutations fire StorageEvents that are caught by the event listener specified as an attribute on the body."); +}); diff --git a/testing/web-platform/tests/webstorage/event_case_sensitive.html b/testing/web-platform/tests/webstorage/event_case_sensitive.html new file mode 100644 index 0000000000..916b230412 --- /dev/null +++ b/testing/web-platform/tests/webstorage/event_case_sensitive.html @@ -0,0 +1,15 @@ +<!DOCTYPE HTML> +<html> +<head> +<meta name="timeout" content="long"> +<title>WebStorage Test: StorageEvent - the case of value changed</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +</head> +<body> +<div id="log"></div> +<script src="eventTestHarness.js"></script> +<script src="event_case_sensitive.js"></script> +</body> +</html> + diff --git a/testing/web-platform/tests/webstorage/event_case_sensitive.js b/testing/web-platform/tests/webstorage/event_case_sensitive.js new file mode 100644 index 0000000000..9c9397fd5a --- /dev/null +++ b/testing/web-platform/tests/webstorage/event_case_sensitive.js @@ -0,0 +1,52 @@ +testStorages(function(storageString) { + async_test(function(t) { + assert_true(storageString in window, storageString + " exist"); + var storage = window[storageString]; + t.add_cleanup(function() { storage.clear() }); + + clearStorage(storageString, t.step_func(loadiframe)); + assert_equals(storage.length, 0, "storage.length"); + + function loadiframe(msg) + { + iframe.onload = t.step_func(step0); + iframe.src = "resources/event_basic.html"; + } + + function step0(msg) + { + storage.foo = "test"; + runAfterNStorageEvents(t.step_func(step1), 1); + } + + function step1(msg) + { + storageEventList = new Array(); + storage.foo = "test"; + + runAfterNStorageEvents(t.step_func(step2), 0); + } + + function step2(msg) + { + if(msg != undefined) { + assert_unreached(msg); + } + assert_equals(storageEventList.length, 0); + + storage.foo = "TEST"; + + runAfterNStorageEvents(t.step_func(step3), 1); + } + + function step3(msg) + { + if(msg != undefined) { + assert_unreached(msg); + } + assert_equals(storageEventList.length, 1); + + t.done(); + } + }, storageString + " storage events fire even when only the case of the value changes."); +}); diff --git a/testing/web-platform/tests/webstorage/event_constructor.window.js b/testing/web-platform/tests/webstorage/event_constructor.window.js new file mode 100644 index 0000000000..13f4ca5e97 --- /dev/null +++ b/testing/web-platform/tests/webstorage/event_constructor.window.js @@ -0,0 +1,77 @@ +test(function() { + assert_throws_js( + TypeError, + () => StorageEvent(""), + "Calling StorageEvent constructor without 'new' must throw" + ); +}, "StorageEvent constructor called as normal function"); + +test(function() { + assert_throws_js(TypeError, () => new StorageEvent()); + // should be redundant, but .length can be wrong with custom bindings + assert_equals(StorageEvent.length, 1, 'StorageEvent.length'); +}, 'constructor with no arguments'); + +test(function() { + var event = new StorageEvent('type'); + assert_equals(event.type, 'type', 'type'); + assert_equals(event.key, null, 'key'); + assert_equals(event.oldValue, null, 'oldValue'); + assert_equals(event.newValue, null, 'newValue'); + assert_equals(event.url, '', 'url'); + assert_equals(event.storageArea, null, 'storageArea'); +}, 'constructor with just type argument'); + +test(function() { + assert_not_equals(localStorage, null, 'localStorage'); // precondition + + var event = new StorageEvent('storage', { + bubbles: true, + cancelable: true, + key: 'key', + oldValue: 'oldValue', + newValue: 'newValue', + url: 'url', // not an absolute URL to ensure it isn't resolved + storageArea: localStorage + }); + assert_equals(event.type, 'storage', 'type'); + assert_equals(event.bubbles, true, 'bubbles'); + assert_equals(event.cancelable, true, 'cancelable'); + assert_equals(event.key, 'key', 'key'); + assert_equals(event.oldValue, 'oldValue', 'oldValue'); + assert_equals(event.newValue, 'newValue', 'newValue'); + assert_equals(event.url, 'url', 'url'); + assert_equals(event.storageArea, localStorage, 'storageArea'); +}, 'constructor with sensible type argument and members'); + +test(function() { + var event = new StorageEvent(null, { + key: null, + oldValue: null, + newValue: null, + url: null, + storageArea: null + }); + assert_equals(event.type, 'null', 'type'); + assert_equals(event.key, null, 'key'); + assert_equals(event.oldValue, null, 'oldValue'); + assert_equals(event.newValue, null, 'newValue'); + assert_equals(event.url, 'null', 'url'); + assert_equals(event.storageArea, null, 'storageArea'); +}, 'constructor with null type argument and members'); + +test(function() { + var event = new StorageEvent(undefined, { + key: undefined, + oldValue: undefined, + newValue: undefined, + url: undefined, + storageArea: undefined + }); + assert_equals(event.type, 'undefined', 'type'); + assert_equals(event.key, null, 'key'); + assert_equals(event.oldValue, null, 'oldValue'); + assert_equals(event.newValue, null, 'newValue'); + assert_equals(event.url, '', 'url'); // not 'undefined'! + assert_equals(event.storageArea, null, 'storageArea'); +}, 'constructor with undefined type argument and members'); diff --git a/testing/web-platform/tests/webstorage/event_initstorageevent.window.js b/testing/web-platform/tests/webstorage/event_initstorageevent.window.js new file mode 100644 index 0000000000..ac0a757021 --- /dev/null +++ b/testing/web-platform/tests/webstorage/event_initstorageevent.window.js @@ -0,0 +1,60 @@ +test(() => { + const event = new StorageEvent('storage'); + assert_throws_js(TypeError, () => event.initStorageEvent()); + // should be redundant, but .length can be wrong with custom bindings + assert_equals(event.initStorageEvent.length, 1, 'event.initStorageEvent.length'); +}, 'initStorageEvent with 0 arguments'); + +test(() => { + const event = new StorageEvent('storage'); + event.initStorageEvent('type'); + assert_equals(event.type, 'type', 'event.type'); + assert_equals(event.bubbles, false, 'event.bubbles'); + assert_equals(event.cancelable, false, 'event.cancelable'); + assert_equals(event.key, null, 'event.key'); + assert_equals(event.oldValue, null, 'event.oldValue'); + assert_equals(event.newValue, null, 'event.newValue'); + assert_equals(event.url, '', 'event.url'); + assert_equals(event.storageArea, null, 'event.storageArea'); +}, 'initStorageEvent with 1 argument'); + +test(() => { + assert_not_equals(localStorage, null, 'localStorage'); // precondition + + const event = new StorageEvent('storage'); + event.initStorageEvent('type', true, true, 'key', 'oldValue', 'newValue', 'url', localStorage); + assert_equals(event.type, 'type', 'event.type'); + assert_equals(event.bubbles, true, 'event.bubbles'); + assert_equals(event.cancelable, true, 'event.cancelable'); + assert_equals(event.key, 'key', 'event.key'); + assert_equals(event.oldValue, 'oldValue', 'event.oldValue'); + assert_equals(event.newValue, 'newValue', 'event.newValue'); + assert_equals(event.url, 'url', 'event.url'); + assert_equals(event.storageArea, localStorage, 'event.storageArea'); +}, 'initStorageEvent with 8 sensible arguments'); + +test(() => { + const event = new StorageEvent('storage'); + event.initStorageEvent(null, null, null, null, null, null, null, null); + assert_equals(event.type, 'null', 'event.type'); + assert_equals(event.bubbles, false, 'event.bubbles'); + assert_equals(event.cancelable, false, 'event.cancelable'); + assert_equals(event.key, null, 'event.key'); + assert_equals(event.oldValue, null, 'event.oldValue'); + assert_equals(event.newValue, null, 'event.newValue'); + assert_equals(event.url, 'null', 'event.url'); + assert_equals(event.storageArea, null, 'event.storageArea'); +}, 'initStorageEvent with 8 null arguments'); + +test(() => { + const event = new StorageEvent('storage'); + event.initStorageEvent(undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined); + assert_equals(event.type, 'undefined', 'event.type'); + assert_equals(event.bubbles, false, 'event.bubbles'); + assert_equals(event.cancelable, false, 'event.cancelable'); + assert_equals(event.key, null, 'event.key'); + assert_equals(event.oldValue, null, 'event.oldValue'); + assert_equals(event.newValue, null, 'event.newValue'); + assert_equals(event.url, '', 'event.url'); + assert_equals(event.storageArea, null, 'event.storageArea'); +}, 'initStorageEvent with 8 undefined arguments'); diff --git a/testing/web-platform/tests/webstorage/event_local_key.html b/testing/web-platform/tests/webstorage/event_local_key.html new file mode 100644 index 0000000000..84512da2d2 --- /dev/null +++ b/testing/web-platform/tests/webstorage/event_local_key.html @@ -0,0 +1,38 @@ +<!DOCTYPE HTML> +<html> + <head> + <title>WebStorage Test: localStorage event - key</title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + </head> + <body> + <h1>event_local_key</h1> + <div id="log"></div> + <script> + async_test(function(t) { + localStorage.clear(); + t.add_cleanup(function() { localStorage.clear() }); + + self.fail = t.step_func(function(msg) { + assert_unreached(msg); + t.done(); + }); + + var expected = ['name', null] + function onStorageEvent(event) { + assert_equals(event.key, expected.shift()); + if (!expected.length) { + t.done(); + } + } + + window.addEventListener('storage', t.step_func(onStorageEvent), false); + + var el = document.createElement("iframe"); + el.setAttribute('id', 'ifrm'); + el.setAttribute('src', 'resources/local_set_item_clear_iframe.html'); + document.body.appendChild(el); + }, "key property test of local event - Local event is fired due to an invocation of the setItem(), clear() methods."); + </script> + </body> +</html> diff --git a/testing/web-platform/tests/webstorage/event_local_newvalue.html b/testing/web-platform/tests/webstorage/event_local_newvalue.html new file mode 100644 index 0000000000..2b743c37bf --- /dev/null +++ b/testing/web-platform/tests/webstorage/event_local_newvalue.html @@ -0,0 +1,38 @@ +<!DOCTYPE HTML> +<html> + <head> + <title>WebStorage Test: localStorage event - newValue</title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + </head> + <body> + <h1>event_local_newValue</h1> + <div id="log"></div> + <script> + async_test(function(t) { + localStorage.clear(); + t.add_cleanup(function() { localStorage.clear() }); + + self.fail = t.step_func(function(msg) { + assert_unreached(msg); + t.done(); + }); + + var expected = ['user1', 'user2', null] + function onStorageEvent(event) { + assert_equals(event.newValue, expected.shift()); + if (!expected.length) { + t.done(); + } + } + + window.addEventListener('storage', t.step_func(onStorageEvent), false); + + var el = document.createElement("iframe"); + el.setAttribute('id', 'ifrm'); + el.setAttribute('src', 'resources/local_change_item_iframe.html'); + document.body.appendChild(el); + }, "newValue property test of local event - Local event is fired due to an invocation of the setItem(), clear() methods."); + </script> + </body> +</html> diff --git a/testing/web-platform/tests/webstorage/event_local_oldvalue.html b/testing/web-platform/tests/webstorage/event_local_oldvalue.html new file mode 100644 index 0000000000..87c79aa07d --- /dev/null +++ b/testing/web-platform/tests/webstorage/event_local_oldvalue.html @@ -0,0 +1,38 @@ +<!DOCTYPE HTML> +<html> + <head> + <title>WebStorage Test: localStorage event - oldValue</title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + </head> + <body> + <h1>event_local_oldValue</h1> + <div id="log"></div> + <script> + async_test(function(t) { + localStorage.clear(); + t.add_cleanup(function() { localStorage.clear() }); + + self.fail = t.step_func(function(msg) { + assert_unreached(msg); + t.done(); + }); + + var expected = [null, 'user1', null] + function onStorageEvent(event) { + assert_equals(event.oldValue, expected.shift()); + if (!expected.length) { + t.done(); + } + } + + window.addEventListener('storage', t.step_func(onStorageEvent), false); + + var el = document.createElement("iframe"); + el.setAttribute('id', 'ifrm'); + el.setAttribute('src', 'resources/local_change_item_iframe.html'); + document.body.appendChild(el); + }, "oldValue property test of local event - Local event is fired due to an invocation of the setItem(), clear() methods."); + </script> + </body> +</html> diff --git a/testing/web-platform/tests/webstorage/event_local_removeitem.html b/testing/web-platform/tests/webstorage/event_local_removeitem.html new file mode 100644 index 0000000000..7b81ea2bac --- /dev/null +++ b/testing/web-platform/tests/webstorage/event_local_removeitem.html @@ -0,0 +1,45 @@ +<!DOCTYPE HTML> +<meta charset="utf-8"> +<title>Web Storage Test: event - localStorage removeItem</title> +<link rel="author" title="Intel" href="http://www.intel.com"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> + +<div id="log"></div> + +<script> + +async_test(function(t) { + localStorage.clear(); + t.add_cleanup(function() { localStorage.clear() }); + + self.step = function(f) { t.step(f); }; + + var event_index = 0; + window.addEventListener('storage', t.step_func(function(event) { + switch(++event_index) { + case 1: + assert_equals(event.key, "name", "set key"); + assert_equals(event.oldValue, null, "set oldValue"); + assert_equals(event.newValue, "user1", "set newValue"); + assert_equals(event.url, el.contentDocument.documentURI, "set url"); + assert_equals(event.storageArea, localStorage, "set storageArea"); + break; + case 2: + assert_equals(event.key, "name", "remove key"); + assert_equals(event.oldValue, "user1", "remove oldValue"); + assert_equals(event.newValue, null, "remove newValue"); + assert_equals(event.url, el.contentDocument.documentURI, "remove url"); + assert_equals(event.storageArea, localStorage, "remove storageArea"); + t.done(); + break; + } + }), false); + + var el = document.createElement("iframe"); + el.setAttribute('id', 'ifrm'); + el.setAttribute('src', 'resources/local_set_item_remove_iframe.html'); + document.body.appendChild(el); +}, "key property test of local event"); + +</script> diff --git a/testing/web-platform/tests/webstorage/event_local_storagearea.html b/testing/web-platform/tests/webstorage/event_local_storagearea.html new file mode 100644 index 0000000000..db4b114a95 --- /dev/null +++ b/testing/web-platform/tests/webstorage/event_local_storagearea.html @@ -0,0 +1,39 @@ +<!DOCTYPE HTML> +<html> + <head> + <title>WebStorage Test: localStorage event - storageArea</title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + </head> + <body> + <h1>event_local_storageArea</h1> + <div id="log"></div> + <script> + async_test(function(t) { + localStorage.clear(); + t.add_cleanup(function() { localStorage.clear() }); + + self.fail = t.step_func(function(msg) { + assert_unreached(msg); + t.done(); + }); + + function onStorageEvent(event) { + assert_equals(event.storageArea.length, 1); + var key = event.storageArea.key(0); + var value = event.storageArea.getItem(key); + assert_equals(key, "name"); + assert_equals(value, "user1"); + t.done(); + } + + window.addEventListener('storage', t.step_func(onStorageEvent), false); + + var el = document.createElement("iframe"); + el.setAttribute('id', 'ifrm'); + el.setAttribute('src', 'resources/local_set_item_iframe.html'); + document.body.appendChild(el); + }, "storageArea property test of local event - Local event is fired due to an invocation of the setItem() method."); + </script> + </body> +</html> diff --git a/testing/web-platform/tests/webstorage/event_local_url.html b/testing/web-platform/tests/webstorage/event_local_url.html new file mode 100644 index 0000000000..7345ce3736 --- /dev/null +++ b/testing/web-platform/tests/webstorage/event_local_url.html @@ -0,0 +1,43 @@ +<!DOCTYPE HTML> +<html> + <head> + <title>WebStorage Test: localStorage event - url</title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + </head> + <body> + <h1>event_local_url</h1> + <div id="log"></div> + <script> + async_test(function(t) { + localStorage.clear(); + t.add_cleanup(function() { localStorage.clear() }); + + self.fail = t.step_func(function(msg) { + assert_unreached(msg); + t.done(); + }); + + function onStorageEvent(event) { + var url = window.location.href; + + var pos = url.lastIndexOf("/"); + if (pos != -1) { + url = url.substr(0, pos + 1); + url = url + "resources/local_set_item_iframe.html"; + } + + assert_equals(event.url, url); + t.done(); + } + + window.addEventListener('storage', t.step_func(onStorageEvent), false); + + var el = document.createElement("iframe"); + el.setAttribute('id', 'ifrm'); + el.setAttribute('src', 'resources/local_set_item_iframe.html'); + document.body.appendChild(el); + }, "url property test of local event - Local event is fired due to an invocation of the setItem() method."); + </script> + </body> +</html> diff --git a/testing/web-platform/tests/webstorage/event_no_duplicates.html b/testing/web-platform/tests/webstorage/event_no_duplicates.html new file mode 100644 index 0000000000..8fbea2bef9 --- /dev/null +++ b/testing/web-platform/tests/webstorage/event_no_duplicates.html @@ -0,0 +1,111 @@ +<!DOCTYPE HTML> +<html> +<title>WebStorage Test: StorageEvent - only if something changes</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<body> +<script> +const iframe = document.createElement('iframe'); + +function tests(storageName) { + test(t => assert_true(storageName in window), storageName + ' exists'); + + const storage = window[storageName]; + const iframeStorage = iframe.contentWindow[storageName]; + + add_completion_callback(() => { + storage.clear(); + }); + + promise_test(t => { + const w = new EventWatcher(t, iframe.contentWindow, 'storage'); + + // Random key to make sure we don't conflict with any cruft leftover from + // earlier runs. Any synchronization would be really hard with localStorage + // limited guarantees. + const testKey = Math.random().toString(36).slice(2); + + storage.setItem(testKey, 'foo'); + storage.setItem(testKey, 'foo'); + storage.setItem(testKey, 'bar'); + return w.wait_for('storage') + .then(e => { + assert_equals(e.storageArea, iframeStorage); + assert_equals(e.key, testKey); + assert_equals(e.newValue, 'foo'); + return w.wait_for('storage'); + }) + .then(e => { + assert_equals(e.storageArea, iframeStorage); + assert_equals(e.key, testKey); + assert_equals(e.oldValue, 'foo'); + assert_equals(e.newValue, 'bar'); + }); + }, 'Setting to same value does not trigger event for ' + storageName); + + promise_test(t => { + const w = new EventWatcher(t, iframe.contentWindow, 'storage'); + + // Random key to make sure we don't conflict with any cruft leftover from + // earlier runs. Any synchronization would be really hard with localStorage + // limited guarantees. + const testKey1 = Math.random().toString(36).slice(2); + const testKey2 = Math.random().toString(36).slice(2); + + storage.removeItem(testKey1); + storage.setItem(testKey2, 'foo'); + return w.wait_for('storage') + .then(e => { + assert_equals(e.storageArea, iframeStorage); + assert_equals(e.key, testKey2); + assert_equals(e.newValue, 'foo'); + }); + }, 'Deleting non-existent key does not trigger event for ' + storageName); + + + promise_test(t => { + const w = new EventWatcher(t, iframe.contentWindow, 'storage'); + + // Random key to make sure we don't conflict with any cruft leftover from + // earlier runs. Any synchronization would be really hard with localStorage + // limited guarantees. + const testKey = Math.random().toString(36).slice(2); + + storage.setItem(testKey, 'foo'); + storage.clear(); + storage.clear(); + storage.setItem(testKey, 'bar'); + return w.wait_for('storage') + .then(e => { + assert_equals(e.storageArea, iframeStorage); + assert_equals(e.key, testKey); + assert_equals(e.newValue, 'foo'); + return w.wait_for('storage'); + }) + .then(e => { + assert_equals(e.storageArea, iframeStorage); + assert_equals(e.key, null); + assert_equals(e.oldValue, null); + assert_equals(e.newValue, null); + return w.wait_for('storage'); + }) + .then(e => { + assert_equals(e.storageArea, iframeStorage); + assert_equals(e.key, testKey); + assert_equals(e.oldValue, null); + assert_equals(e.newValue, 'bar'); + }); + }, 'Clearing empty storage does not trigger event for ' + storageName); + +} + +iframe.src = "resources/event_basic.html"; +iframe.onload = () => { + tests('sessionStorage'); + tests('localStorage'); +}; +document.body.appendChild(iframe); +</script> +</body> +</html> + diff --git a/testing/web-platform/tests/webstorage/event_session_key.html b/testing/web-platform/tests/webstorage/event_session_key.html new file mode 100644 index 0000000000..62600aa394 --- /dev/null +++ b/testing/web-platform/tests/webstorage/event_session_key.html @@ -0,0 +1,38 @@ +<!DOCTYPE HTML> +<html> + <head> + <title>WebStorage Test: sessionStorage event - key</title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + </head> + <body> + <h1>event_session_key</h1> + <div id="log"></div> + <script> + async_test(function(t) { + sessionStorage.clear(); + t.add_cleanup(function() { sessionStorage.clear() }); + + self.fail = t.step_func(function(msg) { + assert_unreached(msg); + t.done(); + }); + + var expected = ['name', null] + function onStorageEvent(event) { + assert_equals(event.key, expected.shift()); + if (!expected.length) { + t.done(); + } + } + + window.addEventListener('storage', t.step_func(onStorageEvent), false); + + var el = document.createElement("iframe"); + el.setAttribute('id', 'ifrm'); + el.setAttribute('src', 'resources/session_set_item_clear_iframe.html'); + document.body.appendChild(el); + }, "key property test of session event - Session event is fired due to an invocation of the setItem(), clear() methods."); + </script> + </body> +</html> diff --git a/testing/web-platform/tests/webstorage/event_session_newvalue.html b/testing/web-platform/tests/webstorage/event_session_newvalue.html new file mode 100644 index 0000000000..1f367988e0 --- /dev/null +++ b/testing/web-platform/tests/webstorage/event_session_newvalue.html @@ -0,0 +1,40 @@ +<!DOCTYPE HTML> +<html> + <head> + <title>WebStorage Test: sessionStorage event - newValue</title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + </head> + <body> + <h1>event_session_newValue</h1> + <div id="log"></div> + <script> + async_test(function(t) { + sessionStorage.clear(); + t.add_cleanup(function() { sessionStorage.clear() }); + + self.fail = t.step_func(function(msg) { + assert_unreached(msg); + t.done(); + }); + + var expected = ['user1', 'user2', null] + function onStorageEvent(event) { + t.step(function() { + assert_equals(event.newValue, expected.shift()); + }); + if (!expected.length) { + t.done(); + } + } + + window.addEventListener('storage', t.step_func(onStorageEvent), false); + + var el = document.createElement("iframe"); + el.setAttribute('id', 'ifrm'); + el.setAttribute('src', 'resources/session_change_item_iframe.html'); + document.body.appendChild(el); + }, "newvalue property test of session event - Session event is fired due to an invocation of the setItem(), clear() methods."); + </script> + </body> +</html> diff --git a/testing/web-platform/tests/webstorage/event_session_oldvalue.html b/testing/web-platform/tests/webstorage/event_session_oldvalue.html new file mode 100644 index 0000000000..00400df252 --- /dev/null +++ b/testing/web-platform/tests/webstorage/event_session_oldvalue.html @@ -0,0 +1,38 @@ +<!DOCTYPE HTML> +<html> + <head> + <title>WebStorage Test: sessionStorage event - oldValue</title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + </head> + <body> + <h1>event_session_oldValue</h1> + <div id="log"></div> + <script> + async_test(function(t) { + sessionStorage.clear(); + t.add_cleanup(function() { sessionStorage.clear() }); + + self.fail = t.step_func(function(msg) { + assert_unreached(msg); + t.done(); + }); + + var expected = [null, 'user1', null] + function onStorageEvent(event) { + assert_equals(event.oldValue, expected.shift()); + if (!expected.length) { + t.done(); + } + } + + window.addEventListener('storage', t.step_func(onStorageEvent), false); + + var el = document.createElement("iframe"); + el.setAttribute('id', 'ifrm'); + el.setAttribute('src', 'resources/session_change_item_iframe.html'); + document.body.appendChild(el); + }, "oldvalue property test of session event - Session event is fired due to an invocation of the setItem(), clear() methods."); + </script> + </body> +</html> diff --git a/testing/web-platform/tests/webstorage/event_session_removeitem.html b/testing/web-platform/tests/webstorage/event_session_removeitem.html new file mode 100644 index 0000000000..7b3c6446ed --- /dev/null +++ b/testing/web-platform/tests/webstorage/event_session_removeitem.html @@ -0,0 +1,44 @@ +<!DOCTYPE HTML> +<meta charset="utf-8"> +<title>Web Storage Test: event - sessionStorage removeItem</title> +<link rel="author" title="Intel" href="http://www.intel.com"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> + +<div id="log"></div> + +<script> + +async_test(function(t) { + sessionStorage.clear(); + t.add_cleanup(function() { sessionStorage.clear() }); + + self.step = function(f) { t.step(f); }; + + var event_index = 0; + window.addEventListener('storage', t.step_func(function(event) { + switch(++event_index) { + case 1: + assert_equals(event.key, "name", "set key"); + assert_equals(event.oldValue, null, "set oldValue"); + assert_equals(event.newValue, "user1", "set newValue"); + assert_equals(event.url, el.contentDocument.documentURI, "set url"); + assert_equals(event.storageArea, sessionStorage, "set storageArea"); + break; + case 2: + assert_equals(event.key, "name", "remove key"); + assert_equals(event.oldValue, "user1", "remove oldValue"); + assert_equals(event.newValue, null, "remove newValue"); + assert_equals(event.url, el.contentDocument.documentURI, "remove url"); + assert_equals(event.storageArea, sessionStorage, "remove storageArea"); + t.done(); + break; + } + }), false); + + var el = document.createElement("iframe"); + el.setAttribute('id', 'ifrm'); + el.setAttribute('src', 'resources/session_set_item_remove_iframe.html'); + document.body.appendChild(el); +}, "key property test of session event"); +</script> diff --git a/testing/web-platform/tests/webstorage/event_session_storagearea.html b/testing/web-platform/tests/webstorage/event_session_storagearea.html new file mode 100644 index 0000000000..d2c2ba437e --- /dev/null +++ b/testing/web-platform/tests/webstorage/event_session_storagearea.html @@ -0,0 +1,40 @@ +<!DOCTYPE HTML> +<html> + <head> + <title>WebStorage Test: sessionStorage event - storageArea</title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + </head> + <body> + <h1>event_session_storageArea</h1> + <div id="log"></div> + <script> + async_test(function(t) { + sessionStorage.clear(); + t.add_cleanup(function() { sessionStorage.clear() }); + + self.fail = t.step_func(function(msg) { + assert_unreached(msg); + t.done(); + }); + + function onStorageEvent(event) { + assert_equals(event.storageArea.length, 1); + var key = event.storageArea.key(0); + var value = event.storageArea.getItem(key); + assert_equals(key, "name"); + assert_equals(value, "user1"); + t.done(); + } + + window.addEventListener('storage', t.step_func(onStorageEvent), false); + + var el = document.createElement("iframe"); + el.setAttribute('id', 'ifrm'); + el.setAttribute('src', 'resources/session_set_item_iframe.html'); + document.body.appendChild(el); + }, "storageArea property test of session event - session event is fired due to an invocation of the setItem() method."); + </script> + + </body> +</html> diff --git a/testing/web-platform/tests/webstorage/event_session_url.html b/testing/web-platform/tests/webstorage/event_session_url.html new file mode 100644 index 0000000000..85250acc2b --- /dev/null +++ b/testing/web-platform/tests/webstorage/event_session_url.html @@ -0,0 +1,43 @@ +<!DOCTYPE HTML> +<html> + <head> + <title>WebStorage Test: sessionStorage event - url</title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + </head> + <body> + <h1>event_session_url</h1> + <div id="log"></div> + <script> + async_test(function(t) { + sessionStorage.clear(); + t.add_cleanup(function() { sessionStorage.clear() }); + + self.fail = t.step_func(function(msg) { + assert_unreached(msg); + t.done(); + }); + + function onStorageEvent(event) { + var url = window.location.href; + + var pos = url.lastIndexOf("/"); + if (pos != -1) { + url = url.substr(0, pos + 1); + url = url + "resources/session_set_item_iframe.html"; + } + + assert_equals(event.url, url); + t.done(); + } + + window.addEventListener('storage', t.step_func(onStorageEvent), false); + + var el = document.createElement("iframe"); + el.setAttribute('id', 'ifrm'); + el.setAttribute('src', 'resources/session_set_item_iframe.html'); + document.body.appendChild(el); + }, "url property test of session event - Session event is fired due to an invocation of the setItem() method."); + </script> + </body> +</html> diff --git a/testing/web-platform/tests/webstorage/event_setattribute.html b/testing/web-platform/tests/webstorage/event_setattribute.html new file mode 100644 index 0000000000..c48a2e0fc3 --- /dev/null +++ b/testing/web-platform/tests/webstorage/event_setattribute.html @@ -0,0 +1,15 @@ +<!DOCTYPE HTML> +<html> +<head> +<meta name="timeout" content="long"> +<title>WebStorage Test: StorageEvent - attached setAttribute</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +</head> +<body> +<div id="log"></div> +<script src="eventTestHarness.js"></script> +<script src="event_setattribute.js"></script> +</body> +</html> + diff --git a/testing/web-platform/tests/webstorage/event_setattribute.js b/testing/web-platform/tests/webstorage/event_setattribute.js new file mode 100644 index 0000000000..8070938baf --- /dev/null +++ b/testing/web-platform/tests/webstorage/event_setattribute.js @@ -0,0 +1,115 @@ +testStorages(function(storageString) { + async_test(function(t) { + assert_true(storageString in window, storageString + " exist"); + var storage = window[storageString]; + t.add_cleanup(function() { storage.clear() }); + + clearStorage(storageString, t.step_func(step0)); + assert_equals(storage.length, 0, "storage.length"); + + function step0(msg) + { + iframe.onload = t.step_func(step1); + // Null out the existing handler eventTestHarness.js set up; + // otherwise this test won't be testing much of anything useful. + iframe.contentWindow.onstorage = null; + iframe.src = "resources/event_setattribute_handler.html"; + } + + function step1(msg) + { + storage.setItem('FOO', 'BAR'); + + runAfterNStorageEvents(t.step_func(step2), 1); + } + + function step2(msg) + { + if(msg != undefined) { + assert_unreached(msg); + } + assert_equals(storageEventList.length, 1); + assert_equals(storageEventList[0].key, "FOO"); + assert_equals(storageEventList[0].oldValue, null); + assert_equals(storageEventList[0].newValue, "BAR"); + + storage.setItem('FU', 'BAR'); + storage.setItem('a', '1'); + storage.setItem('b', '2'); + storage.setItem('b', '3'); + + runAfterNStorageEvents(t.step_func(step3), 5); + } + + function step3(msg) + { + if(msg != undefined) { + assert_unreached(msg); + } + assert_equals(storageEventList.length, 5); + assert_equals(storageEventList[1].key, "FU"); + assert_equals(storageEventList[1].oldValue, null); + assert_equals(storageEventList[1].newValue, "BAR"); + + assert_equals(storageEventList[2].key, "a"); + assert_equals(storageEventList[2].oldValue, null); + assert_equals(storageEventList[2].newValue, "1"); + + assert_equals(storageEventList[3].key, "b"); + assert_equals(storageEventList[3].oldValue, null); + assert_equals(storageEventList[3].newValue, "2"); + + assert_equals(storageEventList[4].key, "b"); + assert_equals(storageEventList[4].oldValue, "2"); + assert_equals(storageEventList[4].newValue, "3"); + + storage.removeItem('FOO'); + + runAfterNStorageEvents(t.step_func(step4), 6); + } + + function step4(msg) + { + if(msg != undefined) { + assert_unreached(msg); + } + assert_equals(storageEventList.length, 6); + assert_equals(storageEventList[5].key, "FOO"); + assert_equals(storageEventList[5].oldValue, "BAR"); + assert_equals(storageEventList[5].newValue, null); + + storage.removeItem('FU'); + + runAfterNStorageEvents(t.step_func(step5), 7); + } + + function step5(msg) + { + if(msg != undefined) { + assert_unreached(msg); + } + assert_equals(storageEventList.length, 7); + assert_equals(storageEventList[6].key, "FU"); + assert_equals(storageEventList[6].oldValue, "BAR"); + assert_equals(storageEventList[6].newValue, null); + + storage.clear(); + + runAfterNStorageEvents(t.step_func(step6), 8); + } + + function step6(msg) + { + if(msg != undefined) { + assert_unreached(msg); + } + assert_equals(storageEventList.length, 8); + assert_equals(storageEventList[7].key, null); + assert_equals(storageEventList[7].oldValue, null); + assert_equals(storageEventList[7].newValue, null); + + t.done(); + } + + }, storageString + " mutations fire StorageEvents that are caught by the event listener attached via setattribute."); +}); diff --git a/testing/web-platform/tests/webstorage/localstorage-about-blank-3P-iframe-opens-3P-window.partitioned.tentative.html b/testing/web-platform/tests/webstorage/localstorage-about-blank-3P-iframe-opens-3P-window.partitioned.tentative.html new file mode 100644 index 0000000000..de94fb2cf4 --- /dev/null +++ b/testing/web-platform/tests/webstorage/localstorage-about-blank-3P-iframe-opens-3P-window.partitioned.tentative.html @@ -0,0 +1,75 @@ +<!doctype html> +<meta charset=utf-8> +<title>localStorage: about:blank partitioning</title> +<meta name=help href="https://privacycg.github.io/storage-partitioning/"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/common/get-host-info.sub.js"></script> +<script src="/webstorage/resources/partitioning-utils.js"></script> +<body> +<script> +const path = + "webstorage/resources/localstorage-about-blank-partitioned-win-open.html"; +const crossSiteURL = `${get_host_info().HTTP_NOTSAMESITE_ORIGIN}/${path}`; +const sameSiteURL = `${get_host_info().HTTP_ORIGIN}/${path}`; +let firstPartyID = getOrCreateID("userID3"); +let crossSiteIframeID; +let sameSiteIframeID; +let crossSiteIframe; +let crossSiteIframeAboutBlankID; +let frameMessageCount = 0; + +promise_test(async t => { + localStorage.clear(); + + // Step 1. Add a cross-site iframe + return addIframePromise(crossSiteURL).then(async crossSiteIframe => { + return new Promise(resolve => { + window.addEventListener("message", async e => { + const payload = { + command: "open about:blank window" + } + + if (e.data.message === "window loaded") { + // Step 2. cross-site iframe is loaded, capture reference to its ID + crossSiteIframeID = e.data.userID; + // Step 3. Ask the cross-site iframe to create an about:blank window + crossSiteIframe.contentWindow.postMessage(payload, e.origin); + } + + if (e.data.message === "about:blank frame ID") { + // Step 4. capture reference to 3P iframe's about:blank window ID + crossSiteIframeAboutBlankID = e.data.userID; + crossSiteIframe.contentWindow.postMessage( + {command: "close about:blank window"}, "*"); + } + + if (e.data.message === "about:blank window closed") { + resolve({crossSiteIframeID, crossSiteIframeAboutBlankID}); + } + }); + }).then(ids => { + const { + crossSiteIframeID, + crossSiteIframeAboutBlankID + } = ids; + // Step 5. Assert some things + for (let id in ids) { + assert_true(id !== undefined, "id is not undefined"); + } + // Note: we use assert_true, rather than assert_equals becuase we're + // setting random numbers as IDs - this would mean expectations + // files wouldn't work as intended. + assert_true(crossSiteIframeAboutBlankID !== crossSiteIframeID, + "about:blank window opened by 3P iframe does not inherit 3P iframe's StorageKey"); + assert_true(firstPartyID !== crossSiteIframeAboutBlankID, + "about:blank window open by 3P iframe does not inherit 1P StorageKey"); + + localStorage.clear(); + }) + }); + + +}, "StorageKey: test 3P about:blank window opened from a 3P iframe"); +</script> +</body> diff --git a/testing/web-platform/tests/webstorage/localstorage-basic-partitioned.tentative.sub.html b/testing/web-platform/tests/webstorage/localstorage-basic-partitioned.tentative.sub.html new file mode 100644 index 0000000000..7ed49b1e9a --- /dev/null +++ b/testing/web-platform/tests/webstorage/localstorage-basic-partitioned.tentative.sub.html @@ -0,0 +1,61 @@ +<!doctype html> +<meta charset=utf-8> +<title>localStorage: partitioned storage test</title> +<meta name=help href="https://privacycg.github.io/storage-partitioning/"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<iframe id="shared-iframe" src="http://{{host}}:{{ports[http][0]}}/webstorage/resources/localstorage-about-blank-partitioned-iframe.html"></iframe> +<body> +<script> +// Here's the set-up for this test: +// Step 1. (window) set up listeners for main window. +// Step 2. (window) set up load listener for same-site iframe. +// Step 3. (same-site iframe) loads, send it a message to createOrGet a "userID". +// Step 4. (same-site iframe) receives the message, creates the "userID". +// Step 5. (window) receives "storage got set" message from same-site iframe. +// Step 6. (window) opens cross-site window w/ shared (same-site to us currently) iframe. +// Step 7. (cross-site iframe) loads, sends back the userID key from the iframe. +// Step 8. (window) asserts that the IDs should be different, as they should have a different StorageKey. +const altOrigin = "http://{{hosts[alt][]}}:{{ports[http][0]}}"; + +async_test(t => { + let crossSiteWindow; + let crossSiteID; + let sameSiteID; + const iframe = document.getElementById("shared-iframe"); + + iframe.addEventListener("load", t.step_func(e => { + const payload = { + command: "create ID", + key: "userID", + }; + iframe.contentWindow.postMessage(payload, iframe.origin); + }), {once: true}); + + window.addEventListener("message", t.step_func(e => { + if (e.data.message === "ID created") { + sameSiteID = e.data.userID; + assert_true(typeof sameSiteID === "string"); + + if (location.origin !== altOrigin) { + crossSiteWindow = window.open(`${altOrigin}/webstorage/localstorage-basic-partitioned.tentative.sub.html`, "", "noopener=false"); + t.add_cleanup(() => crossSiteWindow.close()); + } + } + + if (e.data.message === "cross-site window iframe loaded") { + crossSiteID = e.data.userID; + t.step(() => { + assert_true(typeof crossSiteID === "string"); + assert_true(sameSiteID !== crossSiteID, "IDs pulled from two partitioned iframes are different.") + }); + + // clean up after ourselves. + iframe.contentWindow.localStorage.clear(); + crossSiteWindow.postMessage({command: "clearStorage"}, altOrigin); + t.done(); + }; + })); +}, "Simple test for partitioned localStorage"); +</script> +</body> diff --git a/testing/web-platform/tests/webstorage/localstorage-cross-origin-iframe.tentative.https.window.js b/testing/web-platform/tests/webstorage/localstorage-cross-origin-iframe.tentative.https.window.js new file mode 100644 index 0000000000..39812f27a0 --- /dev/null +++ b/testing/web-platform/tests/webstorage/localstorage-cross-origin-iframe.tentative.https.window.js @@ -0,0 +1,27 @@ +// META: script=/common/get-host-info.sub.js +// META: script=/common/utils.js +// META: script=/common/dispatcher/dispatcher.js +// META: script=/html/cross-origin-embedder-policy/credentialless/resources/common.js +// META: script=/html/anonymous-iframe/resources/common.js + +promise_test(async test => { + const same_origin= get_host_info().HTTPS_ORIGIN; + const cross_origin = get_host_info().HTTPS_REMOTE_ORIGIN; + const reply_token = token(); + + for(iframe of [ + newIframe(same_origin), + newIframe(cross_origin), + ]) { + send(iframe, ` + try { + let c = window.localStorage; + send("${reply_token}","OK"); + } catch (exception) { + send("${reply_token}","ERROR"); + } + `); + } + assert_equals(await receive(reply_token), "OK"); + assert_equals(await receive(reply_token), "OK"); + }, "LocalStorage should be accessible on both same_origin and cross_origin iframes");
\ No newline at end of file diff --git a/testing/web-platform/tests/webstorage/missing_arguments.window.js b/testing/web-platform/tests/webstorage/missing_arguments.window.js new file mode 100644 index 0000000000..2e41a22ec7 --- /dev/null +++ b/testing/web-platform/tests/webstorage/missing_arguments.window.js @@ -0,0 +1,17 @@ +var tests = [ + function() { localStorage.key(); }, + function() { localStorage.getItem(); }, + function() { localStorage.setItem(); }, + function() { localStorage.setItem("a"); }, + function() { localStorage.removeItem(); }, + function() { sessionStorage.key(); }, + function() { sessionStorage.getItem(); }, + function() { sessionStorage.setItem(); }, + function() { sessionStorage.setItem("a"); }, + function() { sessionStorage.removeItem(); }, +]; +tests.forEach(function(fun) { + test(function() { + assert_throws_js(TypeError, fun); + }, "Should throw TypeError for " + format_value(fun) + "."); +}); diff --git a/testing/web-platform/tests/webstorage/resources/event_basic.html b/testing/web-platform/tests/webstorage/resources/event_basic.html new file mode 100644 index 0000000000..5933b40eeb --- /dev/null +++ b/testing/web-platform/tests/webstorage/resources/event_basic.html @@ -0,0 +1,16 @@ +<!DOCTYPE HTML> +<html> +<head> +<script> +function handleStorageEvent(e) { + if (window.sessionStorage === e.storageArea) + e.storageAreaString = "sessionStorage"; + else if (window.localStorage === e.storageArea) + e.storageAreaString = "localStorage"; + window.parent.storageEventList.push(e); +} +</script> +</head> +<body onstorage="handleStorageEvent(event);"> +</body> +</html> diff --git a/testing/web-platform/tests/webstorage/resources/event_body_handler.html b/testing/web-platform/tests/webstorage/resources/event_body_handler.html new file mode 100644 index 0000000000..11d8ec9447 --- /dev/null +++ b/testing/web-platform/tests/webstorage/resources/event_body_handler.html @@ -0,0 +1,14 @@ +<!DOCTYPE HTML> +<html> +<head> +<script> + +function handleStorageEvent(e) { + window.parent.storageEventList.push(e); +} + +</script> +</head> +<body onstorage="handleStorageEvent(event);"> +</body> +</html> diff --git a/testing/web-platform/tests/webstorage/resources/event_setattribute_handler.html b/testing/web-platform/tests/webstorage/resources/event_setattribute_handler.html new file mode 100644 index 0000000000..b9e2f04021 --- /dev/null +++ b/testing/web-platform/tests/webstorage/resources/event_setattribute_handler.html @@ -0,0 +1,15 @@ +<!DOCTYPE HTML> +<html> +<head></head> +<body> +<script> + +function handleStorageEvent(e) { + window.parent.storageEventList.push(e); +} + +document.body.setAttribute("onstorage", "handleStorageEvent(event);"); + +</script> +</body> +</html> diff --git a/testing/web-platform/tests/webstorage/resources/local_change_item_iframe.html b/testing/web-platform/tests/webstorage/resources/local_change_item_iframe.html new file mode 100644 index 0000000000..17be8fb26e --- /dev/null +++ b/testing/web-platform/tests/webstorage/resources/local_change_item_iframe.html @@ -0,0 +1,18 @@ +<!DOCTYPE HTML> +<html> + <body> + <script> + if (('localStorage' in window) && window.localStorage !== null){ + try { + localStorage.setItem("name", "user1"); + localStorage.setItem("name", "user2"); + } catch (e) { + parent.fail("setItem method is failed."); + } + localStorage.clear(); + } else { + parent.fail("localStorage is not supported."); + } + </script> + </body> +</html> diff --git a/testing/web-platform/tests/webstorage/resources/local_set_item_clear_iframe.html b/testing/web-platform/tests/webstorage/resources/local_set_item_clear_iframe.html new file mode 100644 index 0000000000..742b7dad1a --- /dev/null +++ b/testing/web-platform/tests/webstorage/resources/local_set_item_clear_iframe.html @@ -0,0 +1,17 @@ +<!DOCTYPE HTML> +<html> + <body> + <script> + if (('localStorage' in window) && window.localStorage !== null){ + try { + localStorage.setItem("name", "user1"); + } catch (e) { + parent.fail("setItem method is failed."); + } + localStorage.clear(); + } else { + parent.fail("localStorage is not supported."); + } + </script> + </body> +</html> diff --git a/testing/web-platform/tests/webstorage/resources/local_set_item_iframe.html b/testing/web-platform/tests/webstorage/resources/local_set_item_iframe.html new file mode 100644 index 0000000000..0693824e5d --- /dev/null +++ b/testing/web-platform/tests/webstorage/resources/local_set_item_iframe.html @@ -0,0 +1,16 @@ +<!DOCTYPE HTML> +<html> + <body> + <script> + if (('localStorage' in window) && window.localStorage !== null){ + try { + localStorage.setItem("name", "user1"); + } catch (e) { + parent.fail("setItem method is failed."); + } + } else { + parent.fail("localStorage is not supported."); + } + </script> + </body> +</html> diff --git a/testing/web-platform/tests/webstorage/resources/local_set_item_remove_iframe.html b/testing/web-platform/tests/webstorage/resources/local_set_item_remove_iframe.html new file mode 100644 index 0000000000..7451594c89 --- /dev/null +++ b/testing/web-platform/tests/webstorage/resources/local_set_item_remove_iframe.html @@ -0,0 +1,11 @@ +<!DOCTYPE HTML> +<html> + <body> + <script> + parent.step(function() { + localStorage.setItem("name", "user1"); + localStorage.removeItem('name'); + }); + </script> + </body> +</html> diff --git a/testing/web-platform/tests/webstorage/resources/localstorage-about-blank-partitioned-iframe.html b/testing/web-platform/tests/webstorage/resources/localstorage-about-blank-partitioned-iframe.html new file mode 100644 index 0000000000..5cb2c4f7e2 --- /dev/null +++ b/testing/web-platform/tests/webstorage/resources/localstorage-about-blank-partitioned-iframe.html @@ -0,0 +1,41 @@ +<!doctype html> +<meta charset="utf-8"> +<script> +function getOrCreateID(key) { + if (!localStorage.getItem(key)) { + const newID = +new Date() + "-" + Math.random(); + localStorage.setItem(key, newID); + } + return localStorage.getItem(key); +} + +window.addEventListener("load", () => { + // if we have an opener, we know that we are loaded inside a cross-site + // iframe (because we opened it ourselves). + if (parent.opener) { + const payload = { + message: "cross-site window iframe loaded", + userID: getOrCreateID("userID"), + } + parent.opener.postMessage(payload, parent.opener.origin); + } +}); + +window.addEventListener("message", (e) => { + if (e.data.command == "create ID") { + getOrCreateID(e.data.key); + + // storage is set, call back to window. + const payload = { + message: "ID created", + userID: localStorage.getItem("userID"), + } + + e.source.postMessage(payload, e.source.origin); + } + + if (e.data.command == "clearStorage") { + localStorage.clear(); + } +}); +</script> diff --git a/testing/web-platform/tests/webstorage/resources/localstorage-about-blank-partitioned-win-open.html b/testing/web-platform/tests/webstorage/resources/localstorage-about-blank-partitioned-win-open.html new file mode 100644 index 0000000000..90d3a4309e --- /dev/null +++ b/testing/web-platform/tests/webstorage/resources/localstorage-about-blank-partitioned-win-open.html @@ -0,0 +1,37 @@ +<!doctype html> +<meta charset="utf-8"> +<script src="./partitioning-utils.js"></script> +<script> +window.addEventListener("load", () => { + localStorage.clear(); + + const userID = getOrCreateID("userID4"); + const payload = { + message: "window loaded", + userID, + } + + let win = window.opener ? window.opener : window.parent; + win.postMessage(payload, "*"); +}); + +window.addEventListener("message", e => { + let win = window.opener ? parent.window.opener : window.parent; + + if (e.data.command == "open about:blank window") { + window.blankWindow = window.open("about:blank"); + const payload = { + message: "about:blank frame ID", + userID: window.blankWindow?.localStorage["userID4"], + } + + let win = window.opener ? parent.window.opener : window.parent; + win.postMessage(payload, "*"); + } + + if (e.data.command == "close about:blank window") { + window.blankWindow.close(); + win.postMessage({message: "about:blank window closed"}, "*"); + } +}); +</script> diff --git a/testing/web-platform/tests/webstorage/resources/partitioning-utils.js b/testing/web-platform/tests/webstorage/resources/partitioning-utils.js new file mode 100644 index 0000000000..9d9e0b8ac5 --- /dev/null +++ b/testing/web-platform/tests/webstorage/resources/partitioning-utils.js @@ -0,0 +1,20 @@ +function getOrCreateID(key) { + if (!localStorage.getItem(key)) { + const newID = +new Date() + "-" + Math.random(); + localStorage.setItem(key, newID); + } + return localStorage.getItem(key); +} + +function addIframePromise(url) { + return new Promise(resolve => { + const iframe = document.createElement("iframe"); + iframe.style.display = "none"; + iframe.src = url; + iframe.addEventListener("load", (e) => { + resolve(iframe); + }, {once: true}); + + document.body.appendChild(iframe); + }); +} diff --git a/testing/web-platform/tests/webstorage/resources/sessionStorage-about-blank-partitioned-iframe.html b/testing/web-platform/tests/webstorage/resources/sessionStorage-about-blank-partitioned-iframe.html new file mode 100644 index 0000000000..dd530a7c22 --- /dev/null +++ b/testing/web-platform/tests/webstorage/resources/sessionStorage-about-blank-partitioned-iframe.html @@ -0,0 +1,44 @@ +<!doctype html> +<meta charset="utf-8"> +<script> + +function getOrCreateID(key) { + if (!sessionStorage.getItem(key)) { + const newID = new Date() + "-" + Math.random(); + sessionStorage.setItem(key, newID); + } + return sessionStorage.getItem(key); +} + +window.addEventListener("load", () => { + // In this testing set-up, only cross-site iframes will have an opener. + if (parent.opener) { + const payload = { + message: "cross-site window iframe loaded", + userID: getOrCreateID("userID"), + } + // Once the cross-site iframe has loaded, we send a message back to + // the main window with the ID from sessionStorage. + parent.opener.postMessage(payload, parent.opener.origin); + } +}); + +window.addEventListener("message", (e) => { + if (e.data.command == "create ID") { + // e.data.key is equivalent to "userID" + getOrCreateID(e.data.key); + + const payload = { + message: "ID created", + userID: sessionStorage.getItem("userID"), + } + // Return the ID from sessionStorage to the main window. + e.source.postMessage(payload, e.source.origin); + } + + // Additional functionality for clean-up at the end of the test. + if (e.data.command == "clearStorage") { + sessionStorage.clear(); + } +}); +</script> diff --git a/testing/web-platform/tests/webstorage/resources/session_change_item_iframe.html b/testing/web-platform/tests/webstorage/resources/session_change_item_iframe.html new file mode 100644 index 0000000000..1e1867e51e --- /dev/null +++ b/testing/web-platform/tests/webstorage/resources/session_change_item_iframe.html @@ -0,0 +1,18 @@ +<!DOCTYPE HTML> +<html> + <body> + <script> + if (('sessionStorage' in window) && window.sessionStorage !== null){ + try { + sessionStorage.setItem("name", "user1"); + sessionStorage.setItem("name", "user2"); + } catch (e) { + parent.fail("setItem method is failed."); + } + sessionStorage.clear(); + } else { + parent.fail("sessionStorage is not supported."); + } + </script> + </body> +</html> diff --git a/testing/web-platform/tests/webstorage/resources/session_set_item_clear_iframe.html b/testing/web-platform/tests/webstorage/resources/session_set_item_clear_iframe.html new file mode 100644 index 0000000000..7deaa9b17c --- /dev/null +++ b/testing/web-platform/tests/webstorage/resources/session_set_item_clear_iframe.html @@ -0,0 +1,17 @@ +<!DOCTYPE HTML> +<html> + <body> + <script> + if (('sessionStorage' in window) && window.sessionStorage !== null){ + try { + sessionStorage.setItem('name', 'user1'); + } catch (e) { + parent.fail('setItem method is failed.'); + } + sessionStorage.clear(); + } else { + parent.fail('sessionStorage is not supported.'); + } + </script> + </body> +</html> diff --git a/testing/web-platform/tests/webstorage/resources/session_set_item_iframe.html b/testing/web-platform/tests/webstorage/resources/session_set_item_iframe.html new file mode 100644 index 0000000000..de844cca45 --- /dev/null +++ b/testing/web-platform/tests/webstorage/resources/session_set_item_iframe.html @@ -0,0 +1,16 @@ +<!DOCTYPE HTML> +<html> + <body> + <script> + if (('sessionStorage' in window) && window.sessionStorage !== null){ + try { + sessionStorage.setItem('name', 'user1'); + } catch (e) { + parent.fail('setItem method is failed.'); + } + } else { + parent.fail('sessionStorage is not supported.'); + } + </script> + </body> +</html> diff --git a/testing/web-platform/tests/webstorage/resources/session_set_item_remove_iframe.html b/testing/web-platform/tests/webstorage/resources/session_set_item_remove_iframe.html new file mode 100644 index 0000000000..60303e70f5 --- /dev/null +++ b/testing/web-platform/tests/webstorage/resources/session_set_item_remove_iframe.html @@ -0,0 +1,11 @@ +<!DOCTYPE HTML> +<html> + <body> + <script> + parent.step(function() { + sessionStorage.setItem("name", "user1"); + sessionStorage.removeItem('name'); + }); + </script> + </body> +</html> diff --git a/testing/web-platform/tests/webstorage/resources/storage_local_window_open_second.html b/testing/web-platform/tests/webstorage/resources/storage_local_window_open_second.html new file mode 100644 index 0000000000..3c8405adcf --- /dev/null +++ b/testing/web-platform/tests/webstorage/resources/storage_local_window_open_second.html @@ -0,0 +1,36 @@ +<!DOCTYPE HTML> +<html> +<head> +<title>WebStorage Test: localStorage - second page</title> +</head> +<body> +<script> + +var storage = window.localStorage; + +var assertions = []; + +assertions.push({ + actual: storage.getItem("FOO"), + expected: "BAR", + message: "storage.getItem('FOO')" +}); + +storage.setItem("FOO", "BAR-NEWWINDOW"); + +assertions.push({ + actual: storage.getItem("FOO"), + expected: "BAR-NEWWINDOW", + message: "value for FOO after changing" +}); +assertions.push({ + actual: window.opener.localStorage.getItem("FOO"), + expected: "BAR-NEWWINDOW", + message: "value for FOO in my opening window" +}); + +window.opener.postMessage(assertions, '*'); + +</script> +</body> +</html> diff --git a/testing/web-platform/tests/webstorage/resources/storage_session_window_noopener_second.html b/testing/web-platform/tests/webstorage/resources/storage_session_window_noopener_second.html new file mode 100644 index 0000000000..7e477375ae --- /dev/null +++ b/testing/web-platform/tests/webstorage/resources/storage_session_window_noopener_second.html @@ -0,0 +1,34 @@ +<!DOCTYPE HTML> +<html> +<head> +<title>WebStorage Test: sessionStorage - second page</title> +</head> +<body> +<script> + +var storage = window.sessionStorage; + +var assertions = []; + +assertions.push({ + actual: storage.getItem("FOO"), + expected: null, + message: "storage.getItem('FOO')" +}); + +storage.setItem("FOO", "BAR-NEWWINDOW"); + +assertions.push({ + actual: storage.getItem("FOO"), + expected: "BAR-NEWWINDOW", + message: "value for FOO after changing" +}); + +let channel = new BroadcastChannel('storage_session_window_noopener'); +channel.postMessage(assertions, '*'); + +window.close(); + +</script> +</body> +</html> diff --git a/testing/web-platform/tests/webstorage/resources/storage_session_window_open_second.html b/testing/web-platform/tests/webstorage/resources/storage_session_window_open_second.html new file mode 100644 index 0000000000..2eeff0b865 --- /dev/null +++ b/testing/web-platform/tests/webstorage/resources/storage_session_window_open_second.html @@ -0,0 +1,41 @@ +<!DOCTYPE HTML> +<html> +<head> +<title>WebStorage Test: sessionStorage - second page</title> +</head> +<body> +<script> + +var storage = window.sessionStorage; + +var assertions = []; + +assertions.push({ + actual: storage.getItem("FOO"), + expected: "BAR", + message: "storage.getItem('FOO')" +}); + +storage.setItem("FOO", "BAR-NEWWINDOW"); + +assertions.push({ + actual: storage.getItem("FOO"), + expected: "BAR-NEWWINDOW", + message: "value for FOO after changing" +}); +assertions.push({ + actual: window.opener.sessionStorage.getItem("FOO"), + expected: "BAR", + message: "value for FOO in my opening window" +}); +assertions.push({ + actual: storage.getItem("BAZ"), + expected: null, + message: "value for BAZ set after window.open(), is not set in new window" +}); + +window.opener.postMessage(assertions, '*'); + +</script> +</body> +</html> diff --git a/testing/web-platform/tests/webstorage/sessionStorage-basic-partitioned.tentative.sub.html b/testing/web-platform/tests/webstorage/sessionStorage-basic-partitioned.tentative.sub.html new file mode 100644 index 0000000000..30575bfaf1 --- /dev/null +++ b/testing/web-platform/tests/webstorage/sessionStorage-basic-partitioned.tentative.sub.html @@ -0,0 +1,73 @@ +<!doctype html> +<meta charset=utf-8> +<title>sessionStorage: partitioned storage test</title> +<meta name=help href="https://privacycg.github.io/storage-partitioning/"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<iframe id="shared-iframe" src="http://{{host}}:{{ports[http][0]}}/webstorage/resources/sessionStorage-about-blank-partitioned-iframe.html"></iframe> +<body> +<script> +// Here's the set-up for this test: +// Step 1. (main window) set up messaging and same-site iframe load listeners. +// Step 2. (same-site iframe) loads, requests sessionStorage for "userID". +// Step 3. (same-site iframe) receives the message, gets or allocates sessionStorage, +// and returns the generated ID to the main frame. +// Step 4. (main window) receives "storage got set" message from same-site iframe. +// Step 5. (main window) opens a new cross-site window with the shared-iframe inside. +// Step 6. (cross-site iframe) loads, requests sessionStorage for "userID", gets or +// allocates that sessionStorage, and returns the generated ID to the main frame. +// Step 7. (main window) asserts that the generated IDs should be different, as +// they should have a different StorageKey. +const altOrigin = "http://{{hosts[alt][]}}:{{ports[http][0]}}"; + +async_test(t => { + let crossSiteWindow; + let crossSiteID; + let sameSiteID; + // Retrieve the iframe we created in the HTML above. + const iframe = document.getElementById("shared-iframe"); + + // Once the iframe loads, we request sessionStorage. + iframe.addEventListener("load", t.step_func(e => { + const payload = { + command: "create ID", + key: "userID", + }; + iframe.contentWindow.postMessage(payload, iframe.origin); + }), {once: true}); + + window.addEventListener("message", t.step_func(e => { + // Once we get or allocate the sessionStorage, we expect the iframe + // to message us back with the generated ID. + if (e.data.message === "ID created") { + sameSiteID = e.data.userID; + assert_true(typeof sameSiteID === "string"); + + // Now that same-site storage has been secured, we need to open a + // new cross-site window that contains our shared-iframe to repeat + // the process in a cross-site environment. + if (location.origin !== altOrigin) { + crossSiteWindow = window.open(`${altOrigin}/webstorage/sessionStorage-basic-partitioned.tentative.sub.html`, "", "noopener=false"); + t.add_cleanup(() => crossSiteWindow.close()); + } + } + + // We expect that once the cross-site iframe requests sessionStorage, + // it will message us back with the generated ID. + if (e.data.message === "cross-site window iframe loaded") { + crossSiteID = e.data.userID; + t.step(() => { + // Same and cross-site iframes should have different generated IDs. + assert_true(typeof crossSiteID === "string"); + assert_true(sameSiteID !== crossSiteID, "IDs pulled from two partitioned iframes are different.") + }); + + // Clear storage state to clean up after the test. + iframe.contentWindow.sessionStorage.clear(); + crossSiteWindow.postMessage({command: "clearStorage"}, altOrigin); + t.done(); + }; + })); +}, "Simple test for partitioned sessionStorage"); +</script> +</body> diff --git a/testing/web-platform/tests/webstorage/set.window.js b/testing/web-platform/tests/webstorage/set.window.js new file mode 100644 index 0000000000..8e671d2ded --- /dev/null +++ b/testing/web-platform/tests/webstorage/set.window.js @@ -0,0 +1,102 @@ +["localStorage", "sessionStorage"].forEach(function(name) { + [9, "x"].forEach(function(key) { + test(function() { + var expected = "value for " + this.name; + var value = expected; + + var storage = window[name]; + storage.clear(); + + assert_equals(storage[key], undefined); + assert_equals(storage.getItem(key), null); + assert_equals(storage[key] = value, value); + assert_equals(storage[key], expected); + assert_equals(storage.getItem(key), expected); + }, "Setting property for key " + key + " on " + name); + + test(function() { + var expected = "value for " + this.name; + var value = { + toString: function() { return expected; } + }; + + var storage = window[name]; + storage.clear(); + + assert_equals(storage[key], undefined); + assert_equals(storage.getItem(key), null); + assert_equals(storage[key] = value, value); + assert_equals(storage[key], expected); + assert_equals(storage.getItem(key), expected); + }, "Setting property with toString for key " + key + " on " + name); + + test(function() { + var proto = "proto for " + this.name; + Storage.prototype[key] = proto; + this.add_cleanup(function() { delete Storage.prototype[key]; }); + + var value = "value for " + this.name; + + var storage = window[name]; + storage.clear(); + + assert_equals(storage[key], proto); + assert_equals(storage.getItem(key), null); + assert_equals(storage[key] = value, value); + // Hidden because no [LegacyOverrideBuiltIns]. + assert_equals(storage[key], proto); + assert_equals(Object.getOwnPropertyDescriptor(storage, key), undefined); + assert_equals(storage.getItem(key), value); + }, "Setting property for key " + key + " on " + name + " with data property on prototype"); + + test(function() { + var proto = "proto for " + this.name; + Storage.prototype[key] = proto; + this.add_cleanup(function() { delete Storage.prototype[key]; }); + + var value = "value for " + this.name; + var existing = "existing for " + this.name; + + var storage = window[name]; + storage.clear(); + + storage.setItem(key, existing); + + // Hidden because no [LegacyOverrideBuiltIns]. + assert_equals(storage[key], proto); + assert_equals(Object.getOwnPropertyDescriptor(storage, key), undefined); + assert_equals(storage.getItem(key), existing); + assert_equals(storage[key] = value, value); + assert_equals(storage[key], proto); + assert_equals(Object.getOwnPropertyDescriptor(storage, key), undefined); + assert_equals(storage.getItem(key), value); + }, "Setting property for key " + key + " on " + name + " with data property on prototype and existing item"); + + test(function() { + var storage = window[name]; + storage.clear(); + + var proto = "proto getter for " + this.name; + Object.defineProperty(Storage.prototype, key, { + "get": function() { return proto; }, + "set": this.unreached_func("Should not call [[Set]] on prototype"), + "configurable": true, + }); + this.add_cleanup(function() { + delete Storage.prototype[key]; + delete storage[key]; + assert_false(key in storage); + }); + + var value = "value for " + this.name; + + assert_equals(storage[key], proto); + assert_equals(storage.getItem(key), null); + assert_equals(storage[key] = value, value); + // Property is hidden because no [LegacyOverrideBuiltIns]. + assert_equals(storage[key], proto); + assert_equals(Object.getOwnPropertyDescriptor(storage, key), undefined); + assert_equals(storage.getItem(key), value); + }, "Setting property for key " + key + " on " + name + " with accessor property on prototype"); + }); +}); diff --git a/testing/web-platform/tests/webstorage/storage_builtins.window.js b/testing/web-platform/tests/webstorage/storage_builtins.window.js new file mode 100644 index 0000000000..72bb90db21 --- /dev/null +++ b/testing/web-platform/tests/webstorage/storage_builtins.window.js @@ -0,0 +1,16 @@ +["localStorage", "sessionStorage"].forEach(function(name) { + test(function() { + var storage = window[name]; + storage.clear(); + assert_equals(storage.length, 0, "storage.length"); + + var builtins = ["key", "getItem", "setItem", "removeItem", "clear"]; + var origBuiltins = builtins.map(function(b) { return Storage.prototype[b]; }); + assert_array_equals(builtins.map(function(b) { return storage[b]; }), origBuiltins, "a"); + builtins.forEach(function(b) { storage[b] = b; }); + assert_array_equals(builtins.map(function(b) { return storage[b]; }), origBuiltins, "b"); + assert_array_equals(builtins.map(function(b) { return storage.getItem(b); }), builtins, "c"); + + assert_equals(storage.length, builtins.length, "storage.length"); + }, "Builtins in " + name); +}); diff --git a/testing/web-platform/tests/webstorage/storage_clear.window.js b/testing/web-platform/tests/webstorage/storage_clear.window.js new file mode 100644 index 0000000000..6f42bf85f7 --- /dev/null +++ b/testing/web-platform/tests/webstorage/storage_clear.window.js @@ -0,0 +1,16 @@ +["localStorage", "sessionStorage"].forEach(function(name) { + test(function() { + var storage = window[name]; + storage.clear(); + + storage.setItem("name", "user1"); + assert_equals(storage.getItem("name"), "user1"); + assert_equals(storage.name, "user1"); + assert_equals(storage.length, 1); + + storage.clear(); + assert_equals(storage.getItem("name"), null, "storage.getItem('name')"); + assert_equals(storage.name, undefined, "storage.name"); + assert_equals(storage.length, 0, "storage.length"); + }, "Clear in " + name); +}); diff --git a/testing/web-platform/tests/webstorage/storage_enumerate.window.js b/testing/web-platform/tests/webstorage/storage_enumerate.window.js new file mode 100644 index 0000000000..fcc71e1c9e --- /dev/null +++ b/testing/web-platform/tests/webstorage/storage_enumerate.window.js @@ -0,0 +1,55 @@ +["localStorage", "sessionStorage"].forEach(function(name) { + test(function() { + assert_true(name in window, name + " exist"); + + var storage = window[name]; + storage.clear(); + + Storage.prototype.prototypeTestKey = "prototypeTestValue"; + storage.foo = "bar"; + storage.fu = "baz"; + storage.batman = "bin suparman"; + storage.bar = "foo"; + storage.alpha = "beta"; + storage.zeta = "gamma"; + + const enumeratedArray = Object.keys(storage); + enumeratedArray.sort(); // Storage order is implementation-defined. + + const expectArray = ["alpha", "bar", "batman", "foo", "fu", "zeta"]; + assert_array_equals(enumeratedArray, expectArray); + + // 'prototypeTestKey' is not an actual storage key, it is just a + // property set on Storage's prototype object. + assert_equals(storage.length, 6); + assert_equals(storage.getItem("prototypeTestKey"), null); + assert_equals(storage.prototypeTestKey, "prototypeTestValue"); + }, name + ": enumerate a Storage object and get only the keys as a result and the built-in properties of the Storage object should be ignored"); + + test(function() { + const storage = window[name]; + storage.clear(); + + storage.setItem("foo", "bar"); + storage.baz = "quux"; + storage.setItem(0, "alpha"); + storage[42] = "beta"; + + for (let prop in storage) { + if (!storage.hasOwnProperty(prop)) + continue; + const desc = Object.getOwnPropertyDescriptor(storage, prop); + assert_true(desc.configurable); + assert_true(desc.enumerable); + assert_true(desc.writable); + } + + const keys = Object.keys(storage); + keys.sort(); // Storage order is implementation-defined. + assert_array_equals(keys, ["0", "42", "baz", "foo"]); + + const values = Object.values(storage); + values.sort(); // Storage order is implementation-defined. + assert_array_equals(values, ["alpha", "bar", "beta", "quux"]); + }, name + ": test enumeration of numeric and non-numeric keys"); +}); diff --git a/testing/web-platform/tests/webstorage/storage_functions_not_overwritten.window.js b/testing/web-platform/tests/webstorage/storage_functions_not_overwritten.window.js new file mode 100644 index 0000000000..693743de90 --- /dev/null +++ b/testing/web-platform/tests/webstorage/storage_functions_not_overwritten.window.js @@ -0,0 +1,37 @@ +["localStorage", "sessionStorage"].forEach(function(name) { + test(function() { + var storage = window[name]; + storage.clear(); + + runTest(); + function doWedgeThySelf() { + storage.setItem("clear", "almost"); + storage.setItem("key", "too"); + storage.setItem("getItem", "funny"); + storage.setItem("removeItem", "to"); + storage.setItem("length", "be"); + storage.setItem("setItem", "true"); + } + + function runTest() { + doWedgeThySelf(); + + assert_equals(storage.getItem('clear'), "almost"); + assert_equals(storage.getItem('key'), "too"); + assert_equals(storage.getItem('getItem'), "funny"); + assert_equals(storage.getItem('removeItem'), "to"); + assert_equals(storage.getItem('length'), "be"); + assert_equals(storage.getItem('setItem'), "true"); + + // Test to see if an exception is thrown for any of the built in + // functions. + storage.setItem("test", "123"); + storage.key(0); + storage.getItem("test"); + storage.removeItem("test"); + storage.clear(); + assert_equals(storage.length, 0); + } + + }, name + " should be not rendered unusable by setting a key with the same name as a storage function such that the function is hidden"); +}); diff --git a/testing/web-platform/tests/webstorage/storage_getitem.window.js b/testing/web-platform/tests/webstorage/storage_getitem.window.js new file mode 100644 index 0000000000..8a5896836d --- /dev/null +++ b/testing/web-platform/tests/webstorage/storage_getitem.window.js @@ -0,0 +1,34 @@ +["localStorage", "sessionStorage"].forEach(function(name) { + test(function() { + var storage = window[name]; + storage.clear(); + storage.setItem("name", "x"); + storage.setItem("undefined", "foo"); + storage.setItem("null", "bar"); + storage.setItem("", "baz"); + + test(function() { + assert_equals(storage.length, 4); + }, "All items should be added to " + name + "."); + + test(function() { + assert_equals(storage["unknown"], undefined, "storage['unknown']") + assert_equals(storage["name"], "x", "storage['name']") + assert_equals(storage["undefined"], "foo", "storage['undefined']") + assert_equals(storage["null"], "bar", "storage['null']") + assert_equals(storage[undefined], "foo", "storage[undefined]") + assert_equals(storage[null], "bar", "storage[null]") + assert_equals(storage[""], "baz", "storage['']") + }, "Named access to " + name + " should be correct"); + + test(function() { + assert_equals(storage.getItem("unknown"), null, "storage.getItem('unknown')") + assert_equals(storage.getItem("name"), "x", "storage.getItem('name')") + assert_equals(storage.getItem("undefined"), "foo", "storage.getItem('undefined')") + assert_equals(storage.getItem("null"), "bar", "storage.getItem('null')") + assert_equals(storage.getItem(undefined), "foo", "storage.getItem(undefined)") + assert_equals(storage.getItem(null), "bar", "storage.getItem(null)") + assert_equals(storage.getItem(""), "baz", "storage.getItem('')") + }, name + ".getItem should be correct") + }, "Get value by getIten(key) and named access in " + name + "."); +}); diff --git a/testing/web-platform/tests/webstorage/storage_in.window.js b/testing/web-platform/tests/webstorage/storage_in.window.js new file mode 100644 index 0000000000..148285a1eb --- /dev/null +++ b/testing/web-platform/tests/webstorage/storage_in.window.js @@ -0,0 +1,22 @@ +["localStorage", "sessionStorage"].forEach(function(name) { + test(function() { + var storage = window[name]; + storage.clear(); + + assert_false("name" in storage); + storage["name"] = "user1"; + assert_true("name" in storage); + }, "The in operator in " + name + ": property access"); + + test(function() { + var storage = window[name]; + storage.clear(); + + assert_false("name" in storage); + storage.setItem("name", "user1"); + assert_true("name" in storage); + assert_equals(storage.name, "user1"); + storage.removeItem("name"); + assert_false("name" in storage); + }, "The in operator in " + name + ": method access"); +}); diff --git a/testing/web-platform/tests/webstorage/storage_indexing.window.js b/testing/web-platform/tests/webstorage/storage_indexing.window.js new file mode 100644 index 0000000000..685b6b67fb --- /dev/null +++ b/testing/web-platform/tests/webstorage/storage_indexing.window.js @@ -0,0 +1,28 @@ +["localStorage", "sessionStorage"].forEach(function(name) { + test(function() { + var storage = window[name]; + storage.clear(); + storage["name"] = "user1"; + storage["age"] = "42"; + + test(function() { + assert_equals(storage[-1], undefined); + assert_equals(storage[0], undefined); + assert_equals(storage[1], undefined); + assert_equals(storage[2], undefined); + }, "Getting number properties on " + name); + + test(function() { + assert_equals(storage["-1"], undefined); + assert_equals(storage["0"], undefined); + assert_equals(storage["1"], undefined); + assert_equals(storage["2"], undefined); + }, "Getting number-valued string properties on " + name); + + test(function() { + storage.setItem(1, "number"); + assert_equals(storage[1], "number"); + assert_equals(storage["1"], "number"); + }, "Getting existing number-valued properties on " + name); + }, "Indexed getter on " + name); +}); diff --git a/testing/web-platform/tests/webstorage/storage_key.window.js b/testing/web-platform/tests/webstorage/storage_key.window.js new file mode 100644 index 0000000000..723f6563d7 --- /dev/null +++ b/testing/web-platform/tests/webstorage/storage_key.window.js @@ -0,0 +1,51 @@ +["localStorage", "sessionStorage"].forEach(function(name) { + test(function() { + var storage = window[name]; + storage.clear(); + + storage.setItem("name", "user1"); + storage.setItem("age", "20"); + storage.setItem("a", "1"); + storage.setItem("b", "2"); + + var keys = ["name", "age", "a", "b"]; + function doTest(index) { + test(function() { + var key = storage.key(index); + assert_not_equals(key, null); + assert_true(keys.indexOf(key) >= 0, + "Unexpected key " + key + " found."); + }, name + ".key(" + index + ") should return the right thing."); + } + for (var i = 0; i < keys.length; ++i) { + doTest(i); + doTest(i + 0x100000000); + } + + test(function() { + assert_equals(storage.key(-1), null, "storage.key(-1)"); + assert_equals(storage.key(4), null, "storage.key(4)"); + }, name + ".key() should return null for out-of-range arguments."); + }, name + ".key"); + + test(function() { + var get_keys = function(s) { + var keys = []; + for (var i = 0; i < s.length; ++i) { + keys.push(s.key(i)); + } + return keys; + }; + var storage = window[name]; + storage.clear(); + + storage.setItem("name", "user1"); + storage.setItem("age", "20"); + storage.setItem("a", "1"); + storage.setItem("b", "2"); + + var expected_keys = get_keys(storage); + storage.setItem("name", "user2"); + assert_array_equals(get_keys(storage), expected_keys); + }, name + ".key with value changes"); +}); diff --git a/testing/web-platform/tests/webstorage/storage_key_empty_string.window.js b/testing/web-platform/tests/webstorage/storage_key_empty_string.window.js new file mode 100644 index 0000000000..c3d59c42b8 --- /dev/null +++ b/testing/web-platform/tests/webstorage/storage_key_empty_string.window.js @@ -0,0 +1,10 @@ +["localStorage", "sessionStorage"].forEach(function(name) { + test(function () { + var storage = window[name]; + storage.clear(); + + storage.setItem("", "empty string"); + assert_equals(storage.getItem(""), "empty string"); + + }, name + ".key with empty string"); +}); diff --git a/testing/web-platform/tests/webstorage/storage_length.window.js b/testing/web-platform/tests/webstorage/storage_length.window.js new file mode 100644 index 0000000000..9648e48c8d --- /dev/null +++ b/testing/web-platform/tests/webstorage/storage_length.window.js @@ -0,0 +1,23 @@ +["localStorage", "sessionStorage"].forEach(function(name) { + test(function() { + var storage = window[name]; + storage.clear(); + assert_equals(storage.length, 0, "storage.length") + + storage["name"] = "user1"; + storage["age"] = "20"; + + assert_equals(storage.length, 2, "storage.length") + }, name + ".length (method access)"); + + test(function() { + var storage = window[name]; + storage.clear(); + assert_equals(storage.length, 0, "storage.length") + + storage.setItem("name", "user1"); + storage.setItem("age", "20"); + + assert_equals(storage.length, 2, "storage.length") + }, name + ".length (proprty access)"); +}); diff --git a/testing/web-platform/tests/webstorage/storage_local-manual.html b/testing/web-platform/tests/webstorage/storage_local-manual.html new file mode 100644 index 0000000000..d039773b5b --- /dev/null +++ b/testing/web-platform/tests/webstorage/storage_local-manual.html @@ -0,0 +1,40 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>WebStorage Test: local storage</title> +<link rel="author" title="Intel" href="http://www.intel.com"> +<meta name="flags" content="interact"> + +<h2>Description</h2> +<p> + This test validates that store data using Local Storage which means that close the page, and re-open it, the data saved before should be loaded again. +</p> + +<h2>Preconditions</h2> +<ol class="instructions"> + <li> + Click the "Clear" button, refresh the page once and then check if the page shows "You have viewed this page 1 time(s)" + </li> + <li> + Close the page, re-open it and then check if the page still shows "You have viewed this page 2 time(s)" + </li> + <li> + If the above two steps are all true the test case pass, otherwise it fail + </li> +</ol> + +<p> + <h2>You have viewed this page + <span id="count">an untold number of</span> + time(s).</h2> + <button type="button" onclick="javascript:localStorage.pageLoadCount = 0;"><h3>Clear</h3></button> +</p> + +<script> + + if (!localStorage.pageLoadCount) { + localStorage.pageLoadCount = 0; + } + localStorage.pageLoadCount = parseInt(localStorage.pageLoadCount) + 1; + document.getElementById('count').textContent = localStorage.pageLoadCount; + +</script> diff --git a/testing/web-platform/tests/webstorage/storage_local_setitem_quotaexceedederr.window.js b/testing/web-platform/tests/webstorage/storage_local_setitem_quotaexceedederr.window.js new file mode 100644 index 0000000000..fff7d6444a --- /dev/null +++ b/testing/web-platform/tests/webstorage/storage_local_setitem_quotaexceedederr.window.js @@ -0,0 +1,16 @@ +test(function() { + localStorage.clear(); + + var index = 0; + var key = "name"; + var val = "x".repeat(1024); + + assert_throws_dom("QUOTA_EXCEEDED_ERR", function() { + while (true) { + index++; + localStorage.setItem("" + key + index, "" + val + index); + } + }); + + localStorage.clear(); +}, "Throws QuotaExceededError when the quota has been exceeded"); diff --git a/testing/web-platform/tests/webstorage/storage_local_window_open.window.js b/testing/web-platform/tests/webstorage/storage_local_window_open.window.js new file mode 100644 index 0000000000..8c67289400 --- /dev/null +++ b/testing/web-platform/tests/webstorage/storage_local_window_open.window.js @@ -0,0 +1,16 @@ +async_test(function(t) { + + var storage = window.localStorage; + storage.clear(); + + storage.setItem("FOO", "BAR"); + var win = window.open("resources/storage_local_window_open_second.html"); + window.addEventListener('message', t.step_func(function(e) { + e.data.forEach(t.step_func(function(assertion) { + assert_equals(assertion.actual, assertion.expected, assertion.message); + })); + win.close(); + t.done(); + })); + +}, "A new window to make sure there is a copy of the previous window's localStorage, and that they do not diverge after a change"); diff --git a/testing/web-platform/tests/webstorage/storage_removeitem.window.js b/testing/web-platform/tests/webstorage/storage_removeitem.window.js new file mode 100644 index 0000000000..be3174a89b --- /dev/null +++ b/testing/web-platform/tests/webstorage/storage_removeitem.window.js @@ -0,0 +1,44 @@ +["localStorage", "sessionStorage"].forEach(function(name) { + test(function() { + var storage = window[name]; + storage.clear(); + + storage.setItem("name", "user1"); + assert_equals(storage.getItem("name"), "user1"); + + storage.removeItem("name"); + storage.removeItem("unknown"); + assert_equals(storage.getItem("name"), null, "storage.getItem('name')") + }, name + ".removeItem()"); + + test(function() { + var storage = window[name]; + storage.clear(); + + storage.setItem("name", "user1"); + assert_equals(storage.getItem("name"), "user1"); + delete storage["name"]; + delete storage["unknown"]; + assert_equals(storage.getItem("name"), null, "storage.getItem('name')") + }, "delete " + name + "[]"); + + test(function() { + var storage = window[name]; + storage.clear(); + + storage.setItem("null", "test"); + assert_true("null" in storage); + storage.removeItem(null); + assert_false("null" in storage); + }, name + ".removeItem(null)"); + + test(function() { + var storage = window[name]; + storage.clear(); + + storage.setItem("undefined", "test"); + assert_true("undefined" in storage); + storage.removeItem(undefined); + assert_false("undefined" in storage); + }, name + ".removeItem(undefined)"); +}); diff --git a/testing/web-platform/tests/webstorage/storage_session-manual.html b/testing/web-platform/tests/webstorage/storage_session-manual.html new file mode 100644 index 0000000000..c2676af14d --- /dev/null +++ b/testing/web-platform/tests/webstorage/storage_session-manual.html @@ -0,0 +1,39 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>WebStorage Test: session storage</title> +<link rel="author" title="Intel" href="http://www.intel.com"> +<meta name="flags" content="interact"> + +<h2>Description</h2> +<p> + This test validates that store the data using Session Storage which means that even if you close the page, and re-open it, the data saved before should be lost. +</p> + +<ol class="instructions"> + <li> + Click the "Clear" button, refresh the page once and then check if the page shows "You have viewed this page 1 time(s)" + </li> + <li> + Close the page, re-open it and then check if the page still shows "You have viewed this page 1 time(s)" + </li> + <li> + If the above two steps are all true the test case pass, otherwise it fail.<br> + </li> +</ol> + +<p> + <h2>You have viewed this page + <span id="count">an untold number of</span> + time(s).</h2> + <button type="button" onclick="javascript:sessionStorage.pageLoadCount = 0;"><h3>Clear</h3></button> +</p> + +<script> + + if (!sessionStorage.pageLoadCount) { + sessionStorage.pageLoadCount = 0; + } + sessionStorage.pageLoadCount = parseInt(sessionStorage.pageLoadCount) + 1; + document.getElementById('count').textContent = sessionStorage.pageLoadCount; + +</script> diff --git a/testing/web-platform/tests/webstorage/storage_session_setitem_quotaexceedederr.window.js b/testing/web-platform/tests/webstorage/storage_session_setitem_quotaexceedederr.window.js new file mode 100644 index 0000000000..42a895470e --- /dev/null +++ b/testing/web-platform/tests/webstorage/storage_session_setitem_quotaexceedederr.window.js @@ -0,0 +1,16 @@ +test(function() { + sessionStorage.clear(); + + var index = 0; + var key = "name"; + var val = "x".repeat(1024); + + assert_throws_dom("QUOTA_EXCEEDED_ERR", function() { + while (true) { + index++; + sessionStorage.setItem("" + key + index, "" + val + index); + } + }); + + sessionStorage.clear(); +}, "Throws QuotaExceededError when the quota has been exceeded"); diff --git a/testing/web-platform/tests/webstorage/storage_session_window_noopener.window.js b/testing/web-platform/tests/webstorage/storage_session_window_noopener.window.js new file mode 100644 index 0000000000..fe131059d8 --- /dev/null +++ b/testing/web-platform/tests/webstorage/storage_session_window_noopener.window.js @@ -0,0 +1,21 @@ +async_test(function(t) { + + var storage = window.sessionStorage; + storage.clear(); + + storage.setItem("FOO", "BAR"); + + let channel = new BroadcastChannel("storage_session_window_noopener"); + channel.addEventListener("message", t.step_func(function(e) { + e.data.forEach(t.step_func(function(assertion) { + assert_equals(assertion.actual, assertion.expected, assertion.message); + })); + assert_equals(storage.getItem("FOO"), "BAR", "value for FOO in original window"); + t.done(); + })); + + var win = window.open("resources/storage_session_window_noopener_second.html", + "_blank", + "noopener"); + +}, "A new noopener window to make sure there is a not copy of the previous window's sessionStorage"); diff --git a/testing/web-platform/tests/webstorage/storage_session_window_open.window.js b/testing/web-platform/tests/webstorage/storage_session_window_open.window.js new file mode 100644 index 0000000000..83d4447017 --- /dev/null +++ b/testing/web-platform/tests/webstorage/storage_session_window_open.window.js @@ -0,0 +1,17 @@ +async_test(function(t) { + + var storage = window.sessionStorage; + storage.clear(); + + storage.setItem("FOO", "BAR"); + var win = window.open("resources/storage_session_window_open_second.html"); + storage.setItem("BAZ", "QUX"); + window.addEventListener('message', t.step_func(function(e) { + e.data.forEach(t.step_func(function(assertion) { + assert_equals(assertion.actual, assertion.expected, assertion.message); + })); + win.close(); + t.done(); + })); + +}, "A new window to make sure there is a copy of the previous window's sessionStorage, and that they diverge after a change"); diff --git a/testing/web-platform/tests/webstorage/storage_session_window_reopen.window.js b/testing/web-platform/tests/webstorage/storage_session_window_reopen.window.js new file mode 100644 index 0000000000..1ce17d47f1 --- /dev/null +++ b/testing/web-platform/tests/webstorage/storage_session_window_reopen.window.js @@ -0,0 +1,26 @@ +test(function() { + var popup = window.open("", "sessionStorageTestWindow"); + + sessionStorage.setItem("FOO", "BAR"); + + var reopened = window.open("", "sessionStorageTestWindow"); + + assert_equals( + popup, + reopened, + "window.open with the same name should re-open the same window" + ); + + assert_equals( + sessionStorage.getItem("FOO"), + "BAR", + "local sessionStorage is correct" + ); + assert_equals( + popup.sessionStorage.getItem("FOO"), + null, + "popup sessionStorage is correct" + ); + + popup.close(); +}, "ensure that re-opening a named window doesn't copy sessionStorage"); diff --git a/testing/web-platform/tests/webstorage/storage_set_value_enumerate.window.js b/testing/web-platform/tests/webstorage/storage_set_value_enumerate.window.js new file mode 100644 index 0000000000..09a55ad454 --- /dev/null +++ b/testing/web-platform/tests/webstorage/storage_set_value_enumerate.window.js @@ -0,0 +1,21 @@ +var store_list = [ + ["key0", "value0"], + ["key1", "value1"], + ["key2", "value2"] +]; +["localStorage", "sessionStorage"].forEach(function(name) { + test(function () { + var storage = window[name]; + storage.clear(); + + store_list.forEach(function(item) { + storage.setItem(item[0], item[1]); + }); + + for (var i = 0; i < store_list.length; i++) { + var value = storage.getItem("key" + i); + assert_equals(value, "value" + i); + } + }, "enumerate a " + name + " object with the key and get the values"); +}); + diff --git a/testing/web-platform/tests/webstorage/storage_setitem.window.js b/testing/web-platform/tests/webstorage/storage_setitem.window.js new file mode 100644 index 0000000000..97817da1d8 --- /dev/null +++ b/testing/web-platform/tests/webstorage/storage_setitem.window.js @@ -0,0 +1,215 @@ +["localStorage", "sessionStorage"].forEach(function(name) { + var test_error = { name: "test" }; + var interesting_strs = ["\uD7FF", "\uD800", "\uDBFF", "\uDC00", + "\uDFFF", "\uE000", "\uFFFD", "\uFFFE", "\uFFFF", + "\uD83C\uDF4D", "\uD83Ca", "a\uDF4D", + "\uDBFF\uDFFF"]; + + for (var i = 0; i <= 0xFF; i++) { + interesting_strs.push(String.fromCharCode(i)); + } + + test(function() { + var storage = window[name]; + storage.clear(); + + storage.setItem("name", "user1"); + assert_equals(storage.length, 1, "localStorage.setItem") + }, name + ".setItem()"); + + test(function() { + var storage = window[name]; + storage.clear(); + + storage["name"] = "user1"; + assert_true("name" in storage); + assert_equals(storage.length, 1, "storage.length") + assert_equals(storage.getItem("name"), "user1"); + assert_equals(storage["name"], "user1"); + }, name + "[]"); + + test(function() { + var storage = window[name]; + storage.clear(); + + storage["name"] = "user1"; + storage["name"] = "user2"; + assert_true("name" in storage); + assert_equals(storage.length, 1, "storage.length") + assert_equals(storage.getItem("name"), "user2"); + assert_equals(storage["name"], "user2"); + }, name + "[] update"); + + test(function() { + var storage = window[name]; + storage.clear(); + + storage.setItem("age", null); + assert_true("age" in storage); + assert_equals(storage.length, 1, "storage.length") + assert_equals(storage.getItem("age"), "null"); + assert_equals(storage["age"], "null"); + }, name + ".setItem(_, null)"); + + test(function() { + var storage = window[name]; + storage.clear(); + + storage["age"] = null; + assert_true("age" in storage); + assert_equals(storage.length, 1, "storage.length") + assert_equals(storage.getItem("age"), "null"); + assert_equals(storage["age"], "null"); + }, name + "[] = null"); + + test(function() { + var storage = window[name]; + storage.clear(); + + storage.setItem("age", undefined); + assert_true("age" in storage); + assert_equals(storage.length, 1, "storage.length") + assert_equals(storage.getItem("age"), "undefined"); + assert_equals(storage["age"], "undefined"); + }, name + ".setItem(_, undefined)"); + + test(function() { + var storage = window[name]; + storage.clear(); + + storage["age"] = undefined; + assert_true("age" in storage); + assert_equals(storage.length, 1, "storage.length") + assert_equals(storage.getItem("age"), "undefined"); + assert_equals(storage["age"], "undefined"); + }, name + "[] = undefined"); + + test(function() { + var storage = window[name]; + storage.clear(); + + storage.setItem("age", "10"); + assert_throws_exactly(test_error, function() { + storage.setItem("age", + { toString: function() { throw test_error; } }); + }); + assert_true("age" in storage); + assert_equals(storage.length, 1, "storage.length") + assert_equals(storage.getItem("age"), "10"); + assert_equals(storage["age"], "10"); + }, name + ".setItem({ throws })"); + + test(function() { + var storage = window[name]; + storage.clear(); + + storage.setItem("age", "10"); + assert_throws_exactly(test_error, function() { + storage["age"] = + { toString: function() { throw test_error; } }; + }); + assert_true("age" in storage); + assert_equals(storage.length, 1, "storage.length") + assert_equals(storage.getItem("age"), "10"); + assert_equals(storage["age"], "10"); + }, name + "[] = { throws }"); + + test(function() { + var storage = window[name]; + storage.clear(); + + storage.setItem(undefined, "test"); + assert_true("undefined" in storage); + assert_equals(storage.length, 1, "storage.length") + assert_equals(storage.getItem("undefined"), "test"); + assert_equals(storage["undefined"], "test"); + }, name + ".setItem(undefined, _)"); + + test(function() { + var storage = window[name]; + storage.clear(); + + storage[undefined] = "test2"; + assert_true("undefined" in storage); + assert_equals(storage.length, 1, "storage.length") + assert_equals(storage.getItem("undefined"), "test2"); + assert_equals(storage["undefined"], "test2"); + }, name + "[undefined]"); + + test(function() { + var storage = window[name]; + storage.clear(); + + storage.setItem(null, "test"); + assert_true("null" in storage); + assert_equals(storage.length, 1, "storage.length") + assert_equals(storage.getItem("null"), "test"); + assert_equals(storage["null"], "test"); + }, name + ".setItem(null, _)"); + + test(function() { + var storage = window[name]; + storage.clear(); + + storage[null] = "test2"; + assert_true("null" in storage); + assert_equals(storage.length, 1, "storage.length") + assert_equals(storage.getItem("null"), "test2"); + assert_equals(storage["null"], "test2"); + }, name + "[null]"); + + test(function() { + var storage = window[name]; + storage.clear(); + + storage["foo\0bar"] = "user1"; + assert_true("foo\0bar" in storage); + assert_false("foo\0" in storage); + assert_false("foo\0baz" in storage); + assert_false("foo" in storage); + assert_equals(storage.length, 1, "storage.length") + assert_equals(storage.getItem("foo\0bar"), "user1"); + assert_equals(storage.getItem("foo\0"), null); + assert_equals(storage.getItem("foo\0baz"), null); + assert_equals(storage.getItem("foo"), null); + assert_equals(storage["foo\0bar"], "user1"); + assert_equals(storage["foo\0"], undefined); + assert_equals(storage["foo\0baz"], undefined); + assert_equals(storage["foo"], undefined); + }, name + " key containing null"); + + test(function() { + var storage = window[name]; + storage.clear(); + + storage["name"] = "foo\0bar"; + assert_true("name" in storage); + assert_equals(storage.length, 1, "storage.length") + assert_equals(storage.getItem("name"), "foo\0bar"); + assert_equals(storage["name"], "foo\0bar"); + }, name + " value containing null"); + + for (i = 0; i < interesting_strs.length; i++) { + var str = interesting_strs[i]; + test(function() { + var storage = window[name]; + storage.clear(); + + storage[str] = "user1"; + assert_true(str in storage); + assert_equals(storage.length, 1, "storage.length") + assert_equals(storage.getItem(str), "user1"); + assert_equals(storage[str], "user1"); + }, name + "[" + format_value(str) + "]"); + + test(function() { + var storage = window[name]; + storage.clear(); + + storage["name"] = str; + assert_equals(storage.length, 1, "storage.length") + assert_equals(storage.getItem("name"), str); + assert_equals(storage["name"], str); + }, name + "[] = " + format_value(str)); + } +}); diff --git a/testing/web-platform/tests/webstorage/storage_string_conversion.window.js b/testing/web-platform/tests/webstorage/storage_string_conversion.window.js new file mode 100644 index 0000000000..51b07a3a38 --- /dev/null +++ b/testing/web-platform/tests/webstorage/storage_string_conversion.window.js @@ -0,0 +1,32 @@ +["localStorage", "sessionStorage"].forEach(function(name) { + test(function() { + assert_true(name in window, name + " exist"); + + var storage = window[name]; + storage.clear(); + + assert_equals(storage.length, 0); + + storage.a = null; + assert_equals(storage.a, "null"); + storage.b = 0; + assert_equals(storage.b, "0"); + storage.c = function(){}; + assert_equals(storage.c, "function(){}"); + + storage.setItem('d', null); + assert_equals(storage.d, "null"); + storage.setItem('e', 0); + assert_equals(storage.e, "0"); + storage.setItem('f', function(){}); + assert_equals(storage.f, "function(){}"); + + storage['g'] = null; + assert_equals(storage.g, "null"); + storage['h'] = 0; + assert_equals(storage.h, "0"); + storage['i'] = function(){}; + assert_equals(storage.f, "function(){}"); + + }, name + " only stores strings"); +}); diff --git a/testing/web-platform/tests/webstorage/storage_supported_property_names.window.js b/testing/web-platform/tests/webstorage/storage_supported_property_names.window.js new file mode 100644 index 0000000000..08c5d77afc --- /dev/null +++ b/testing/web-platform/tests/webstorage/storage_supported_property_names.window.js @@ -0,0 +1,15 @@ +["localStorage", "sessionStorage"].forEach(function(name) { + test(function() { + var storage = window[name]; + storage.clear(); + + storage["name"] = "user1"; + assert_array_equals(Object.getOwnPropertyNames(storage), ['name']); + }, "Object.getOwnPropertyNames on " + name + " Storage"); + + test(function() { + var storage = window[name]; + storage.clear(); + assert_array_equals(Object.getOwnPropertyNames(storage), []); + }, "Object.getOwnPropertyNames on " + name + " storage with empty collection"); +}); diff --git a/testing/web-platform/tests/webstorage/symbol-props.window.js b/testing/web-platform/tests/webstorage/symbol-props.window.js new file mode 100644 index 0000000000..61dd8f83dc --- /dev/null +++ b/testing/web-platform/tests/webstorage/symbol-props.window.js @@ -0,0 +1,81 @@ +["localStorage", "sessionStorage"].forEach(function(name) { + test(function() { + var key = Symbol(); + + var storage = window[name]; + storage.clear(); + + storage[key] = "test"; + assert_equals(storage[key], "test"); + }, name + ": plain set + get (loose)"); + + test(function() { + "use strict"; + var key = Symbol(); + + var storage = window[name]; + storage.clear(); + + storage[key] = "test"; + assert_equals(storage[key], "test"); + }, name + ": plain set + get (strict)"); + + test(function() { + var key = Symbol(); + + var storage = window[name]; + storage.clear(); + + Object.defineProperty(storage, key, { "value": "test" }); + assert_equals(storage[key], "test"); + }, name + ": defineProperty + get"); + + test(function() { + var key = Symbol(); + + var storage = window[name]; + storage.clear(); + + Object.defineProperty(storage, key, { "value": "test", "configurable": false }); + assert_equals(storage[key], "test"); + var desc = Object.getOwnPropertyDescriptor(storage, key); + assert_true(desc.configurable, "configurable"); + + assert_true(delete storage[key]); + assert_equals(storage[key], undefined); + }, name + ": defineProperty not configurable"); + + test(function() { + var key = Symbol(); + Storage.prototype[key] = "test"; + this.add_cleanup(function() { delete Storage.prototype[key]; }); + + var storage = window[name]; + storage.clear(); + + assert_equals(storage[key], "test"); + var desc = Object.getOwnPropertyDescriptor(storage, key); + assert_equals(desc, undefined); + }, name + ": get with symbol on prototype"); + + test(function() { + var key = Symbol(); + + var storage = window[name]; + storage.clear(); + + storage[key] = "test"; + assert_true(delete storage[key]); + assert_equals(storage[key], undefined); + }, name + ": delete existing property"); + + test(function() { + var key = Symbol(); + + var storage = window[name]; + storage.clear(); + + assert_true(delete storage[key]); + assert_equals(storage[key], undefined); + }, name + ": delete non-existent property"); +}); |