summaryrefslogtreecommitdiffstats
path: root/dom/tests/mochitest/ajax/offline
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--dom/tests/mochitest/ajax/offline/445544.cacheManifest8
-rw-r--r--dom/tests/mochitest/ajax/offline/445544.cacheManifest^headers^2
-rw-r--r--dom/tests/mochitest/ajax/offline/445544_part1.html9
-rw-r--r--dom/tests/mochitest/ajax/offline/445544_part2.html9
-rw-r--r--dom/tests/mochitest/ajax/offline/460353_iframe_nomanifest.html9
-rw-r--r--dom/tests/mochitest/ajax/offline/460353_iframe_ownmanifest.html21
-rw-r--r--dom/tests/mochitest/ajax/offline/460353_iframe_samemanifest.html25
-rw-r--r--dom/tests/mochitest/ajax/offline/744719-cancel.cacheManifest37
-rw-r--r--dom/tests/mochitest/ajax/offline/744719-cancel.cacheManifest^headers^2
-rw-r--r--dom/tests/mochitest/ajax/offline/744719.cacheManifest36
-rw-r--r--dom/tests/mochitest/ajax/offline/744719.cacheManifest^headers^2
-rw-r--r--dom/tests/mochitest/ajax/offline/badManifestMagic.cacheManifest3
-rw-r--r--dom/tests/mochitest/ajax/offline/badManifestMagic.cacheManifest^headers^2
-rw-r--r--dom/tests/mochitest/ajax/offline/browser.ini8
-rw-r--r--dom/tests/mochitest/ajax/offline/browser_disableAppcache.js22
-rw-r--r--dom/tests/mochitest/ajax/offline/bypass.cacheManifest7
-rw-r--r--dom/tests/mochitest/ajax/offline/bypass.cacheManifest^headers^2
-rw-r--r--dom/tests/mochitest/ajax/offline/bypass.html41
-rw-r--r--dom/tests/mochitest/ajax/offline/changing1Hour.sjs8
-rw-r--r--dom/tests/mochitest/ajax/offline/changing1Sec.sjs9
-rw-r--r--dom/tests/mochitest/ajax/offline/changingManifest.sjs27
-rw-r--r--dom/tests/mochitest/ajax/offline/dynamicRedirect.sjs27
-rw-r--r--dom/tests/mochitest/ajax/offline/explicitRedirect.sjs27
-rw-r--r--dom/tests/mochitest/ajax/offline/fallback.cacheManifest11
-rw-r--r--dom/tests/mochitest/ajax/offline/fallback.cacheManifest^headers^2
-rw-r--r--dom/tests/mochitest/ajax/offline/fallback.html12
-rw-r--r--dom/tests/mochitest/ajax/offline/fallback2.html12
-rw-r--r--dom/tests/mochitest/ajax/offline/fallbackTop.html8
-rw-r--r--dom/tests/mochitest/ajax/offline/file_simpleManifest.cacheManifest5
-rw-r--r--dom/tests/mochitest/ajax/offline/file_simpleManifest.html23
-rw-r--r--dom/tests/mochitest/ajax/offline/file_testFile.sjs25
-rw-r--r--dom/tests/mochitest/ajax/offline/foreign1.cacheManifest3
-rw-r--r--dom/tests/mochitest/ajax/offline/foreign1.cacheManifest^headers^2
-rw-r--r--dom/tests/mochitest/ajax/offline/foreign2.cacheManifest3
-rw-r--r--dom/tests/mochitest/ajax/offline/foreign2.cacheManifest^headers^2
-rw-r--r--dom/tests/mochitest/ajax/offline/foreign2.html69
-rw-r--r--dom/tests/mochitest/ajax/offline/jupiter.jpgbin0 -> 30694 bytes
-rw-r--r--dom/tests/mochitest/ajax/offline/manifestRedirect.sjs6
-rw-r--r--dom/tests/mochitest/ajax/offline/missing.html24
-rw-r--r--dom/tests/mochitest/ajax/offline/missingFile.cacheManifest6
-rw-r--r--dom/tests/mochitest/ajax/offline/missingFile.cacheManifest^headers^2
-rw-r--r--dom/tests/mochitest/ajax/offline/mochitest.ini97
-rw-r--r--dom/tests/mochitest/ajax/offline/namespace1/opp.html9
-rw-r--r--dom/tests/mochitest/ajax/offline/namespace1/redirectToDifferentOrigin.sjs6
-rw-r--r--dom/tests/mochitest/ajax/offline/namespace1/script.js4
-rw-r--r--dom/tests/mochitest/ajax/offline/namespace1/sub/opp.html9
-rw-r--r--dom/tests/mochitest/ajax/offline/namespace1/sub/script1.js4
-rw-r--r--dom/tests/mochitest/ajax/offline/namespace1/sub2/script2.js4
-rw-r--r--dom/tests/mochitest/ajax/offline/namespace2/script3.js4
-rw-r--r--dom/tests/mochitest/ajax/offline/notonwhitelist.html9
-rw-r--r--dom/tests/mochitest/ajax/offline/obsolete.html69
-rw-r--r--dom/tests/mochitest/ajax/offline/obsoletingManifest.sjs31
-rw-r--r--dom/tests/mochitest/ajax/offline/offlineChild.html33
-rw-r--r--dom/tests/mochitest/ajax/offline/offlineTests.js390
-rw-r--r--dom/tests/mochitest/ajax/offline/onwhitelist.html9
-rw-r--r--dom/tests/mochitest/ajax/offline/onwhitelist.html^headers^1
-rw-r--r--dom/tests/mochitest/ajax/offline/overlap.cacheManifest12
-rw-r--r--dom/tests/mochitest/ajax/offline/overlap.cacheManifest^headers^1
-rw-r--r--dom/tests/mochitest/ajax/offline/redirects.sjs52
-rw-r--r--dom/tests/mochitest/ajax/offline/simpleManifest.cacheManifest7
-rw-r--r--dom/tests/mochitest/ajax/offline/simpleManifest.cacheManifest^headers^2
-rw-r--r--dom/tests/mochitest/ajax/offline/subresource744719.html1
-rw-r--r--dom/tests/mochitest/ajax/offline/test_badManifestMagic.html53
-rw-r--r--dom/tests/mochitest/ajax/offline/test_bug445544.html73
-rw-r--r--dom/tests/mochitest/ajax/offline/test_bug460353.html100
-rw-r--r--dom/tests/mochitest/ajax/offline/test_bug474696.html41
-rw-r--r--dom/tests/mochitest/ajax/offline/test_bug544462.html53
-rw-r--r--dom/tests/mochitest/ajax/offline/test_bug744719-cancel.html84
-rw-r--r--dom/tests/mochitest/ajax/offline/test_bug744719.html77
-rw-r--r--dom/tests/mochitest/ajax/offline/test_bug765203.html73
-rw-r--r--dom/tests/mochitest/ajax/offline/test_bypass.html37
-rw-r--r--dom/tests/mochitest/ajax/offline/test_cancelOfflineCache.html58
-rw-r--r--dom/tests/mochitest/ajax/offline/test_changingManifest.html116
-rw-r--r--dom/tests/mochitest/ajax/offline/test_fallback.html129
-rw-r--r--dom/tests/mochitest/ajax/offline/test_foreign.html60
-rw-r--r--dom/tests/mochitest/ajax/offline/test_identicalManifest.html86
-rw-r--r--dom/tests/mochitest/ajax/offline/test_missingFile.html53
-rw-r--r--dom/tests/mochitest/ajax/offline/test_missingManifest.html33
-rw-r--r--dom/tests/mochitest/ajax/offline/test_noManifest.html43
-rw-r--r--dom/tests/mochitest/ajax/offline/test_obsolete.html42
-rw-r--r--dom/tests/mochitest/ajax/offline/test_offlineIFrame.html46
-rw-r--r--dom/tests/mochitest/ajax/offline/test_offlineMode.html165
-rw-r--r--dom/tests/mochitest/ajax/offline/test_overlap.html35
-rw-r--r--dom/tests/mochitest/ajax/offline/test_redirectManifest.html44
-rwxr-xr-xdom/tests/mochitest/ajax/offline/test_redirectUpdateItem.html137
-rw-r--r--dom/tests/mochitest/ajax/offline/test_refetchManifest.html88
-rw-r--r--dom/tests/mochitest/ajax/offline/test_simpleManifest.html130
-rw-r--r--dom/tests/mochitest/ajax/offline/test_updateCheck.html87
-rw-r--r--dom/tests/mochitest/ajax/offline/test_updatingManifest.html346
-rw-r--r--dom/tests/mochitest/ajax/offline/test_xhtmlManifest.xhtml32
-rw-r--r--dom/tests/mochitest/ajax/offline/unknownSection.cacheManifest10
-rw-r--r--dom/tests/mochitest/ajax/offline/unknownSection.cacheManifest^headers^2
-rw-r--r--dom/tests/mochitest/ajax/offline/updatingIframe.sjs45
-rw-r--r--dom/tests/mochitest/ajax/offline/updatingImplicit.html53
-rw-r--r--dom/tests/mochitest/ajax/offline/updatingManifest.sjs66
-rw-r--r--dom/tests/mochitest/ajax/offline/wildcardManifest.cacheManifest7
-rw-r--r--dom/tests/mochitest/ajax/offline/wildcardManifest.cacheManifest^headers^2
97 files changed, 3818 insertions, 0 deletions
diff --git a/dom/tests/mochitest/ajax/offline/445544.cacheManifest b/dom/tests/mochitest/ajax/offline/445544.cacheManifest
new file mode 100644
index 0000000000..344ab53a3f
--- /dev/null
+++ b/dom/tests/mochitest/ajax/offline/445544.cacheManifest
@@ -0,0 +1,8 @@
+CACHE MANIFEST
+https://example.com/tests/SimpleTest/SimpleTest.js
+https://example.com/tests/dom/tests/mochitest/ajax/offline/offlineTests.js
+
+test_bug445544.html
+445544_part1.html
+
+# not including 445544_part2.html
diff --git a/dom/tests/mochitest/ajax/offline/445544.cacheManifest^headers^ b/dom/tests/mochitest/ajax/offline/445544.cacheManifest^headers^
new file mode 100644
index 0000000000..5efde3c5b0
--- /dev/null
+++ b/dom/tests/mochitest/ajax/offline/445544.cacheManifest^headers^
@@ -0,0 +1,2 @@
+Content-Type: text/cache-manifest
+
diff --git a/dom/tests/mochitest/ajax/offline/445544_part1.html b/dom/tests/mochitest/ajax/offline/445544_part1.html
new file mode 100644
index 0000000000..d5219e4b7b
--- /dev/null
+++ b/dom/tests/mochitest/ajax/offline/445544_part1.html
@@ -0,0 +1,9 @@
+<html manifest="445544.cacheManifest">
+<head>
+<title>testing navigation part 1</title>
+</head>
+
+<body onload="window.opener.part1loaded(window.applicationCache.status)">
+testing navigation...
+</body>
+</html>
diff --git a/dom/tests/mochitest/ajax/offline/445544_part2.html b/dom/tests/mochitest/ajax/offline/445544_part2.html
new file mode 100644
index 0000000000..74dec4a9a8
--- /dev/null
+++ b/dom/tests/mochitest/ajax/offline/445544_part2.html
@@ -0,0 +1,9 @@
+<html>
+<head>
+<title>testing navigation part 2</title>
+</head>
+
+<body onload="window.opener.part2loaded()">
+success.
+</body>
+</html>
diff --git a/dom/tests/mochitest/ajax/offline/460353_iframe_nomanifest.html b/dom/tests/mochitest/ajax/offline/460353_iframe_nomanifest.html
new file mode 100644
index 0000000000..75b297bbd2
--- /dev/null
+++ b/dom/tests/mochitest/ajax/offline/460353_iframe_nomanifest.html
@@ -0,0 +1,9 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Bug 460353, iframe with no manifest reference</title>
+
+</head>
+<body onload="parent.frameOnLoad('noman', applicationCache.status);">
+ This is an iframe without a manifest reference
+</body>
+</html>
diff --git a/dom/tests/mochitest/ajax/offline/460353_iframe_ownmanifest.html b/dom/tests/mochitest/ajax/offline/460353_iframe_ownmanifest.html
new file mode 100644
index 0000000000..2bcdb4611e
--- /dev/null
+++ b/dom/tests/mochitest/ajax/offline/460353_iframe_ownmanifest.html
@@ -0,0 +1,21 @@
+<html xmlns="http://www.w3.org/1999/xhtml" manifest="updatingManifest.sjs">
+<head>
+<title>Bug 460353, iframe with a different manifest reference</title>
+
+<script type="text/javascript">
+
+applicationCache.onerror = function() {
+ parent.frameOnUpdate("diff", false);
+}
+
+applicationCache.oncached = function() {
+ parent.frameOnUpdate("diff", true, applicationCache.status);
+}
+
+</script>
+
+</head>
+<body onload="parent.frameOnLoad('diff', applicationCache.status);">
+ This is an iframe with a different manifest reference
+</body>
+</html>
diff --git a/dom/tests/mochitest/ajax/offline/460353_iframe_samemanifest.html b/dom/tests/mochitest/ajax/offline/460353_iframe_samemanifest.html
new file mode 100644
index 0000000000..de357827b6
--- /dev/null
+++ b/dom/tests/mochitest/ajax/offline/460353_iframe_samemanifest.html
@@ -0,0 +1,25 @@
+<html xmlns="http://www.w3.org/1999/xhtml" manifest="simpleManifest.cacheManifest">
+<head>
+<title>Bug 460353, iframe with a different manifest reference</title>
+
+<script type="text/javascript">
+
+applicationCache.onerror = function() {
+ parent.frameOnUpdate("same", false);
+}
+
+applicationCache.oncached = function() {
+ parent.frameOnUpdate("same", true, applicationCache.status);
+}
+
+applicationCache.onnoupdate = function() {
+ parent.frameOnUpdate("same", true, applicationCache.status);
+}
+
+</script>
+
+</head>
+<body onload="parent.frameOnLoad('same', applicationCache.status);">
+ This is an iframe with the same manifest reference
+</body>
+</html>
diff --git a/dom/tests/mochitest/ajax/offline/744719-cancel.cacheManifest b/dom/tests/mochitest/ajax/offline/744719-cancel.cacheManifest
new file mode 100644
index 0000000000..c0f4b855c5
--- /dev/null
+++ b/dom/tests/mochitest/ajax/offline/744719-cancel.cacheManifest
@@ -0,0 +1,37 @@
+CACHE MANIFEST
+
+https://example.com/tests/SimpleTest/SimpleTest.js
+https://example.com/tests/dom/tests/mochitest/ajax/offline/offlineTests.js
+
+# more than 15 what is a number of parallel loads
+subresource744719.html?001
+subresource744719.html?002
+subresource744719.html?003
+subresource744719.html?004
+subresource744719.html?005
+subresource744719.html?006
+subresource744719.html?007
+subresource744719.html?008
+subresource744719.html?009
+# this one is non existing and should cancel the load
+nonexistent744719.html?010
+subresource744719.html?011
+subresource744719.html?012
+subresource744719.html?013
+subresource744719.html?014
+subresource744719.html?015
+subresource744719.html?016
+subresource744719.html?017
+subresource744719.html?018
+subresource744719.html?019
+subresource744719.html?020
+subresource744719.html?021
+subresource744719.html?022
+subresource744719.html?023
+subresource744719.html?024
+subresource744719.html?025
+subresource744719.html?026
+subresource744719.html?027
+subresource744719.html?028
+subresource744719.html?029
+subresource744719.html?030
diff --git a/dom/tests/mochitest/ajax/offline/744719-cancel.cacheManifest^headers^ b/dom/tests/mochitest/ajax/offline/744719-cancel.cacheManifest^headers^
new file mode 100644
index 0000000000..5efde3c5b0
--- /dev/null
+++ b/dom/tests/mochitest/ajax/offline/744719-cancel.cacheManifest^headers^
@@ -0,0 +1,2 @@
+Content-Type: text/cache-manifest
+
diff --git a/dom/tests/mochitest/ajax/offline/744719.cacheManifest b/dom/tests/mochitest/ajax/offline/744719.cacheManifest
new file mode 100644
index 0000000000..f6ac2986e7
--- /dev/null
+++ b/dom/tests/mochitest/ajax/offline/744719.cacheManifest
@@ -0,0 +1,36 @@
+CACHE MANIFEST
+
+https://example.com/tests/SimpleTest/SimpleTest.js
+https://example.com/tests/dom/tests/mochitest/ajax/offline/offlineTests.js
+
+# more than 15 what is a number of parallel loads
+subresource744719.html?001
+subresource744719.html?002
+subresource744719.html?003
+subresource744719.html?004
+subresource744719.html?005
+subresource744719.html?006
+subresource744719.html?007
+subresource744719.html?008
+subresource744719.html?009
+subresource744719.html?010
+subresource744719.html?011
+subresource744719.html?012
+subresource744719.html?013
+subresource744719.html?014
+subresource744719.html?015
+subresource744719.html?016
+subresource744719.html?017
+subresource744719.html?018
+subresource744719.html?019
+subresource744719.html?020
+subresource744719.html?021
+subresource744719.html?022
+subresource744719.html?023
+subresource744719.html?024
+subresource744719.html?025
+subresource744719.html?026
+subresource744719.html?027
+subresource744719.html?028
+subresource744719.html?029
+subresource744719.html?030
diff --git a/dom/tests/mochitest/ajax/offline/744719.cacheManifest^headers^ b/dom/tests/mochitest/ajax/offline/744719.cacheManifest^headers^
new file mode 100644
index 0000000000..5efde3c5b0
--- /dev/null
+++ b/dom/tests/mochitest/ajax/offline/744719.cacheManifest^headers^
@@ -0,0 +1,2 @@
+Content-Type: text/cache-manifest
+
diff --git a/dom/tests/mochitest/ajax/offline/badManifestMagic.cacheManifest b/dom/tests/mochitest/ajax/offline/badManifestMagic.cacheManifest
new file mode 100644
index 0000000000..97ce7363f4
--- /dev/null
+++ b/dom/tests/mochitest/ajax/offline/badManifestMagic.cacheManifest
@@ -0,0 +1,3 @@
+# This doesn't start with the magic cache manifest line.
+https://example.com/tests/SimpleTest/SimpleTest.js
+https://example.com/tests/dom/tests/mochitest/ajax/offline/offlineTests.js
diff --git a/dom/tests/mochitest/ajax/offline/badManifestMagic.cacheManifest^headers^ b/dom/tests/mochitest/ajax/offline/badManifestMagic.cacheManifest^headers^
new file mode 100644
index 0000000000..5efde3c5b0
--- /dev/null
+++ b/dom/tests/mochitest/ajax/offline/badManifestMagic.cacheManifest^headers^
@@ -0,0 +1,2 @@
+Content-Type: text/cache-manifest
+
diff --git a/dom/tests/mochitest/ajax/offline/browser.ini b/dom/tests/mochitest/ajax/offline/browser.ini
new file mode 100644
index 0000000000..3935dd3152
--- /dev/null
+++ b/dom/tests/mochitest/ajax/offline/browser.ini
@@ -0,0 +1,8 @@
+[DEFAULT]
+support-files =
+ file_simpleManifest.html
+ file_testFile.sjs
+ file_simpleManifest.cacheManifest
+
+[browser_disableAppcache.js]
+skip-if = !e10s || (toolkit == 'android') || debug # Slow
diff --git a/dom/tests/mochitest/ajax/offline/browser_disableAppcache.js b/dom/tests/mochitest/ajax/offline/browser_disableAppcache.js
new file mode 100644
index 0000000000..41465087cf
--- /dev/null
+++ b/dom/tests/mochitest/ajax/offline/browser_disableAppcache.js
@@ -0,0 +1,22 @@
+const PATH = "http://example.com/browser/dom/tests/mochitest/ajax/offline/";
+const URL = PATH + "file_simpleManifest.html";
+const MANIFEST = PATH + "file_simpleManifest.cacheManifest";
+const PREF_NETWORK_PROXY = "network.proxy.type";
+
+add_task(async function test_pref_removes_api() {
+ await BrowserTestUtils.openNewForegroundTab(gBrowser, URL);
+ await SpecialPowers.spawn(gBrowser.selectedBrowser, [], async () => {
+ // Have to use in page checking as IsSecureContextOrObjectIsFromSecureContext is true for spawn()
+ is(
+ content.document.getElementById("hasAppcache").textContent,
+ "no",
+ "Appcache is disabled"
+ );
+ is(
+ content.document.getElementById("hasOfflineResourceList").textContent,
+ "no",
+ "OfflineResourceList is disabled"
+ );
+ });
+ gBrowser.removeCurrentTab();
+});
diff --git a/dom/tests/mochitest/ajax/offline/bypass.cacheManifest b/dom/tests/mochitest/ajax/offline/bypass.cacheManifest
new file mode 100644
index 0000000000..ec31a901d7
--- /dev/null
+++ b/dom/tests/mochitest/ajax/offline/bypass.cacheManifest
@@ -0,0 +1,7 @@
+CACHE MANIFEST
+
+bypass.html
+
+NETWORK:
+namespace1/sub
+namespace2
diff --git a/dom/tests/mochitest/ajax/offline/bypass.cacheManifest^headers^ b/dom/tests/mochitest/ajax/offline/bypass.cacheManifest^headers^
new file mode 100644
index 0000000000..5efde3c5b0
--- /dev/null
+++ b/dom/tests/mochitest/ajax/offline/bypass.cacheManifest^headers^
@@ -0,0 +1,2 @@
+Content-Type: text/cache-manifest
+
diff --git a/dom/tests/mochitest/ajax/offline/bypass.html b/dom/tests/mochitest/ajax/offline/bypass.html
new file mode 100644
index 0000000000..f5bf71e9e3
--- /dev/null
+++ b/dom/tests/mochitest/ajax/offline/bypass.html
@@ -0,0 +1,41 @@
+<html xmlns="http://www.w3.org/1999/xhtml" manifest="bypass.cacheManifest">
+<head>
+
+<script type="text/javascript" src="namespace1/script.js"></script>
+<script type="text/javascript" src="namespace1/sub/script1.js"></script>
+<script type="text/javascript" src="namespace1/sub2/script2.js"></script>
+<script type="text/javascript" src="namespace2/script3.js"></script>
+
+<script class="testbody" type="text/javascript">
+
+function testScriptPresence(scriptPath, func, shouldPass)
+{
+ var msg = "Script " + scriptPath + (shouldPass ? " loaded" : " not loaded");
+ try {
+ eval(func);
+ opener.OfflineTest.ok(shouldPass, msg);
+ }
+ catch(ex) {
+ opener.OfflineTest.ok(!shouldPass, msg);
+ }
+
+}
+
+function startTest()
+{
+ testScriptPresence("namespace1/script.js", "scriptNo0Function();", false);
+ testScriptPresence("namespace1/sub/script1.js", "scriptNo1Function();", true);
+ testScriptPresence("namespace1/sub2/script2.js", "scriptNo2Function();", true);
+ testScriptPresence("namespace2/script3.js", "scriptNo3Function();", true);
+
+ opener.OfflineTest.teardownAndFinish();
+ window.close(window);
+}
+
+</script>
+
+</head>
+
+<body onload="startTest();">
+</body>
+</html>
diff --git a/dom/tests/mochitest/ajax/offline/changing1Hour.sjs b/dom/tests/mochitest/ajax/offline/changing1Hour.sjs
new file mode 100644
index 0000000000..2a10359650
--- /dev/null
+++ b/dom/tests/mochitest/ajax/offline/changing1Hour.sjs
@@ -0,0 +1,8 @@
+function handleRequest(request, response)
+{
+ response.setStatusLine(request.httpVersion, 200, "Ok");
+ response.setHeader("Content-Type", "text/plain");
+ response.setHeader("Cache-Control", "max-age=3600");
+
+ response.write(Date.now());
+}
diff --git a/dom/tests/mochitest/ajax/offline/changing1Sec.sjs b/dom/tests/mochitest/ajax/offline/changing1Sec.sjs
new file mode 100644
index 0000000000..cb9428b6c3
--- /dev/null
+++ b/dom/tests/mochitest/ajax/offline/changing1Sec.sjs
@@ -0,0 +1,9 @@
+function handleRequest(request, response)
+{
+ response.setStatusLine(request.httpVersion, 200, "Ok");
+ response.setHeader("Content-Type", "text/plain");
+ response.setHeader("Cache-Control", "max-age=1");
+
+ response.write(Date.now());
+}
+
diff --git a/dom/tests/mochitest/ajax/offline/changingManifest.sjs b/dom/tests/mochitest/ajax/offline/changingManifest.sjs
new file mode 100644
index 0000000000..4d178d1dd7
--- /dev/null
+++ b/dom/tests/mochitest/ajax/offline/changingManifest.sjs
@@ -0,0 +1,27 @@
+function handleRequest(request, response)
+{
+ var match = request.queryString.match(/^state=(.*)$/);
+ if (match)
+ {
+ response.setStatusLine(request.httpVersion, 204, "No content");
+ setState("offline.changingManifest", match[1]);
+ }
+
+ if (request.queryString == "")
+ {
+ response.setStatusLine(request.httpVersion, 200, "Ok");
+ response.setHeader("Content-Type", "text/cache-manifest");
+ response.setHeader("Cache-Control", "no-cache");
+ response.write(
+ "CACHE MANIFEST\n" +
+ "# v" + getState("offline.changingManifest") + "\n" +
+ "changing1Hour.sjs\n" +
+ "changing1Sec.sjs\n");
+
+ if (getState("offline.changingManifest") != "2") {
+ response.write(
+ "NETWORK:\n" +
+ "onwhitelist.html\n");
+ }
+ }
+}
diff --git a/dom/tests/mochitest/ajax/offline/dynamicRedirect.sjs b/dom/tests/mochitest/ajax/offline/dynamicRedirect.sjs
new file mode 100644
index 0000000000..d2bb845f60
--- /dev/null
+++ b/dom/tests/mochitest/ajax/offline/dynamicRedirect.sjs
@@ -0,0 +1,27 @@
+function handleRequest(request, response)
+{
+ var match = request.queryString.match(/^state=(.*)$/);
+ if (match)
+ {
+ response.setStatusLine(request.httpVersion, 200, "No content");
+ setState("state", match[1]);
+ response.write("state='" + match[1] + "'");
+ }
+
+ if (request.queryString == "")
+ {
+ switch (getState("state"))
+ {
+ case "": // The default value
+ response.setStatusLine(request.httpVersion, 307, "Moved temporarly");
+ response.setHeader("Location", "https://example.org/non-existing-dynamic.html");
+ response.setHeader("Content-Type", "text/html");
+ break;
+ case "on":
+ response.setStatusLine(request.httpVersion, 200, "OK");
+ response.setHeader("Content-Type", "text/html");
+ response.write("<html><body>Dynamic page</body></html>");
+ break;
+ }
+ }
+}
diff --git a/dom/tests/mochitest/ajax/offline/explicitRedirect.sjs b/dom/tests/mochitest/ajax/offline/explicitRedirect.sjs
new file mode 100644
index 0000000000..501d1a71d4
--- /dev/null
+++ b/dom/tests/mochitest/ajax/offline/explicitRedirect.sjs
@@ -0,0 +1,27 @@
+function handleRequest(request, response)
+{
+ var match = request.queryString.match(/^state=(.*)$/);
+ if (match)
+ {
+ response.setStatusLine(request.httpVersion, 200, "No content");
+ setState("state", match[1]);
+ response.write("state='" + match[1] + "'");
+ }
+
+ if (request.queryString == "")
+ {
+ switch (getState("state"))
+ {
+ case "": // The default value
+ response.setStatusLine(request.httpVersion, 307, "Moved temporarly");
+ response.setHeader("Location", "https://example.com/non-existing-explicit.html");
+ response.setHeader("Content-Type", "text/html");
+ break;
+ case "on":
+ response.setStatusLine(request.httpVersion, 200, "OK");
+ response.setHeader("Content-Type", "text/html");
+ response.write("<html><body>Explicit page</body></html>");
+ break;
+ }
+ }
+}
diff --git a/dom/tests/mochitest/ajax/offline/fallback.cacheManifest b/dom/tests/mochitest/ajax/offline/fallback.cacheManifest
new file mode 100644
index 0000000000..dad050991b
--- /dev/null
+++ b/dom/tests/mochitest/ajax/offline/fallback.cacheManifest
@@ -0,0 +1,11 @@
+CACHE MANIFEST
+https://example.com/tests/SimpleTest/SimpleTest.js
+https://example.com/tests/dom/tests/mochitest/ajax/offline/offlineTests.js
+
+FALLBACK:
+namespace1/ fallback.html
+namespace1/sub/ fallback2.html
+namespace2/ fallbackTop.html
+
+NETWORK:
+onwhitelist.html
diff --git a/dom/tests/mochitest/ajax/offline/fallback.cacheManifest^headers^ b/dom/tests/mochitest/ajax/offline/fallback.cacheManifest^headers^
new file mode 100644
index 0000000000..5efde3c5b0
--- /dev/null
+++ b/dom/tests/mochitest/ajax/offline/fallback.cacheManifest^headers^
@@ -0,0 +1,2 @@
+Content-Type: text/cache-manifest
+
diff --git a/dom/tests/mochitest/ajax/offline/fallback.html b/dom/tests/mochitest/ajax/offline/fallback.html
new file mode 100644
index 0000000000..9b591a1195
--- /dev/null
+++ b/dom/tests/mochitest/ajax/offline/fallback.html
@@ -0,0 +1,12 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>fallback page for fallback test</title>
+
+<script src="/tests/SimpleTest/SimpleTest.js"></script>
+<script type="text/javascript" src="/tests/dom/tests/mochitest/ajax/offline/offlineTests.js"></script>
+
+</head>
+<body onload="parent.onFallbackLoad(1);">
+Fallback page
+</body>
+</html>
diff --git a/dom/tests/mochitest/ajax/offline/fallback2.html b/dom/tests/mochitest/ajax/offline/fallback2.html
new file mode 100644
index 0000000000..ce737b09e6
--- /dev/null
+++ b/dom/tests/mochitest/ajax/offline/fallback2.html
@@ -0,0 +1,12 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>fallback page for fallback test</title>
+
+<script src="/tests/SimpleTest/SimpleTest.js"></script>
+<script type="text/javascript" src="/tests/dom/tests/mochitest/ajax/offline/offlineTests.js"></script>
+
+</head>
+<body onload="parent.onFallbackLoad(2);">
+Sub fallback page
+</body>
+</html>
diff --git a/dom/tests/mochitest/ajax/offline/fallbackTop.html b/dom/tests/mochitest/ajax/offline/fallbackTop.html
new file mode 100644
index 0000000000..5de4316c04
--- /dev/null
+++ b/dom/tests/mochitest/ajax/offline/fallbackTop.html
@@ -0,0 +1,8 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Fallback for top window</title>
+</head>
+
+<body onLoad="window.opener.onFallbackLoad(100);">
+</body>
+</html>
diff --git a/dom/tests/mochitest/ajax/offline/file_simpleManifest.cacheManifest b/dom/tests/mochitest/ajax/offline/file_simpleManifest.cacheManifest
new file mode 100644
index 0000000000..a6b430488b
--- /dev/null
+++ b/dom/tests/mochitest/ajax/offline/file_simpleManifest.cacheManifest
@@ -0,0 +1,5 @@
+CACHE MANIFEST
+http://example.com/browser/dom/tests/mochitest/ajax/offline/file_testFile.sjs
+http://example.com/browser/dom/tests/mochitest/ajax/offline/file_simpleManifest.html
+http://example.com/tests/dom/tests/mochitest/ajax/offline/offlineTests.js
+
diff --git a/dom/tests/mochitest/ajax/offline/file_simpleManifest.html b/dom/tests/mochitest/ajax/offline/file_simpleManifest.html
new file mode 100644
index 0000000000..dc365807b6
--- /dev/null
+++ b/dom/tests/mochitest/ajax/offline/file_simpleManifest.html
@@ -0,0 +1,23 @@
+<html xmlns="http://www.w3.org/1999/xhtml" manifest="http://example.com/browser/dom/tests/mochitest/ajax/offline/file_simpleManifest.cacheManifest">
+<head>
+<title>load manifest test</title>
+
+<script type="text/javascript">
+ window.addEventListener("load", () => {
+ const hasAppcache = document.getElementById("hasAppcache");
+ hasAppcache.textContent = "applicationCache" in window ? "yes" : "no";
+ const hasOfflineResourceList = document.getElementById("hasOfflineResourceList");
+ hasOfflineResourceList.textContent = "OfflineResourceList" in window ? "yes" : "no";
+ });
+</script>
+<script type="text/javascript" src="http://example.com/tests/dom/tests/mochitest/ajax/offline/offlineTests.js"></script>
+</head>
+
+<body>
+Offline testing<br />
+We have AppCache: <span id="hasAppcache"></span><br />
+We have OfflineResourceList: <span id="hasOfflineResourceList"></span><br />
+
+<iframe id="childframe" src="http://example.com/browser/dom/tests/mochitest/ajax/offline/file_testFile.sjs" ></iframe>
+</body>
+</html>
diff --git a/dom/tests/mochitest/ajax/offline/file_testFile.sjs b/dom/tests/mochitest/ajax/offline/file_testFile.sjs
new file mode 100644
index 0000000000..62d020b355
--- /dev/null
+++ b/dom/tests/mochitest/ajax/offline/file_testFile.sjs
@@ -0,0 +1,25 @@
+function handleRequest(request, response) {
+ var match = request.queryString.match(/^state=(.*)$/);
+ if (match) {
+ response.setStatusLine(request.httpVersion, 204, "No content");
+ setState("version", match[1]);
+ return;
+ }
+ const state = getState("version");
+ let color = "green";
+ if (state === "evil") {
+ color = "red";
+ }
+ const frameContent = `
+ <!DOCTYPE html>
+ <html>
+ <head>
+ <style>body,html {background: ${color};}</style>
+ </head>
+ <body>
+ <h1>Offline file: <span id="state">${state}</span></h1>
+ `;
+ response.setHeader("Content-Type", "text/html");
+ response.setHeader("Cache-Control", "no-cache");
+ response.write(frameContent);
+}
diff --git a/dom/tests/mochitest/ajax/offline/foreign1.cacheManifest b/dom/tests/mochitest/ajax/offline/foreign1.cacheManifest
new file mode 100644
index 0000000000..4b713f8443
--- /dev/null
+++ b/dom/tests/mochitest/ajax/offline/foreign1.cacheManifest
@@ -0,0 +1,3 @@
+CACHE MANIFEST
+
+foreign2.html
diff --git a/dom/tests/mochitest/ajax/offline/foreign1.cacheManifest^headers^ b/dom/tests/mochitest/ajax/offline/foreign1.cacheManifest^headers^
new file mode 100644
index 0000000000..5efde3c5b0
--- /dev/null
+++ b/dom/tests/mochitest/ajax/offline/foreign1.cacheManifest^headers^
@@ -0,0 +1,2 @@
+Content-Type: text/cache-manifest
+
diff --git a/dom/tests/mochitest/ajax/offline/foreign2.cacheManifest b/dom/tests/mochitest/ajax/offline/foreign2.cacheManifest
new file mode 100644
index 0000000000..4b713f8443
--- /dev/null
+++ b/dom/tests/mochitest/ajax/offline/foreign2.cacheManifest
@@ -0,0 +1,3 @@
+CACHE MANIFEST
+
+foreign2.html
diff --git a/dom/tests/mochitest/ajax/offline/foreign2.cacheManifest^headers^ b/dom/tests/mochitest/ajax/offline/foreign2.cacheManifest^headers^
new file mode 100644
index 0000000000..5efde3c5b0
--- /dev/null
+++ b/dom/tests/mochitest/ajax/offline/foreign2.cacheManifest^headers^
@@ -0,0 +1,2 @@
+Content-Type: text/cache-manifest
+
diff --git a/dom/tests/mochitest/ajax/offline/foreign2.html b/dom/tests/mochitest/ajax/offline/foreign2.html
new file mode 100644
index 0000000000..126ee47a60
--- /dev/null
+++ b/dom/tests/mochitest/ajax/offline/foreign2.html
@@ -0,0 +1,69 @@
+<html xmlns="http://www.w3.org/1999/xhtml" manifest="https://example.com/tests/dom/tests/mochitest/ajax/offline/foreign2.cacheManifest">
+<head>
+<title>Foreign page 2</title>
+
+<script src="/tests/SimpleTest/SimpleTest.js"></script>
+<script type="text/javascript" src="/tests/dom/tests/mochitest/ajax/offline/offlineTests.js"></script>
+<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+
+<script class="testbody" type="text/javascript">
+
+function manifestUpdated()
+{
+ var appCacheService = SpecialPowers.Cc["@mozilla.org/network/application-cache-service;1"]
+ .getService(SpecialPowers.Ci.nsIApplicationCacheService);
+
+ var foreign2cache = appCacheService.chooseApplicationCache(
+ "https://example.com/tests/dom/tests/mochitest/ajax/offline/foreign2.html", OfflineTest.loadContextInfo());
+
+ window.opener.OfflineTest.ok(foreign2cache, "Foreign 2 cache present, chosen for foreign2.html");
+ window.opener.OfflineTest.is(foreign2cache.manifestURI.asciiSpec, "https://example.com/tests/dom/tests/mochitest/ajax/offline/foreign2.cacheManifest");
+
+ var foreign1cache = OfflineTest.getActiveCache(
+ "https://example.com/tests/dom/tests/mochitest/ajax/offline/foreign1.cacheManifest");
+ window.opener.OfflineTest.ok(foreign1cache, "Foreign 1 cache loaded");
+ foreign1cache.discard();
+
+ window.opener.onDone();
+}
+
+function onLoaded()
+{
+ var appCacheService = SpecialPowers.Cc["@mozilla.org/network/application-cache-service;1"]
+ .getService(SpecialPowers.Ci.nsIApplicationCacheService);
+
+ var foreign1cache = window.opener.OfflineTest.getActiveCache(
+ "https://example.com/tests/dom/tests/mochitest/ajax/offline/foreign1.cacheManifest");
+ window.opener.OfflineTest.ok(foreign1cache, "Foreign 1 cache loaded");
+
+ var foreign2cache = window.opener.OfflineTest.getActiveCache(
+ "https://example.com/tests/dom/tests/mochitest/ajax/offline/foreign2.cacheManifest");
+ window.opener.OfflineTest.ok(!foreign2cache, "Foreign 2 cache not present");
+
+ foreign1cache = appCacheService.chooseApplicationCache(
+ "https://example.com/tests/dom/tests/mochitest/ajax/offline/foreign2.html", window.opener.OfflineTest.loadContextInfo());
+ window.opener.OfflineTest.ok(!foreign1cache, "foreign2.html not chosen from foreign1 cache");
+
+ try
+ {
+ window.opener.OfflineTest.ok(applicationCache.status == OfflineResourceList.UNCACHED,
+ "there is no associated application cache");
+ }
+ catch (ex)
+ {
+ window.opener.OfflineTest.ok(false, "applicationCache.status must not throw an exception");
+ }
+}
+
+applicationCache.onerror = window.opener.OfflineTest.failEvent;
+applicationCache.onupdateready = window.opener.OfflineTest.failEvent;
+applicationCache.onnoupdate = window.opener.OfflineTest.failEvent;
+applicationCache.oncached = window.opener.OfflineTest.priv(manifestUpdated);
+
+</script>
+
+</head>
+
+<body onload="OfflineTest.priv(onLoaded)();">
+</body>
+</html>
diff --git a/dom/tests/mochitest/ajax/offline/jupiter.jpg b/dom/tests/mochitest/ajax/offline/jupiter.jpg
new file mode 100644
index 0000000000..cddf589d56
--- /dev/null
+++ b/dom/tests/mochitest/ajax/offline/jupiter.jpg
Binary files differ
diff --git a/dom/tests/mochitest/ajax/offline/manifestRedirect.sjs b/dom/tests/mochitest/ajax/offline/manifestRedirect.sjs
new file mode 100644
index 0000000000..5f562ec310
--- /dev/null
+++ b/dom/tests/mochitest/ajax/offline/manifestRedirect.sjs
@@ -0,0 +1,6 @@
+function handleRequest(request, response)
+{
+ response.setStatusLine(request.httpVersion, 307, "Moved temporarly");
+ response.setHeader("Location", "https://example.com/tests/dom/tests/mochitest/ajax/offline/updating.cacheManifest");
+ response.setHeader("Content-Type", "text/cache-manifest");
+}
diff --git a/dom/tests/mochitest/ajax/offline/missing.html b/dom/tests/mochitest/ajax/offline/missing.html
new file mode 100644
index 0000000000..3e4fef759d
--- /dev/null
+++ b/dom/tests/mochitest/ajax/offline/missing.html
@@ -0,0 +1,24 @@
+<html manifest="missing.cacheManifest">
+<head>
+<title>missing test</title>
+<script type="text/javascript">
+
+function obsolete(evt)
+{
+ window.opener.ok(false, "Got an 'obsolete' event");
+ window.opener.finish();
+}
+
+function error(evt) {
+ window.opener.ok(true, "Got an 'error' event");
+ window.opener.finish();
+}
+
+applicationCache.onobsolete = obsolete;
+applicationCache.onerror = error;
+</script>
+</head>
+
+<body>
+<h1></h1>
+</body> </html>
diff --git a/dom/tests/mochitest/ajax/offline/missingFile.cacheManifest b/dom/tests/mochitest/ajax/offline/missingFile.cacheManifest
new file mode 100644
index 0000000000..4c0bf27a13
--- /dev/null
+++ b/dom/tests/mochitest/ajax/offline/missingFile.cacheManifest
@@ -0,0 +1,6 @@
+CACHE MANIFEST
+https://example.com/tests/SimpleTest/SimpleTest.js
+https://example.com/tests/dom/tests/mochitest/ajax/offline/offlineTests.js
+
+# The following item doesn't exist, and will cause an update error.
+https://example.com/tests/dom/tests/mochitest/ajax/offline/doesntExist.html
diff --git a/dom/tests/mochitest/ajax/offline/missingFile.cacheManifest^headers^ b/dom/tests/mochitest/ajax/offline/missingFile.cacheManifest^headers^
new file mode 100644
index 0000000000..5efde3c5b0
--- /dev/null
+++ b/dom/tests/mochitest/ajax/offline/missingFile.cacheManifest^headers^
@@ -0,0 +1,2 @@
+Content-Type: text/cache-manifest
+
diff --git a/dom/tests/mochitest/ajax/offline/mochitest.ini b/dom/tests/mochitest/ajax/offline/mochitest.ini
new file mode 100644
index 0000000000..64c2363bfb
--- /dev/null
+++ b/dom/tests/mochitest/ajax/offline/mochitest.ini
@@ -0,0 +1,97 @@
+[DEFAULT]
+scheme = https
+skip-if = e10s #SLOW_DIRECTORY
+support-files =
+ 445544.cacheManifest
+ 445544.cacheManifest^headers^
+ 445544_part1.html
+ 445544_part2.html
+ 460353_iframe_nomanifest.html
+ 460353_iframe_ownmanifest.html
+ 460353_iframe_samemanifest.html
+ 744719-cancel.cacheManifest
+ 744719-cancel.cacheManifest^headers^
+ 744719.cacheManifest
+ 744719.cacheManifest^headers^
+ badManifestMagic.cacheManifest
+ badManifestMagic.cacheManifest^headers^
+ bypass.cacheManifest
+ bypass.cacheManifest^headers^
+ bypass.html
+ changing1Hour.sjs
+ changing1Sec.sjs
+ changingManifest.sjs
+ dynamicRedirect.sjs
+ explicitRedirect.sjs
+ fallback.cacheManifest
+ fallback.cacheManifest^headers^
+ fallback.html
+ fallback2.html
+ fallbackTop.html
+ foreign1.cacheManifest
+ foreign1.cacheManifest^headers^
+ foreign2.cacheManifest
+ foreign2.cacheManifest^headers^
+ foreign2.html
+ jupiter.jpg
+ manifestRedirect.sjs
+ missing.html
+ missingFile.cacheManifest
+ missingFile.cacheManifest^headers^
+ notonwhitelist.html
+ obsolete.html
+ obsoletingManifest.sjs
+ offlineChild.html
+ offlineTests.js
+ onwhitelist.html
+ onwhitelist.html^headers^
+ overlap.cacheManifest
+ overlap.cacheManifest^headers^
+ redirects.sjs
+ simpleManifest.cacheManifest
+ simpleManifest.cacheManifest^headers^
+ subresource744719.html
+ unknownSection.cacheManifest
+ unknownSection.cacheManifest^headers^
+ updatingIframe.sjs
+ updatingImplicit.html
+ updatingManifest.sjs
+ wildcardManifest.cacheManifest
+ wildcardManifest.cacheManifest^headers^
+ namespace1/opp.html
+ namespace1/script.js
+ namespace1/redirectToDifferentOrigin.sjs
+ namespace1/sub/opp.html
+ namespace1/sub/script1.js
+ namespace1/sub2/script2.js
+ namespace2/script3.js
+
+[test_badManifestMagic.html]
+[test_bug445544.html]
+[test_bug460353.html]
+[test_bug474696.html]
+[test_bug544462.html]
+[test_bug744719-cancel.html]
+[test_bug744719.html]
+[test_bug765203.html]
+[test_bypass.html]
+[test_cancelOfflineCache.html]
+[test_changingManifest.html]
+[test_fallback.html]
+[test_foreign.html]
+[test_identicalManifest.html]
+[test_missingFile.html]
+[test_missingManifest.html]
+[test_noManifest.html]
+[test_obsolete.html]
+[test_offlineIFrame.html]
+[test_offlineMode.html]
+skip-if = true # disabled due to bug 656943
+[test_overlap.html]
+[test_redirectManifest.html]
+[test_redirectUpdateItem.html]
+[test_refetchManifest.html]
+[test_simpleManifest.html]
+[test_updateCheck.html]
+[test_updatingManifest.html]
+[test_xhtmlManifest.xhtml]
diff --git a/dom/tests/mochitest/ajax/offline/namespace1/opp.html b/dom/tests/mochitest/ajax/offline/namespace1/opp.html
new file mode 100644
index 0000000000..daf4abf213
--- /dev/null
+++ b/dom/tests/mochitest/ajax/offline/namespace1/opp.html
@@ -0,0 +1,9 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Falback namespace page 1</title>
+</head>
+
+<body>
+Page in fall back namespace No. 1
+</body>
+</html>
diff --git a/dom/tests/mochitest/ajax/offline/namespace1/redirectToDifferentOrigin.sjs b/dom/tests/mochitest/ajax/offline/namespace1/redirectToDifferentOrigin.sjs
new file mode 100644
index 0000000000..a64e00e044
--- /dev/null
+++ b/dom/tests/mochitest/ajax/offline/namespace1/redirectToDifferentOrigin.sjs
@@ -0,0 +1,6 @@
+function handleRequest(request, response)
+{
+ response.setStatusLine(request.httpVersion, 307, "Moved temporarly");
+ response.setHeader("Location", "https://example.org/tests/dom/tests/mochitest/ajax/offline/fallback2.html");
+ response.setHeader("Content-Type", "text/html");
+}
diff --git a/dom/tests/mochitest/ajax/offline/namespace1/script.js b/dom/tests/mochitest/ajax/offline/namespace1/script.js
new file mode 100644
index 0000000000..61ffb174f2
--- /dev/null
+++ b/dom/tests/mochitest/ajax/offline/namespace1/script.js
@@ -0,0 +1,4 @@
+function scriptNo0Function()
+{
+ return true;
+}
diff --git a/dom/tests/mochitest/ajax/offline/namespace1/sub/opp.html b/dom/tests/mochitest/ajax/offline/namespace1/sub/opp.html
new file mode 100644
index 0000000000..2d0996553d
--- /dev/null
+++ b/dom/tests/mochitest/ajax/offline/namespace1/sub/opp.html
@@ -0,0 +1,9 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Falback namespace page 2</title>
+</head>
+
+<body>
+Page in fall back namespace No. 2
+</body>
+</html>
diff --git a/dom/tests/mochitest/ajax/offline/namespace1/sub/script1.js b/dom/tests/mochitest/ajax/offline/namespace1/sub/script1.js
new file mode 100644
index 0000000000..30829316b2
--- /dev/null
+++ b/dom/tests/mochitest/ajax/offline/namespace1/sub/script1.js
@@ -0,0 +1,4 @@
+function scriptNo1Function()
+{
+ return true;
+}
diff --git a/dom/tests/mochitest/ajax/offline/namespace1/sub2/script2.js b/dom/tests/mochitest/ajax/offline/namespace1/sub2/script2.js
new file mode 100644
index 0000000000..586d39a19c
--- /dev/null
+++ b/dom/tests/mochitest/ajax/offline/namespace1/sub2/script2.js
@@ -0,0 +1,4 @@
+function scriptNo2Function()
+{
+ return true;
+}
diff --git a/dom/tests/mochitest/ajax/offline/namespace2/script3.js b/dom/tests/mochitest/ajax/offline/namespace2/script3.js
new file mode 100644
index 0000000000..20dd8b97d2
--- /dev/null
+++ b/dom/tests/mochitest/ajax/offline/namespace2/script3.js
@@ -0,0 +1,4 @@
+function scriptNo3Function()
+{
+ return true;
+}
diff --git a/dom/tests/mochitest/ajax/offline/notonwhitelist.html b/dom/tests/mochitest/ajax/offline/notonwhitelist.html
new file mode 100644
index 0000000000..7b61c68436
--- /dev/null
+++ b/dom/tests/mochitest/ajax/offline/notonwhitelist.html
@@ -0,0 +1,9 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Page NOT on whitelist</title>
+
+</head>
+<body onload="parent.notwhitelistOnLoad()">
+Page NOT on whitelist
+</body>
+</html>
diff --git a/dom/tests/mochitest/ajax/offline/obsolete.html b/dom/tests/mochitest/ajax/offline/obsolete.html
new file mode 100644
index 0000000000..6c76529e8c
--- /dev/null
+++ b/dom/tests/mochitest/ajax/offline/obsolete.html
@@ -0,0 +1,69 @@
+<html manifest="obsoletingManifest.sjs">
+<head>
+<title>obsolete test</title>
+<script type="text/javascript">
+
+function obsolete(evt)
+{
+ window.opener.ok(true, "Got an 'obsolete' event");
+
+ // The cache status is switched immediately AFTER sending the event,
+ // make sure that it isn't OBSOLETE yet...
+ window.opener.isnot(applicationCache.status, 5,
+ "Status should not yet be 5 (obsolete)");
+
+ // But check that it is after the event is fired.
+ setTimeout(function(){
+ window.opener.is(applicationCache.status, 5,
+ "Status should be 5 (obsolete)");
+
+ // Now swapCache(), and our new status should be UNCACHED.
+ applicationCache.swapCache();
+ window.opener.is(applicationCache.status, 0,
+ "Status should be 0 (UNCACHED)");
+ window.opener.finish();
+ }, 0);
+}
+
+function fail(evt)
+{
+ window.opener.ok(false, "Got an unexpected event: " + evt.type)
+ window.opener.finish();
+}
+
+applicationCache.oncached = function() {
+ // ok, we've successfully loaded from the initial cache.
+ try {
+ applicationCache.swapCache();
+ window.opener.todo(false, "We shouldn't have to swapCache in the oncached handler (bug 443023)");
+ } catch(e) {
+ }
+
+ // Now delete the manifest and refresh, we should get an "obsolete" message.
+ applicationCache.oncached = fail;
+ applicationCache.onupdateready = fail;
+ applicationCache.onnoupdate = fail;
+ applicationCache.onerror = fail;
+ applicationCache.onobsolete = obsolete;
+
+ // Make the obsoleting.sjs return 404 NOT FOUND code
+ var req = new XMLHttpRequest();
+ req.open("GET", "https://example.com/tests/dom/tests/mochitest/ajax/offline/obsoletingManifest.sjs?state=");
+ var channel = SpecialPowers.wrap(req).channel
+ .QueryInterface(SpecialPowers.Ci.nsIApplicationCacheChannel);
+ channel.chooseApplicationCache = false;
+ channel.inheritApplicationCache = false;
+ req.send("");
+ req.onreadystatechange = function() {
+ if (req.readyState == 4) {
+ applicationCache.update();
+ }
+ }
+}
+
+</script>
+</head>
+
+<body>
+<h1></h1>
+</body> </html>
diff --git a/dom/tests/mochitest/ajax/offline/obsoletingManifest.sjs b/dom/tests/mochitest/ajax/offline/obsoletingManifest.sjs
new file mode 100644
index 0000000000..f53dbeb79d
--- /dev/null
+++ b/dom/tests/mochitest/ajax/offline/obsoletingManifest.sjs
@@ -0,0 +1,31 @@
+var manifest =
+ "CACHE MANIFEST\n" +
+ "obsolete.html\n";
+
+function handleRequest(request, response)
+{
+ var match = request.queryString.match(/^state=(.*)$/);
+ if (match)
+ {
+ response.setStatusLine(request.httpVersion, 204, "No content");
+ response.setHeader("Cache-Control", "no-cache");
+ setState("offline.obsoletingManifest", match[1]);
+ }
+
+ if (request.queryString == "")
+ {
+ switch (getState("offline.obsoletingManifest"))
+ {
+ case "": // The default value
+ response.setStatusLine(request.httpVersion, 404, "Not found");
+ response.setHeader("Cache-Control", "no-cache");
+ break;
+ case "manifestPresent":
+ response.setStatusLine(request.httpVersion, 200, "Ok");
+ response.setHeader("Content-Type", "text/cache-manifest");
+ response.setHeader("Cache-Control", "no-cache");
+ response.write(manifest);
+ break;
+ }
+ }
+}
diff --git a/dom/tests/mochitest/ajax/offline/offlineChild.html b/dom/tests/mochitest/ajax/offline/offlineChild.html
new file mode 100644
index 0000000000..66ef74576e
--- /dev/null
+++ b/dom/tests/mochitest/ajax/offline/offlineChild.html
@@ -0,0 +1,33 @@
+<html>
+<head>
+<title></title>
+
+<script src="/tests/SimpleTest/SimpleTest.js"></script>
+<script type="text/javascript" src="/tests/dom/tests/mochitest/ajax/offline/offlineTests.js"></script>
+
+
+<script type="text/javascript">
+
+// This is called by the parent when the offline update is complete
+// (since we don't get those events)
+function doneLoading()
+{
+ window.parent.childFinished();
+}
+
+if (OfflineTest.setupChild()) {
+ // Child frames shouldn't be receiving cache events.
+ applicationCache.onerror = OfflineTest.failEvent;
+ applicationCache.onnoupdate = OfflineTest.failEvent;
+ applicationCache.ondownloading = OfflineTest.failEvent;
+ applicationCache.onprogress = OfflineTest.failEvent;
+ applicationCache.onupdateready = OfflineTest.failEvent;
+ applicationCache.oncached = OfflineTest.failEvent;
+}
+</script>
+
+</head>
+
+<body>
+
+</body> </html>
diff --git a/dom/tests/mochitest/ajax/offline/offlineTests.js b/dom/tests/mochitest/ajax/offline/offlineTests.js
new file mode 100644
index 0000000000..eb03f25f0a
--- /dev/null
+++ b/dom/tests/mochitest/ajax/offline/offlineTests.js
@@ -0,0 +1,390 @@
+// Utility functions for offline tests.
+var Cc = SpecialPowers.Cc;
+var Ci = SpecialPowers.Ci;
+var Cu = SpecialPowers.Cu;
+var LoadContextInfo = Cc["@mozilla.org/load-context-info-factory;1"].getService(Ci.nsILoadContextInfoFactory);
+var CommonUtils = Cu.import("resource://services-common/utils.js", {}).CommonUtils;
+
+const kNetBase = 2152398848; // 0x804B0000
+var NS_ERROR_CACHE_KEY_NOT_FOUND = kNetBase + 61;
+var NS_ERROR_CACHE_KEY_WAIT_FOR_VALIDATION = kNetBase + 64;
+
+// Reading the contents of multiple cache entries asynchronously
+function OfflineCacheContents(urls) {
+ this.urls = urls;
+ this.contents = {};
+}
+
+OfflineCacheContents.prototype = {
+QueryInterface: function(iid) {
+ if (!iid.equals(Ci.nsISupports) &&
+ !iid.equals(Ci.nsICacheEntryOpenCallback)) {
+ throw Cr.NS_ERROR_NO_INTERFACE;
+ }
+ return this;
+ },
+onCacheEntryCheck: function() { return Ci.nsICacheEntryOpenCallback.ENTRY_WANTED; },
+onCacheEntryAvailable: function(desc, isnew, applicationCache, status) {
+ if (!desc) {
+ this.fetch(this.callback);
+ return;
+ }
+
+ var stream = desc.openInputStream(0);
+ var sstream = Cc["@mozilla.org/scriptableinputstream;1"]
+ .createInstance(SpecialPowers.Ci.nsIScriptableInputStream);
+ sstream.init(stream);
+ this.contents[desc.key] = sstream.read(sstream.available());
+ sstream.close();
+ desc.close();
+ this.fetch(this.callback);
+ },
+
+fetch: function(callback)
+{
+ this.callback = callback;
+ if (this.urls.length == 0) {
+ callback(this.contents);
+ return;
+ }
+
+ var url = this.urls.shift();
+ var self = this;
+
+ var cacheStorage = OfflineTest.getActiveStorage();
+ cacheStorage.asyncOpenURI(CommonUtils.makeURI(url), "", Ci.nsICacheStorage.OPEN_READONLY,
+ SpecialPowers.wrapCallbackObject(this));
+}
+};
+
+var OfflineTest = {
+
+_hasSlave: false,
+
+// The window where test results should be sent.
+_masterWindow: null,
+
+// Array of all PUT overrides on the server
+_pathOverrides: [],
+
+// SJSs whom state was changed to be reverted on teardown
+_SJSsStated: [],
+
+setupChild: function()
+{
+ this._masterWindow = window;
+ return true;
+},
+
+/**
+ * Setup the tests. This will reload the current page in a new window
+ * if necessary.
+ *
+ * @return boolean Whether this window is the slave window
+ * to actually run the test in.
+ */
+setup: function()
+{
+ this._masterWindow = window;
+ return true;
+},
+
+teardownAndFinish: function()
+{
+ this.teardown(function(self) { self.finish(); });
+},
+
+teardown: function(callback)
+{
+ // First wait for any pending scheduled updates to finish
+ this.waitForUpdates(function(self) {
+ // Remove the offline-app permission we gave ourselves.
+
+ SpecialPowers.removePermission("offline-app", window.document);
+
+ // Clear all overrides on the server
+ for (override in self._pathOverrides)
+ self.deleteData(self._pathOverrides[override]);
+ for (statedSJS in self._SJSsStated)
+ self.setSJSState(self._SJSsStated[statedSJS], "");
+
+ self.clear();
+ callback(self);
+ });
+},
+
+finish: function()
+{
+ SimpleTest.executeSoon(SimpleTest.finish);
+},
+
+//
+// Mochitest wrappers - These forward tests to the proper mochitest window.
+//
+ok: function(condition, name)
+{
+ // Forward all arguments to SimpleTest.ok where we will check that ok() was
+ // called with at most 2 arguments.
+ return this._masterWindow.SimpleTest.ok.apply(this._masterWindow.SimpleTest,
+ arguments);
+},
+
+is: function(a, b, name)
+{
+ return this._masterWindow.SimpleTest.is(a, b, name);
+},
+
+isnot: function(a, b, name)
+{
+ return this._masterWindow.SimpleTest.isnot(a, b, name);
+},
+
+todo: function(a, name)
+{
+ return this._masterWindow.SimpleTest.todo(a, name);
+},
+
+clear: function()
+{
+ // XXX: maybe we should just wipe out the entire disk cache.
+ var applicationCache = this.getActiveCache();
+ if (applicationCache) {
+ applicationCache.discard();
+ }
+},
+
+waitForUpdates: function(callback)
+{
+ var self = this;
+ var observer = {
+ notified: false,
+ observe: function(subject, topic, data) {
+ if (subject) {
+ subject.QueryInterface(SpecialPowers.Ci.nsIOfflineCacheUpdate);
+ dump("Update of " + subject.manifestURI.spec + " finished\n");
+ }
+
+ SimpleTest.executeSoon(function() {
+ if (observer.notified) {
+ return;
+ }
+
+ var updateservice = Cc["@mozilla.org/offlinecacheupdate-service;1"]
+ .getService(SpecialPowers.Ci.nsIOfflineCacheUpdateService);
+ var updatesPending = updateservice.numUpdates;
+ if (updatesPending == 0) {
+ try {
+ SpecialPowers.removeObserver(observer, "offline-cache-update-completed");
+ } catch(ex) {}
+ dump("All pending updates done\n");
+ observer.notified = true;
+ callback(self);
+ return;
+ }
+
+ dump("Waiting for " + updateservice.numUpdates + " update(s) to finish\n");
+ });
+ }
+ }
+
+ SpecialPowers.addObserver(observer, "offline-cache-update-completed", false);
+
+ // Call now to check whether there are some updates scheduled
+ observer.observe();
+},
+
+failEvent: function(e)
+{
+ OfflineTest.ok(false, "Unexpected event: " + e.type);
+},
+
+// The offline API as specified has no way to watch the load of a resource
+// added with applicationCache.mozAdd().
+waitForAdd: function(url, onFinished) {
+ // Check every half second for ten seconds.
+ var numChecks = 20;
+
+ var waitForAddListener = SpecialPowers.wrapCallbackObject({
+ onCacheEntryCheck: function() { return Ci.nsICacheEntryOpenCallback.ENTRY_WANTED; },
+ onCacheEntryAvailable: function(entry, isnew, applicationCache, status) {
+ if (entry) {
+ entry.close();
+ onFinished();
+ return;
+ }
+
+ if (--numChecks == 0) {
+ onFinished();
+ return;
+ }
+
+ setTimeout(OfflineTest.priv(waitFunc), 500);
+ }
+ });
+
+ var waitFunc = function() {
+ var cacheStorage = OfflineTest.getActiveStorage();
+ cacheStorage.asyncOpenURI(CommonUtils.makeURI(url), "", Ci.nsICacheStorage.OPEN_READONLY, waitForAddListener);
+ }
+
+ setTimeout(this.priv(waitFunc), 500);
+},
+
+manifestURL: function(overload)
+{
+ var manifestURLspec;
+ if (overload) {
+ manifestURLspec = overload;
+ } else {
+ var win = window;
+ while (win && !win.document.documentElement.getAttribute("manifest")) {
+ if (win == win.parent)
+ break;
+ win = win.parent;
+ }
+ if (win)
+ manifestURLspec = win.document.documentElement.getAttribute("manifest");
+ }
+
+ var ios = Cc["@mozilla.org/network/io-service;1"]
+ .getService(Ci.nsIIOService)
+
+ var baseURI = ios.newURI(window.location.href);
+ return ios.newURI(manifestURLspec, null, baseURI);
+},
+
+loadContext: function()
+{
+ return SpecialPowers.wrap(window).docShell
+ .QueryInterface(SpecialPowers.Ci.nsILoadContext);
+},
+
+loadContextInfo: function()
+{
+ return LoadContextInfo.fromLoadContext(this.loadContext(), false);
+},
+
+getActiveCache: function(overload)
+{
+ // Note that this is the current active cache in the cache stack, not the
+ // one associated with this window.
+ var serv = Cc["@mozilla.org/network/application-cache-service;1"]
+ .getService(Ci.nsIApplicationCacheService);
+
+ var groupID = serv.buildGroupIDForInfo(this.manifestURL(overload), this.loadContextInfo());
+ var cache;
+ // Sometimes this throws a NS_ERROR_UNEXPECTED when cache isn't init
+ try {
+ cache = serv.getActiveCache(groupID);
+ } catch (e) {
+ cache = false;
+ }
+ return cache;
+},
+
+getActiveStorage: function()
+{
+ var cache = this.getActiveCache();
+ if (!cache) {
+ return null;
+ }
+
+ var cacheService = Cc["@mozilla.org/netwerk/cache-storage-service;1"]
+ .getService(Ci.nsICacheStorageService);
+ return cacheService.appCacheStorage(LoadContextInfo.default, cache);
+},
+
+priv: function(func)
+{
+ var self = this;
+ return function() {
+ func(arguments);
+ }
+},
+
+checkCacheEntries: function(entries, callback)
+{
+ var checkNextEntry = function() {
+ if (entries.length == 0) {
+ setTimeout(OfflineTest.priv(callback), 0);
+ } else {
+ OfflineTest.checkCache(entries[0][0], entries[0][1], checkNextEntry);
+ entries.shift();
+ }
+ }
+
+ checkNextEntry();
+},
+
+checkCache: function(url, expectEntry, callback)
+{
+ var cacheStorage = this.getActiveStorage();
+ this._checkCache(cacheStorage, url, expectEntry, callback);
+},
+
+_checkCache: function(cacheStorage, url, expectEntry, callback)
+{
+ if (!cacheStorage) {
+ if (expectEntry) {
+ this.ok(false, url + " should exist in the offline cache (no session)");
+ } else {
+ this.ok(true, url + " should not exist in the offline cache (no session)");
+ }
+ if (callback) setTimeout(this.priv(callback), 0);
+ return;
+ }
+
+ var _checkCacheListener = SpecialPowers.wrapCallbackObject({
+ onCacheEntryCheck: function() { return Ci.nsICacheEntryOpenCallback.ENTRY_WANTED; },
+ onCacheEntryAvailable: function(entry, isnew, applicationCache, status) {
+ if (entry) {
+ if (expectEntry) {
+ OfflineTest.ok(true, url + " should exist in the offline cache");
+ } else {
+ OfflineTest.ok(false, url + " should not exist in the offline cache");
+ }
+ entry.close();
+ } else {
+ if (status == NS_ERROR_CACHE_KEY_NOT_FOUND) {
+ if (expectEntry) {
+ OfflineTest.ok(false, url + " should exist in the offline cache");
+ } else {
+ OfflineTest.ok(true, url + " should not exist in the offline cache");
+ }
+ } else if (status == NS_ERROR_CACHE_KEY_WAIT_FOR_VALIDATION) {
+ // There was a cache key that we couldn't access yet, that's good enough.
+ if (expectEntry) {
+ OfflineTest.ok(!mustBeValid, url + " should exist in the offline cache");
+ } else {
+ OfflineTest.ok(mustBeValid, url + " should not exist in the offline cache");
+ }
+ } else {
+ OfflineTest.ok(false, "got invalid error for " + url);
+ }
+ }
+ if (callback) setTimeout(OfflineTest.priv(callback), 0);
+ }
+ });
+
+ cacheStorage.asyncOpenURI(CommonUtils.makeURI(url), "", Ci.nsICacheStorage.OPEN_READONLY, _checkCacheListener);
+},
+
+setSJSState: function(sjsPath, stateQuery)
+{
+ var client = new XMLHttpRequest();
+ client.open("GET", sjsPath + "?state=" + stateQuery, false);
+
+ var appcachechannel = SpecialPowers.wrap(client).channel.QueryInterface(Ci.nsIApplicationCacheChannel);
+ appcachechannel.chooseApplicationCache = false;
+ appcachechannel.inheritApplicationCache = false;
+ appcachechannel.applicationCache = null;
+
+ client.send();
+
+ if (stateQuery == "")
+ delete this._SJSsStated[sjsPath];
+ else
+ this._SJSsStated.push(sjsPath);
+}
+
+};
diff --git a/dom/tests/mochitest/ajax/offline/onwhitelist.html b/dom/tests/mochitest/ajax/offline/onwhitelist.html
new file mode 100644
index 0000000000..9e40cadbf2
--- /dev/null
+++ b/dom/tests/mochitest/ajax/offline/onwhitelist.html
@@ -0,0 +1,9 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Page on whitelist</title>
+
+</head>
+<body onload="parent.whitelistOnLoad(1)">
+Page on whitelist
+</body>
+</html>
diff --git a/dom/tests/mochitest/ajax/offline/onwhitelist.html^headers^ b/dom/tests/mochitest/ajax/offline/onwhitelist.html^headers^
new file mode 100644
index 0000000000..9e23c73b7f
--- /dev/null
+++ b/dom/tests/mochitest/ajax/offline/onwhitelist.html^headers^
@@ -0,0 +1 @@
+Cache-Control: no-cache
diff --git a/dom/tests/mochitest/ajax/offline/overlap.cacheManifest b/dom/tests/mochitest/ajax/offline/overlap.cacheManifest
new file mode 100644
index 0000000000..8b8e8c118a
--- /dev/null
+++ b/dom/tests/mochitest/ajax/offline/overlap.cacheManifest
@@ -0,0 +1,12 @@
+CACHE MANIFEST
+
+CACHE:
+https://example.com/tests/SimpleTest/SimpleTest.js
+https://example.com/tests/dom/tests/mochitest/ajax/offline/offlineTests.js
+
+NETWORK:
+bogus/specific/
+
+FALLBACK:
+# Fall back for a bogus namespace
+bogus/ fallback.html
diff --git a/dom/tests/mochitest/ajax/offline/overlap.cacheManifest^headers^ b/dom/tests/mochitest/ajax/offline/overlap.cacheManifest^headers^
new file mode 100644
index 0000000000..257f2eb60f
--- /dev/null
+++ b/dom/tests/mochitest/ajax/offline/overlap.cacheManifest^headers^
@@ -0,0 +1 @@
+Content-Type: text/cache-manifest
diff --git a/dom/tests/mochitest/ajax/offline/redirects.sjs b/dom/tests/mochitest/ajax/offline/redirects.sjs
new file mode 100644
index 0000000000..fb2e0ce902
--- /dev/null
+++ b/dom/tests/mochitest/ajax/offline/redirects.sjs
@@ -0,0 +1,52 @@
+ver1manifest =
+ "CACHE MANIFEST\n" +
+ "# v1\n" +
+ "\n" +
+ "https://example.com/tests/SimpleTest/SimpleTest.js\n" +
+ "https://example.com/tests/dom/tests/mochitest/ajax/offline/offlineTests.js\n" +
+ "https://example.com/tests/dom/tests/mochitest/ajax/offline/explicitRedirect.sjs";
+
+ver2manifest =
+ "CACHE MANIFEST\n" +
+ "# v2\n" +
+ "\n" +
+ "https://example.com/tests/SimpleTest/SimpleTest.js\n" +
+ "https://example.com/tests/dom/tests/mochitest/ajax/offline/offlineTests.js\n" +
+ "https://example.com/tests/dom/tests/mochitest/ajax/offline/explicitRedirect.sjs";
+
+ver3manifest =
+ "CACHE MANIFEST\n" +
+ "# v3\n" +
+ "\n" +
+ "https://example.com/tests/SimpleTest/SimpleTest.js\n" +
+ "https://example.com/tests/dom/tests/mochitest/ajax/offline/offlineTests.js\n" +
+ "https://example.com/tests/dom/tests/mochitest/ajax/offline/explicitRedirect.sjs";
+
+function handleRequest(request, response)
+{
+ var match = request.queryString.match(/^state=(.*)$/);
+ if (match)
+ {
+ response.setStatusLine(request.httpVersion, 204, "No content");
+ setState("state", match[1]);
+ }
+
+ if (request.queryString == "")
+ {
+ response.setStatusLine(request.httpVersion, 200, "Ok");
+ response.setHeader("Content-Type", "text/cache-manifest");
+ response.setHeader("Cache-Control", "no-cache");
+ switch (getState("state"))
+ {
+ case "": // The default value
+ response.write(ver1manifest + "\n#" + getState("state"));
+ break;
+ case "second":
+ response.write(ver2manifest + "\n#" + getState("state"));
+ break;
+ case "third":
+ response.write(ver3manifest + "\n#" + getState("state"));
+ break;
+ }
+ }
+}
diff --git a/dom/tests/mochitest/ajax/offline/simpleManifest.cacheManifest b/dom/tests/mochitest/ajax/offline/simpleManifest.cacheManifest
new file mode 100644
index 0000000000..c9d152bc5a
--- /dev/null
+++ b/dom/tests/mochitest/ajax/offline/simpleManifest.cacheManifest
@@ -0,0 +1,7 @@
+CACHE MANIFEST
+https://example.com/tests/SimpleTest/SimpleTest.js
+https://example.com/tests/dom/tests/mochitest/ajax/offline/offlineTests.js
+
+# The following item is not a valid URI and will be ignored
+bad:/uri/invalid
+
diff --git a/dom/tests/mochitest/ajax/offline/simpleManifest.cacheManifest^headers^ b/dom/tests/mochitest/ajax/offline/simpleManifest.cacheManifest^headers^
new file mode 100644
index 0000000000..5efde3c5b0
--- /dev/null
+++ b/dom/tests/mochitest/ajax/offline/simpleManifest.cacheManifest^headers^
@@ -0,0 +1,2 @@
+Content-Type: text/cache-manifest
+
diff --git a/dom/tests/mochitest/ajax/offline/subresource744719.html b/dom/tests/mochitest/ajax/offline/subresource744719.html
new file mode 100644
index 0000000000..86ba068ec2
--- /dev/null
+++ b/dom/tests/mochitest/ajax/offline/subresource744719.html
@@ -0,0 +1 @@
+<html><body>Dummy subresource</body></html> \ No newline at end of file
diff --git a/dom/tests/mochitest/ajax/offline/test_badManifestMagic.html b/dom/tests/mochitest/ajax/offline/test_badManifestMagic.html
new file mode 100644
index 0000000000..42c0bc8b2c
--- /dev/null
+++ b/dom/tests/mochitest/ajax/offline/test_badManifestMagic.html
@@ -0,0 +1,53 @@
+<html xmlns="http://www.w3.org/1999/xhtml" manifest="https://example.com/tests/dom/tests/mochitest/ajax/offline/badManifestMagic.cacheManifest">
+<head>
+<title>bad manifest magic</title>
+
+<script src="/tests/SimpleTest/SimpleTest.js"></script>
+<script type="text/javascript" src="/tests/dom/tests/mochitest/ajax/offline/offlineTests.js"></script>
+<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+
+<script type="text/javascript">
+
+var gGotChecking = false;
+
+function finishTest() {
+ OfflineTest.teardownAndFinish();
+}
+
+function handleError() {
+ OfflineTest.ok(gGotChecking, "Expected checking event");
+ OfflineTest.ok(true, "Expected error event");
+
+ // These items are listed in the manifest, but the error should have
+ // prevented them from being committed to the cache.
+ var entries = [
+ ["https://example.com/tests/SimpleTest/SimpleTest.js", false],
+ ["https://example.com/tests/dom/tests/mochitest/ajax/offline/offlineTests.js", false]
+ ];
+ OfflineTest.checkCacheEntries(entries, finishTest);
+}
+
+
+if (OfflineTest.setup()) {
+ // Don't expect a bunch of events.
+ applicationCache.ondownloading = OfflineTest.failEvent;
+ applicationCache.onupdateready = OfflineTest.failEvent;
+ applicationCache.oncached = OfflineTest.failEvent;
+ applicationCache.onnoupdate = OfflineTest.failEvent;
+ applicationCache.onprogress = OfflineTest.failEvent;
+
+ // ... but expect 'checking' and 'error'
+ applicationCache.onchecking = function() { gGotChecking = true; };
+ applicationCache.onerror = OfflineTest.priv(handleError);
+}
+
+SimpleTest.waitForExplicitFinish();
+
+</script>
+
+</head>
+
+<body>
+
+</body>
+</html>
diff --git a/dom/tests/mochitest/ajax/offline/test_bug445544.html b/dom/tests/mochitest/ajax/offline/test_bug445544.html
new file mode 100644
index 0000000000..c8054f3a66
--- /dev/null
+++ b/dom/tests/mochitest/ajax/offline/test_bug445544.html
@@ -0,0 +1,73 @@
+<html manifest="445544.cacheManifest">
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=445544
+-->
+
+<head>
+<title>Test for Bug 445544</title>
+
+<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+<script src="/tests/SimpleTest/SimpleTest.js"></script>
+<script type="text/javascript" src="/tests/dom/tests/mochitest/ajax/offline/offlineTests.js"></script>
+
+<script type="text/javascript">
+
+var gTestWin;
+var gTimeoutId;
+
+function finish()
+{
+ gTestWin.close();
+ OfflineTest.teardownAndFinish();
+}
+
+function error()
+{
+ OfflineTest.ok(false, "Part 2 did not successfully load.");
+ finish();
+}
+
+function part2loaded()
+{
+ clearTimeout(gTimeoutId);
+ OfflineTest.ok(true, "Part 2 successfully loaded.");
+ finish();
+}
+
+function part1loaded(appCacheStatus)
+{
+ OfflineTest.ok(appCacheStatus > 0,
+ "Part 1 successfully loaded from the application cache.");
+
+ // Loading part 2 (which is not part of that application
+ // cache) should succeed...
+ gTestWin.location = "445544_part2.html";
+
+ // We won't be notified if the page fails to load, fail this test
+ // in 10 seconds.
+ gTimeoutId = setTimeout(error, 10000);
+}
+
+function manifestUpdated()
+{
+ // Open a new window that will be associated with this application
+ // cache. This will call part1loaded().
+ gTestWin = window.open("445544_part1.html");
+}
+
+if (OfflineTest.setup()) {
+ applicationCache.onerror = OfflineTest.failEvent;
+ applicationCache.oncached = OfflineTest.priv(manifestUpdated);
+}
+
+SimpleTest.waitForExplicitFinish();
+SimpleTest.requestFlakyTimeout("untriaged");
+
+</script>
+
+</head>
+
+<body>
+
+</body>
+</html>
diff --git a/dom/tests/mochitest/ajax/offline/test_bug460353.html b/dom/tests/mochitest/ajax/offline/test_bug460353.html
new file mode 100644
index 0000000000..ac10d7a041
--- /dev/null
+++ b/dom/tests/mochitest/ajax/offline/test_bug460353.html
@@ -0,0 +1,100 @@
+<html xmlns="http://www.w3.org/1999/xhtml" manifest="https://example.com/tests/dom/tests/mochitest/ajax/offline/simpleManifest.cacheManifest">
+<head>
+<title>Bug 460353</title>
+
+<!--
+ This test checks that each iframe creates its own
+ scope. Actually, we just check that it loads and updates
+ its associated cache. There is no check that the cache is the
+ expected one, there is no API to gain that information.
+-->
+
+<script src="/tests/SimpleTest/SimpleTest.js"></script>
+<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+<script type="text/javascript" src="/tests/dom/tests/mochitest/ajax/offline/offlineTests.js"></script>
+
+<script class="testbody" type="text/javascript">
+
+var result = new Array();
+var expectedUpdates = 3; // 2 iframes and our self
+
+applicationCache.oncached = onUpdatePassed;
+applicationCache.onnoupdate = onUpdatePassed;
+
+SpecialPowers.pushPermissions([{'type': 'offline-app', 'allow': true, 'context': document}], init);
+
+function onUpdatePassed()
+{
+ if (!(--expectedUpdates))
+ SimpleTest.executeSoon(finish);
+}
+
+function init()
+{
+ var iframes = document.getElementsByTagName('iframe');
+ iframes[0].src = "460353_iframe_nomanifest.html";
+ iframes[1].src = "460353_iframe_ownmanifest.html";
+ iframes[2].src = "460353_iframe_samemanifest.html";
+}
+
+function frameOnLoad(frameid, status)
+{
+ var obj = new Object();
+ result[frameid] = obj;
+
+ result[frameid].load = true;
+ result[frameid].cacheStatus = status;
+}
+
+function frameOnUpdate(frameid, ok, status)
+{
+ result[frameid].update = true;
+ result[frameid].updateOK = ok;
+ result[frameid].cacheStatus = status;
+
+ onUpdatePassed();
+}
+
+function finish()
+{
+ SimpleTest.ok(result["same"].load || false, "Frame with the same manifest loads");
+ SimpleTest.ok(result["same"].update || false, "Frame with the same manifest cache update notification");
+ SimpleTest.ok(result["same"].updateOK || false, "Frame with the same manifest cache update passed OK");
+ SimpleTest.is(result["same"].cacheStatus || -1, 1, "Frame with the same manifest cache status was IDLE");
+
+ SimpleTest.ok(result["diff"].load || false, "Frame with different manifest loads");
+ SimpleTest.ok(result["diff"].update || false, "Frame with different manifest cache update notification");
+ SimpleTest.ok(result["diff"].updateOK || false, "Frame with different manifest cache update passed OK");
+ SimpleTest.is(result["diff"].cacheStatus || -1, 1, "Frame with different manifest cache status was IDLE");
+
+ SimpleTest.ok(result["noman"].load || false, "Frame with no manifest loads");
+ SimpleTest.ok(result["noman"].update == undefined, "Frame with no manifest cache update didn't notify");
+ SimpleTest.ok(result["noman"].updateOK == undefined, "Frame with no manifest cache update didn't pass");
+ SimpleTest.is(result["noman"].cacheStatus || -1, -1, "Frame with no manifest cache status was undefined");
+
+ OfflineTest.waitForUpdates(function() {
+ cleanCache("https://example.com/tests/dom/tests/mochitest/ajax/offline/simpleManifest.cacheManifest");
+ cleanCache("https://example.com/tests/dom/tests/mochitest/ajax/offline/updatingManifest.sjs");
+
+ SimpleTest.finish();
+ });
+}
+
+function cleanCache(manifestURL)
+{
+ var cache = OfflineTest.getActiveCache(manifestURL);
+ dump("Discarding cache for " + manifestURL + " cache=" + cache + "\n");
+ if (cache)
+ cache.discard();
+}
+
+SimpleTest.waitForExplicitFinish();
+
+</script>
+
+<body>
+ <iframe></iframe>
+ <iframe></iframe>
+ <iframe></iframe>
+</body>
+</html>
diff --git a/dom/tests/mochitest/ajax/offline/test_bug474696.html b/dom/tests/mochitest/ajax/offline/test_bug474696.html
new file mode 100644
index 0000000000..a178521309
--- /dev/null
+++ b/dom/tests/mochitest/ajax/offline/test_bug474696.html
@@ -0,0 +1,41 @@
+<html xmlns="http://www.w3.org/1999/xhtml" manifest="https://example.com/tests/dom/tests/mochitest/ajax/offline/fallback.cacheManifest">
+<head>
+<title>Fallback on different origin redirect test</title>
+
+<script src="/tests/SimpleTest/SimpleTest.js"></script>
+<script type="text/javascript" src="/tests/dom/tests/mochitest/ajax/offline/offlineTests.js"></script>
+<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+
+<script class="testbody" type="text/javascript">
+/* globals fallbackFrame */
+
+function manifestUpdated()
+{
+ fallbackFrame.location = "https://example.com/tests/dom/tests/mochitest/ajax/offline/namespace1/redirectToDifferentOrigin.sjs";
+ // Invokes load of fallback.html
+}
+
+function onFallbackLoad(fallbackIdentification)
+{
+ OfflineTest.is(fallbackIdentification, 1, "Got correct fallback for namespace1 (2)");
+
+ applicationCache.onerror = function() {}; // the update invoked by the iframe will finish after we discard the cache, ignore error
+ OfflineTest.teardownAndFinish();
+}
+
+SimpleTest.waitForExplicitFinish();
+
+if (OfflineTest.setup()) {
+ applicationCache.onerror = OfflineTest.failEvent;
+ applicationCache.onupdateready = OfflineTest.failEvent;
+ applicationCache.oncached = OfflineTest.priv(manifestUpdated);
+}
+
+</script>
+
+</head>
+
+<body>
+<iframe name="fallbackFrame"></iframe>
+</body>
+</html>
diff --git a/dom/tests/mochitest/ajax/offline/test_bug544462.html b/dom/tests/mochitest/ajax/offline/test_bug544462.html
new file mode 100644
index 0000000000..38ccbff7c7
--- /dev/null
+++ b/dom/tests/mochitest/ajax/offline/test_bug544462.html
@@ -0,0 +1,53 @@
+<html xmlns="http://www.w3.org/1999/xhtml" manifest="https://example.com/tests/dom/tests/mochitest/ajax/offline/wildcardManifest.cacheManifest">
+<head>
+<title>wildcard in network section test</title>
+
+<script src="/tests/SimpleTest/SimpleTest.js"></script>
+<script type="text/javascript" src="/tests/dom/tests/mochitest/ajax/offline/offlineTests.js"></script>
+<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+
+<style>
+ img {
+ max-width: 400px;
+ max-height: 400px;
+ }
+</style>
+
+<script type="text/javascript">
+
+var gImageLoaded = [];
+
+function imageOnLoad(idx)
+{
+ gImageLoaded[idx] = true;
+}
+
+function manifestUpdated()
+{
+ window.location.reload();
+}
+
+function finishTheTest()
+{
+ OfflineTest.is(gImageLoaded[1], true, "Image from a different origin not cointained in the offline cache has loaded");
+ OfflineTest.is(gImageLoaded[2], true, "Image not cointained in the offline cache has loaded");
+ OfflineTest.teardownAndFinish();
+}
+
+if (OfflineTest.setup()) {
+ applicationCache.onerror = OfflineTest.failEvent;
+ applicationCache.oncached = OfflineTest.priv(manifestUpdated);
+ applicationCache.onnoupdate = OfflineTest.priv(finishTheTest);
+}
+
+SimpleTest.waitForExplicitFinish();
+
+</script>
+
+</head>
+
+<body>
+ <img src="https://example.org/tests/dom/tests/mochitest/ajax/offline/jupiter.jpg" onload="imageOnLoad(1)" />
+ <img src="jupiter.jpg" onload="imageOnLoad(2)" />
+</body>
+</html>
diff --git a/dom/tests/mochitest/ajax/offline/test_bug744719-cancel.html b/dom/tests/mochitest/ajax/offline/test_bug744719-cancel.html
new file mode 100644
index 0000000000..c4dc850cbe
--- /dev/null
+++ b/dom/tests/mochitest/ajax/offline/test_bug744719-cancel.html
@@ -0,0 +1,84 @@
+<html xmlns="http://www.w3.org/1999/xhtml" manifest="https://example.com/tests/dom/tests/mochitest/ajax/offline/744719-cancel.cacheManifest">
+<head>
+<title>parallel load canceled</title>
+
+<script src="/tests/SimpleTest/SimpleTest.js"></script>
+<script type="text/javascript" src="/tests/dom/tests/mochitest/ajax/offline/offlineTests.js"></script>
+<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+
+<script type="text/javascript">
+
+/*
+ Manifest refers a large number of resource to load. The 10th item however is a reference to a non-existing
+ resource that cancels the load. This test checks we cancel all loads and don't leak any of the other resources
+ after cancelation.
+*/
+
+if (SpecialPowers.isMainProcess()) {
+ ok(applicationCache.mozItems.length == 0,
+ "applicationCache.mozItems should be available and empty before associating with a cache.");
+}
+
+function updateCanceled()
+{
+ OfflineTest.checkCache("https://example.com/tests/dom/tests/mochitest/ajax/offline/744719-cancel.cacheManifest", false, null);
+ OfflineTest.checkCache("https://example.com/tests/SimpleTest/SimpleTest.js", false, null);
+ OfflineTest.checkCache("https://example.com/tests/dom/tests/mochitest/ajax/offline/offlineTests.js", false, null);
+
+ OfflineTest.checkCache("https://example.com/tests/dom/tests/mochitest/ajax/offline/nonexistent744719?010", false, null);
+
+ var URL = "https://example.com/tests/dom/tests/mochitest/ajax/offline/subresource744719.html?";
+ OfflineTest.checkCache(URL + "001", false, null);
+ OfflineTest.checkCache(URL + "002", false, null);
+ OfflineTest.checkCache(URL + "003", false, null);
+ OfflineTest.checkCache(URL + "004", false, null);
+ OfflineTest.checkCache(URL + "005", false, null);
+ OfflineTest.checkCache(URL + "006", false, null);
+ OfflineTest.checkCache(URL + "007", false, null);
+ OfflineTest.checkCache(URL + "008", false, null);
+ OfflineTest.checkCache(URL + "009", false, null);
+ OfflineTest.checkCache(URL + "011", false, null);
+ OfflineTest.checkCache(URL + "012", false, null);
+ OfflineTest.checkCache(URL + "013", false, null);
+ OfflineTest.checkCache(URL + "014", false, null);
+ OfflineTest.checkCache(URL + "015", false, null);
+ OfflineTest.checkCache(URL + "016", false, null);
+ OfflineTest.checkCache(URL + "017", false, null);
+ OfflineTest.checkCache(URL + "018", false, null);
+ OfflineTest.checkCache(URL + "019", false, null);
+ OfflineTest.checkCache(URL + "020", false, null);
+ OfflineTest.checkCache(URL + "021", false, null);
+ OfflineTest.checkCache(URL + "022", false, null);
+ OfflineTest.checkCache(URL + "023", false, null);
+ OfflineTest.checkCache(URL + "024", false, null);
+ OfflineTest.checkCache(URL + "025", false, null);
+ OfflineTest.checkCache(URL + "026", false, null);
+ OfflineTest.checkCache(URL + "027", false, null);
+ OfflineTest.checkCache(URL + "028", false, null);
+ OfflineTest.checkCache(URL + "029", false, null);
+ OfflineTest.checkCache(URL + "030", false, null);
+
+ OfflineTest.teardownAndFinish();
+}
+
+if (OfflineTest.setup()) {
+ // Wait some time after the update has been canceled to catch potential leaks of channels that would cause
+ // unwanted items to be cached regardless the update has been canceled with a failure.
+ var privUpdateCanceled = OfflineTest.priv(updateCanceled);
+ applicationCache.onerror = function() {window.setTimeout(privUpdateCanceled, 1000)};
+
+ // We don't expect this update to finish correctly.
+ applicationCache.oncached = OfflineTest.failEvent;
+}
+
+SimpleTest.waitForExplicitFinish();
+SimpleTest.requestFlakyTimeout("untriaged");
+
+</script>
+
+</head>
+
+<body>
+
+</body>
+</html>
diff --git a/dom/tests/mochitest/ajax/offline/test_bug744719.html b/dom/tests/mochitest/ajax/offline/test_bug744719.html
new file mode 100644
index 0000000000..815d3db58e
--- /dev/null
+++ b/dom/tests/mochitest/ajax/offline/test_bug744719.html
@@ -0,0 +1,77 @@
+<html xmlns="http://www.w3.org/1999/xhtml" manifest="/tests/dom/tests/mochitest/ajax/offline/744719.cacheManifest">
+<head>
+<title>parallel load</title>
+
+<script src="/tests/SimpleTest/SimpleTest.js"></script>
+<script type="text/javascript" src="/tests/dom/tests/mochitest/ajax/offline/offlineTests.js"></script>
+<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+
+<script type="text/javascript">
+
+/*
+ Simply load a large number of resources and check all are properly cached. This should cover all parts
+ of the parallel loading code.
+*/
+
+if (SpecialPowers.isMainProcess()) {
+ ok(applicationCache.mozItems.length == 0,
+ "applicationCache.mozItems should be available and empty before associating with a cache.");
+}
+
+function manifestUpdated()
+{
+ok(window.location.href, "my loc" + window.location.href);
+ OfflineTest.checkCache("https://example.com/tests/dom/tests/mochitest/ajax/offline/744719.cacheManifest", true);
+ OfflineTest.checkCache("https://example.com/tests/SimpleTest/SimpleTest.js", true);
+ OfflineTest.checkCache("https://example.com/tests/dom/tests/mochitest/ajax/offline/offlineTests.js", true);
+
+ var URL = "https://example.com/tests/dom/tests/mochitest/ajax/offline/subresource744719.html?";
+ OfflineTest.checkCache(URL + "001", true);
+ OfflineTest.checkCache(URL + "002", true);
+ OfflineTest.checkCache(URL + "003", true);
+ OfflineTest.checkCache(URL + "004", true);
+ OfflineTest.checkCache(URL + "005", true);
+ OfflineTest.checkCache(URL + "006", true);
+ OfflineTest.checkCache(URL + "007", true);
+ OfflineTest.checkCache(URL + "008", true);
+ OfflineTest.checkCache(URL + "009", true);
+ OfflineTest.checkCache(URL + "010", true);
+ OfflineTest.checkCache(URL + "011", true);
+ OfflineTest.checkCache(URL + "012", true);
+ OfflineTest.checkCache(URL + "013", true);
+ OfflineTest.checkCache(URL + "014", true);
+ OfflineTest.checkCache(URL + "015", true);
+ OfflineTest.checkCache(URL + "016", true);
+ OfflineTest.checkCache(URL + "017", true);
+ OfflineTest.checkCache(URL + "018", true);
+ OfflineTest.checkCache(URL + "019", true);
+ OfflineTest.checkCache(URL + "020", true);
+ OfflineTest.checkCache(URL + "021", true);
+ OfflineTest.checkCache(URL + "022", true);
+ OfflineTest.checkCache(URL + "023", true);
+ OfflineTest.checkCache(URL + "024", true);
+ OfflineTest.checkCache(URL + "025", true);
+ OfflineTest.checkCache(URL + "026", true);
+ OfflineTest.checkCache(URL + "027", true);
+ OfflineTest.checkCache(URL + "028", true);
+ OfflineTest.checkCache(URL + "029", true);
+ OfflineTest.checkCache(URL + "030", true, function() {
+ OfflineTest.teardownAndFinish();
+ });
+}
+
+if (OfflineTest.setup()) {
+ applicationCache.onerror = OfflineTest.failEvent;
+ applicationCache.oncached = OfflineTest.priv(manifestUpdated);
+}
+
+SimpleTest.waitForExplicitFinish();
+
+</script>
+
+</head>
+
+<body>
+
+</body>
+</html>
diff --git a/dom/tests/mochitest/ajax/offline/test_bug765203.html b/dom/tests/mochitest/ajax/offline/test_bug765203.html
new file mode 100644
index 0000000000..734e565e94
--- /dev/null
+++ b/dom/tests/mochitest/ajax/offline/test_bug765203.html
@@ -0,0 +1,73 @@
+<html xmlns="http://www.w3.org/1999/xhtml" manifest="https://example.com/tests/dom/tests/mochitest/ajax/offline/unknownSection.cacheManifest">
+<head>
+<title>unknown section</title>
+
+<script src="/tests/SimpleTest/SimpleTest.js"></script>
+<script type="text/javascript" src="/tests/dom/tests/mochitest/ajax/offline/offlineTests.js"></script>
+<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+
+<script type="text/javascript">
+
+var gGotChecking = false;
+var gGotDownloading = false;
+
+function manifestUpdated()
+{
+ OfflineTest.ok(gGotChecking, "Should get a checking event");
+ OfflineTest.ok(gGotDownloading, "Should get a downloading event");
+
+ OfflineTest.is(applicationCache.status, 1, "Cache status should be 1 (CACHED)");
+
+ var entries = [
+ // The manifest itself should be in the cache
+ ["https://example.com/tests/dom/tests/mochitest/ajax/offline/unknownSection.cacheManifest", true],
+
+ // The document that requested the manifest should be in the cache
+ [window.location.href, true],
+
+ // The entries from the manifest should be in the cache
+ ["https://example.com/tests/SimpleTest/SimpleTest.js", true],
+ ["https://example.com/tests/dom/tests/mochitest/ajax/offline/offlineTests.js", true],
+
+ // The bad entries from the manifest should not be in the cache
+ ["https://example.com/tests/dom/tests/mochitest/ajax/offline/jupiter.jpg", false]
+ ];
+ OfflineTest.checkCacheEntries(
+ entries,
+ function() {
+ OfflineTest.teardownAndFinish();
+ });
+}
+
+if (OfflineTest.setup()) {
+ OfflineTest.ok(applicationCache instanceof EventTarget,
+ "applicationCache should be an event target");
+
+ applicationCache.onerror = OfflineTest.failEvent;
+
+ applicationCache.addEventListener("checking", function() {
+ // We should get the "checking" event during an initial update,
+ // but until we are associated it will not affect applicationCache.status
+ OfflineTest.is(applicationCache.status, applicationCache.UNCACHED,
+ "CHECKING state during initial update");
+ gGotChecking = true;
+ }, true);
+ applicationCache.ondownloading = function() {
+ // We should get the "downloading" event during an initial update,
+ // but until we are associated it will not affect applicationCache.status
+ OfflineTest.is(applicationCache.status, applicationCache.UNCACHED,
+ "DOWNLOADING state during initial update")
+ gGotDownloading = true; };
+ applicationCache.oncached = OfflineTest.priv(manifestUpdated);
+}
+
+SimpleTest.waitForExplicitFinish();
+
+</script>
+
+</head>
+
+<body>
+
+</body>
+</html>
diff --git a/dom/tests/mochitest/ajax/offline/test_bypass.html b/dom/tests/mochitest/ajax/offline/test_bypass.html
new file mode 100644
index 0000000000..27e91ca12d
--- /dev/null
+++ b/dom/tests/mochitest/ajax/offline/test_bypass.html
@@ -0,0 +1,37 @@
+<html xmlns="http://www.w3.org/1999/xhtml" manifest="bypass.cacheManifest">
+<head>
+<title>Bypass test</title>
+
+<script src="/tests/SimpleTest/SimpleTest.js"></script>
+<script type="text/javascript" src="/tests/dom/tests/mochitest/ajax/offline/offlineTests.js"></script>
+<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+
+<script class="testbody" type="text/javascript">
+
+/**
+ * This test defines manifest with namespace1/sub2 and namespace2 as bypass
+ * namespaces.
+ * When cache update finishes it loads a test body in an iframe. This iframe
+ * refers four js scripts, some matching the namespace to bypass and some not.
+ * Then checks that just expected scripts loads by calling a method of each
+ * of the script.
+ */
+
+SimpleTest.waitForExplicitFinish();
+
+if (OfflineTest.setup()) {
+ // Load test body when cache update process finished. The test itself
+ // continues at that file.
+ applicationCache.oncached = function()
+ {
+ window.open("bypass.html");
+ }
+}
+
+</script>
+
+</head>
+
+<body>
+</body>
+</html>
diff --git a/dom/tests/mochitest/ajax/offline/test_cancelOfflineCache.html b/dom/tests/mochitest/ajax/offline/test_cancelOfflineCache.html
new file mode 100644
index 0000000000..91360be7e3
--- /dev/null
+++ b/dom/tests/mochitest/ajax/offline/test_cancelOfflineCache.html
@@ -0,0 +1,58 @@
+<html xmlns="http://www.w3.org/1999/xhtml" manifest="https://example.com/tests/dom/tests/mochitest/ajax/offline/simpleManifest.cacheManifest">
+<head>
+<title>Cancel offline cache</title>
+
+<script src="/tests/SimpleTest/SimpleTest.js"></script>
+<script type="text/javascript" src="/tests/dom/tests/mochitest/ajax/offline/offlineTests.js"></script>
+<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+
+<script type="text/javascript">
+
+var manifest = "https://example.com/tests/dom/tests/mochitest/ajax/offline/simpleManifest.cacheManifest";
+var manifestURI = Cc["@mozilla.org/network/io-service;1"]
+ .getService(Ci.nsIIOService)
+ .newURI(manifest);
+var updateService = Cc['@mozilla.org/offlinecacheupdate-service;1']
+ .getService(Ci.nsIOfflineCacheUpdateService);
+
+function manifestCached () {
+ OfflineTest.ok(false, "The update was supposed to be canceled");
+
+ OfflineTest.teardownAndFinish();
+}
+
+function onError () {
+ OfflineTest.ok(true, "Expected error: Update canceled");
+
+ OfflineTest.teardownAndFinish();
+}
+
+function onProgress () {
+ var i = 0;
+ while (i < updateService.numUpdates) {
+ var update = updateService.getUpdate(i);
+ if (update.manifestURI.spec == manifestURI.spec) {
+ update.cancel();
+ return;
+ }
+ i++;
+ }
+}
+
+if (OfflineTest.setup()) {
+ applicationCache.onerror = OfflineTest.priv(onError);
+ applicationCache.onnoupdate = OfflineTest.failEvent;
+ applicationCache.onprogress = OfflineTest.priv(onProgress);
+ applicationCache.oncached = OfflineTest.priv(manifestCached);
+}
+
+SimpleTest.waitForExplicitFinish();
+
+</script>
+
+</head>
+
+<body>
+
+</body>
+</html>
diff --git a/dom/tests/mochitest/ajax/offline/test_changingManifest.html b/dom/tests/mochitest/ajax/offline/test_changingManifest.html
new file mode 100644
index 0000000000..6af5c4c56a
--- /dev/null
+++ b/dom/tests/mochitest/ajax/offline/test_changingManifest.html
@@ -0,0 +1,116 @@
+<html xmlns="http://www.w3.org/1999/xhtml" manifest="https://example.com/tests/dom/tests/mochitest/ajax/offline/changingManifest.sjs">
+<head>
+<title>changing manifest test</title>
+
+<script src="/tests/SimpleTest/SimpleTest.js"></script>
+<script type="text/javascript" src="/tests/dom/tests/mochitest/ajax/offline/offlineTests.js"></script>
+<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+
+<script type="text/javascript">
+
+var gGotChecking = false;
+var gGotDownloading = false;
+
+var g1SecUrl = "https://example.com/tests/dom/tests/mochitest/ajax/offline/changing1Sec.sjs";
+var g1HourUrl = "https://example.com/tests/dom/tests/mochitest/ajax/offline/changing1Hour.sjs";
+
+var gCacheContents = null;
+
+function finish()
+{
+ OfflineTest.teardownAndFinish();
+}
+
+function manifestUpdatedAgain()
+{
+ OfflineTest.ok(gGotChecking, "Should get a checking event on the second update");
+ OfflineTest.ok(gGotDownloading, "Should get a downloading event on the second update");
+
+ // The second manifest has no NETWORK entry, but we are still
+ // associated with the first version of the manifest, so we should
+ // be able to access the whitelisted entry.
+ try {
+ var xhr = new XMLHttpRequest();
+ xhr.open("GET", "onwhitelist.html", false);
+ xhr.send();
+ OfflineTest.ok(true, "Fetched from the initial cache's whitelist.");
+ } catch (e) {
+ OfflineTest.ok(false, "Failed to fetch from the initial cache's whitelist.");
+ }
+
+ // Get the initial contents of the first two files.
+ fetcher = new OfflineCacheContents([g1SecUrl, g1HourUrl]);
+ fetcher.fetch(function(contents) {
+ // Make sure the contents of the 1-second-expiration file have changed,
+ // but that the 1-hour-expiration has not.
+ OfflineTest.isnot(gCacheContents[g1SecUrl], contents[g1SecUrl], "1-second expiration should have changed");
+ OfflineTest.is(gCacheContents[g1HourUrl], contents[g1HourUrl], "1-hour expiration should not have changed");
+
+ finish();
+ });
+}
+
+function failAndFinish(e) {
+ OfflineTest.ok(false, "Unexpected event: " + e.type);
+ finish();
+}
+
+function manifestUpdated()
+{
+ OfflineTest.ok(gGotChecking, "Should get a checking event");
+ OfflineTest.ok(gGotDownloading, "Should get a downloading event");
+
+ // Replace this manifest with a new one.
+ OfflineTest.setSJSState("changingManifest.sjs", "2");
+
+ // Get the initial contents of the first two files.
+ fetcher = new OfflineCacheContents([g1SecUrl, g1HourUrl]);
+ fetcher.fetch(function(contents) {
+ gCacheContents = contents;
+
+ // Now make sure applicationCache.update() does what we expect.
+ applicationCache.onchecking = function() {
+ OfflineTest.is(applicationCache.status, applicationCache.CHECKING,
+ "CHECKING state during update");
+ gGotChecking = true;
+ };
+ applicationCache.ondownloading = function() {
+ OfflineTest.is(applicationCache.status, applicationCache.DOWNLOADING,
+ "DOWNLOADING state during update");
+ gGotDownloading = true;
+ };
+
+ applicationCache.onupdateready = OfflineTest.priv(manifestUpdatedAgain);
+ applicationCache.onnoupdate = failAndFinish;
+ applicationCache.oncached = failAndFinish;
+
+ gGotChecking = false;
+ gGotDownloading = false;
+
+ // The changing versions give out a new version each second,
+ // make sure it has time to grab a new version, and for the
+ // 1-second cache timeout to pass.
+ window.setTimeout("applicationCache.update()", 5000);
+ });
+}
+
+if (OfflineTest.setup()) {
+ applicationCache.onerror = failAndFinish;
+ applicationCache.onnoupdate = failAndFinish;
+
+ applicationCache.onchecking = function() { gGotChecking = true; };
+ applicationCache.ondownloading = function() { gGotDownloading = true; };
+ applicationCache.oncached = OfflineTest.priv(manifestUpdated);
+}
+
+SimpleTest.waitForExplicitFinish();
+SimpleTest.requestFlakyTimeout("untriaged");
+
+</script>
+
+</head>
+
+<body>
+
+</body>
+</html>
diff --git a/dom/tests/mochitest/ajax/offline/test_fallback.html b/dom/tests/mochitest/ajax/offline/test_fallback.html
new file mode 100644
index 0000000000..5dce657eb5
--- /dev/null
+++ b/dom/tests/mochitest/ajax/offline/test_fallback.html
@@ -0,0 +1,129 @@
+<html xmlns="http://www.w3.org/1999/xhtml" manifest="https://example.com/tests/dom/tests/mochitest/ajax/offline/fallback.cacheManifest">
+<head>
+<title>Fallback entry test</title>
+
+<script src="/tests/SimpleTest/SimpleTest.js"></script>
+<script type="text/javascript" src="/tests/dom/tests/mochitest/ajax/offline/offlineTests.js"></script>
+<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+
+<script class="testbody" type="text/javascript">
+/* globals fallbackFrame */
+
+/**
+ * This tests that we fall back to the correct fallback entries when loading
+ * from fallback namespaces listed in the manifest. The test is performed twice
+ * to make sure that no cache entries are created for the nonexistent items."
+ * That would lead to a failure to fallback, as there would always be an entry
+ * in the application cache.
+ */
+
+var gStep = 1;
+var gChildLoad = false;
+var gTopWindow = null;
+
+function manifestUpdated()
+{
+ fallbackFrame.location = "https://example.com/tests/dom/tests/mochitest/ajax/offline/namespace1/non-existing.html";
+ // Invokes load of fallback.html
+}
+
+function onFallbackLoad(fallbackIdentification)
+{
+ switch (gStep)
+ {
+ case 001:
+ OfflineTest.ok(!gChildLoad, "offline child not load before cache update");
+ gChildLoad = true;
+ // no break
+ case 101:
+ OfflineTest.is(fallbackIdentification, 1, "fallback for namespace1/ in step " + gStep);
+
+ fallbackFrame.location = "https://example.com/tests/dom/tests/mochitest/ajax/offline/namespace1/sub-non-existing.html";
+ // Invokes load of fallback.html
+ break;
+
+ case 002:
+ case 102:
+ OfflineTest.is(fallbackIdentification, 1, "fallback for namespace1/, sub namespace in name of the frame in step " + gStep);
+
+ fallbackFrame.location = "https://example.com/tests/dom/tests/mochitest/ajax/offline/namespace1/sub/non-existing.html";
+ // Invokes load of fallback2.html
+ break;
+
+ case 003:
+ case 103:
+ OfflineTest.is(fallbackIdentification, 2, "fallback for namespace1/sub/ in step " + gStep);
+
+ fallbackFrame.location = "HTTPS://EXAMPLE.COM/tests/dom/tests/mochitest/ajax/offline/namespace1/sub/non-existing.html";
+ // Invokes load of fallback2.html
+ break;
+
+ case 004:
+ case 104:
+ OfflineTest.is(fallbackIdentification, 2, "fallback for namespace1/sub/ in step " + gStep);
+
+ // Try opening a non-existing page as a top level document. It must
+ // fall to fallbackTop.html that identifies it self as '100'.
+ // Invokes load of fallbackTop.html
+ gTopWindow = window.open("https://example.com/tests/dom/tests/mochitest/ajax/offline/namespace2/non-existing.html");
+
+ break;
+
+ case 005:
+ // Try all over again. This checks there are no entries for non-existing
+ // pages created/leaked. That would prevent fallback load.
+ gStep = 100;
+
+ fallbackFrame.location = "https://example.com/tests/dom/tests/mochitest/ajax/offline/namespace1/non-existing.html";
+ // Invokes load of fallback1.html, again, from the start
+ // no break
+ case 105:
+ OfflineTest.is(fallbackIdentification, 100, "fallback for namespace2/, invoked by a top level document " + gStep);
+
+ gTopWindow.close();
+ gTopWindow = null;
+
+ break;
+ }
+
+ if (gStep == 105) {
+ finalize();
+ return;
+ }
+
+ ++gStep;
+}
+
+
+function finishTest()
+{
+ OfflineTest.teardownAndFinish();
+}
+
+function finalize()
+{
+ var entries = [
+ ["https://example.com/tests/dom/tests/mochitest/ajax/offline/namespace1/sub-non-existing.html", false],
+ ["https://example.com/tests/dom/tests/mochitest/ajax/offline/namespace1/sub/non-existing.html", false],
+ ["https://example.com/tests/dom/tests/mochitest/ajax/offline/namespace1/non-existing.html", false],
+ ["https://example.com/tests/dom/tests/mochitest/ajax/offline/namespace2/non-existing.html", false]
+ ];
+ OfflineTest.checkCacheEntries(entries, finishTest);
+}
+
+SimpleTest.waitForExplicitFinish();
+
+if (OfflineTest.setup()) {
+ applicationCache.onerror = OfflineTest.failEvent;
+ applicationCache.onupdateready = OfflineTest.failEvent;
+ applicationCache.oncached = OfflineTest.priv(manifestUpdated);
+}
+
+</script>
+
+</head>
+
+<body>
+<iframe name="fallbackFrame" src=""></iframe>
+</body>
+</html>
diff --git a/dom/tests/mochitest/ajax/offline/test_foreign.html b/dom/tests/mochitest/ajax/offline/test_foreign.html
new file mode 100644
index 0000000000..fec4d1cd29
--- /dev/null
+++ b/dom/tests/mochitest/ajax/offline/test_foreign.html
@@ -0,0 +1,60 @@
+<html xmlns="http://www.w3.org/1999/xhtml" manifest="https://example.com/tests/dom/tests/mochitest/ajax/offline/foreign1.cacheManifest">
+<head>
+<title>Foreign test</title>
+
+<script src="/tests/SimpleTest/SimpleTest.js"></script>
+<script type="text/javascript" src="/tests/dom/tests/mochitest/ajax/offline/offlineTests.js"></script>
+<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+
+<script class="testbody" type="text/javascript">
+/* globals foreign1cache */
+
+/**
+ * This test loads a manifest that contains as an explicit entry
+ * foreign2.html page. After manifest is cached and presence of the
+ * foreign2.html page is checked we redirect to foreign2.html
+ * page. Then the test continues inside that page as follows:
+ * On load of foreign2.html we check there is no associated cache
+ * because the foreign2.html page was marked as FOREIGN in foreign1 cache.
+ * After the foreign2 manifest is updated we check foreign2 cache is
+ * chosen by foreign.html page.
+ */
+
+var win;
+
+function manifestUpdated()
+{
+ var appCacheService = SpecialPowers.Cc["@mozilla.org/network/application-cache-service;1"]
+ .getService(SpecialPowers.Ci.nsIApplicationCacheService);
+
+ foreign1cache = appCacheService.chooseApplicationCache(
+ "https://example.com/tests/dom/tests/mochitest/ajax/offline/foreign2.html", OfflineTest.loadContextInfo());
+
+ OfflineTest.ok(foreign1cache, "foreign2.html chosen from foreign1 cache");
+ OfflineTest.is(foreign1cache.manifestURI.asciiSpec, "https://example.com/tests/dom/tests/mochitest/ajax/offline/foreign1.cacheManifest");
+
+ win = window.open("https://example.com/tests/dom/tests/mochitest/ajax/offline/foreign2.html");
+}
+
+function onDone() // called by the open window after stuff is finished
+{
+ win.close();
+ OfflineTest.teardownAndFinish();
+}
+
+SimpleTest.waitForExplicitFinish();
+
+if (OfflineTest.setup()) {
+ applicationCache.onerror = OfflineTest.failEvent;
+ applicationCache.onupdateready = OfflineTest.failEvent;
+ applicationCache.onnoupdate = OfflineTest.failEvent;
+ applicationCache.oncached = OfflineTest.priv(manifestUpdated);
+}
+
+</script>
+
+</head>
+
+<body>
+</body>
+</html>
diff --git a/dom/tests/mochitest/ajax/offline/test_identicalManifest.html b/dom/tests/mochitest/ajax/offline/test_identicalManifest.html
new file mode 100644
index 0000000000..466d7807cd
--- /dev/null
+++ b/dom/tests/mochitest/ajax/offline/test_identicalManifest.html
@@ -0,0 +1,86 @@
+<html xmlns="http://www.w3.org/1999/xhtml" manifest="https://example.com/tests/dom/tests/mochitest/ajax/offline/simpleManifest.cacheManifest">
+<head>
+<title>identical manifest test</title>
+
+<script src="/tests/SimpleTest/SimpleTest.js"></script>
+<script type="text/javascript" src="/tests/dom/tests/mochitest/ajax/offline/offlineTests.js"></script>
+<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+
+<script type="text/javascript">
+
+var gGotChecking = false;
+var gGotDownloading = false;
+
+function finishTest()
+{
+ OfflineTest.teardownAndFinish();
+}
+
+function noUpdate()
+{
+ OfflineTest.ok(gGotChecking, "Should get a checking event");
+ OfflineTest.ok(!gGotDownloading, "Should not get a downloading event");
+
+ var entries = [
+ // The document that requested the manifest should be in the cache
+ [window.location.href, true],
+
+ ["https://example.com/tests/SimpleTest/SimpleTest.js", true],
+ ["https://example.com/tests/dom/tests/mochitest/ajax/offline/offlineTests.js", true]
+ ];
+ OfflineTest.checkCacheEntries(entries, finishTest);
+}
+
+function manifestUpdated()
+{
+ OfflineTest.ok(gGotChecking, "Should get a checking event");
+ OfflineTest.ok(gGotDownloading, "Should get a downloading event");
+
+ var entries = [
+ // The manifest itself should be in the cache
+ ["https://example.com/tests/dom/tests/mochitest/ajax/offline/simpleManifest.cacheManifest", true],
+
+ // The document that requested the manifest should be in the cache
+ [window.location.href, true],
+
+ // The entries from the manifest should be in the cache
+ ["https://example.com/tests/SimpleTest/SimpleTest.js", true],
+ ["https://example.com/tests/dom/tests/mochitest/ajax/offline/offlineTests.js", true],
+
+ // The bad entries from the manifest should not be in the cache
+ ["bad:/uri/invalid", false]
+ ];
+ OfflineTest.checkCacheEntries(entries, manifestUpdatedContinue);
+}
+
+function manifestUpdatedContinue()
+{
+ // Now make sure applicationCache.update() does what we expect.
+ applicationCache.oncached = OfflineTest.failEvent;
+ applicationCache.onnoupdate = OfflineTest.priv(noUpdate);
+
+ gGotChecking = false;
+ gGotDownloading = false;
+ applicationCache.update();
+}
+
+if (OfflineTest.setup()) {
+ applicationCache.onerror = OfflineTest.failEvent;
+ applicationCache.onnoupdate = OfflineTest.failEvent;
+ applicationCache.onudpateready = OfflineTest.failEvent;
+
+ applicationCache.onchecking = function() { gGotChecking = true; };
+ applicationCache.ondownloading = function() { gGotDownloading = true; };
+ applicationCache.oncached = OfflineTest.priv(manifestUpdated);
+}
+
+SimpleTest.waitForExplicitFinish();
+
+</script>
+
+</head>
+
+<body>
+
+</body>
+</html>
diff --git a/dom/tests/mochitest/ajax/offline/test_missingFile.html b/dom/tests/mochitest/ajax/offline/test_missingFile.html
new file mode 100644
index 0000000000..f06e445b88
--- /dev/null
+++ b/dom/tests/mochitest/ajax/offline/test_missingFile.html
@@ -0,0 +1,53 @@
+<html xmlns="http://www.w3.org/1999/xhtml" manifest="https://example.com/tests/dom/tests/mochitest/ajax/offline/missingFile.cacheManifest">
+<head>
+<title>missing manifest file test</title>
+
+<script src="/tests/SimpleTest/SimpleTest.js"></script>
+<script type="text/javascript" src="/tests/dom/tests/mochitest/ajax/offline/offlineTests.js"></script>
+<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+
+<script type="text/javascript">
+
+var gGotChecking = false;
+var gGotDownloading = false;
+
+function finishTest() {
+ OfflineTest.teardownAndFinish();
+}
+
+function handleError() {
+ OfflineTest.ok(gGotChecking, "Expected checking event");
+ OfflineTest.ok(gGotDownloading, "Expected downloading event");
+ OfflineTest.ok(true, "Expected error event");
+
+ // These items are listed in the manifest, but the error should have
+ // prevented them from being committed to the cache.
+ var entries = [
+ ["https://example.com/tests/SimpleTest/SimpleTest.js", false],
+ ["https://example.com/tests/dom/tests/mochitest/ajax/offline/offlineTests.js", false]
+ ];
+ OfflineTest.checkCacheEntries(entries, finishTest);
+}
+
+if (OfflineTest.setup()) {
+ // Don't expect any "success" events.
+ applicationCache.onupdateready = function() { OfflineTest.failEvent("updateready"); }
+ applicationCache.oncached = function() { OfflineTest.failEvent("cached"); }
+ applicationCache.onnoupdate = function() { OfflineTest.failEvent("noupdate"); }
+
+ applicationCache.ondownloading = function() { gGotDownloading = true; };
+ applicationCache.onchecking = function() { gGotChecking = true; };
+ applicationCache.onerror = OfflineTest.priv(handleError);
+}
+
+SimpleTest.waitForExplicitFinish();
+
+
+</script>
+
+</head>
+
+<body>
+
+</body>
+</html>
diff --git a/dom/tests/mochitest/ajax/offline/test_missingManifest.html b/dom/tests/mochitest/ajax/offline/test_missingManifest.html
new file mode 100644
index 0000000000..2fb764371f
--- /dev/null
+++ b/dom/tests/mochitest/ajax/offline/test_missingManifest.html
@@ -0,0 +1,33 @@
+<html>
+<head>
+<title>Test missing manifest</title>
+
+<script src="/tests/SimpleTest/SimpleTest.js"></script>
+<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+
+<script type="text/javascript">
+
+var gTestWin;
+
+SimpleTest.waitForExplicitFinish();
+
+SpecialPowers.pushPermissions([{'type': 'offline-app', 'allow': true, 'context': document}], startTest);
+
+function startTest() {
+ // now this will properly load the manifest.
+ gTestWin = window.open("missing.html");
+}
+
+function finish() {
+ gTestWin.close();
+ SimpleTest.finish();
+}
+
+</script>
+
+</head>
+
+<body>
+
+</body>
+</html>
diff --git a/dom/tests/mochitest/ajax/offline/test_noManifest.html b/dom/tests/mochitest/ajax/offline/test_noManifest.html
new file mode 100644
index 0000000000..efeb63020f
--- /dev/null
+++ b/dom/tests/mochitest/ajax/offline/test_noManifest.html
@@ -0,0 +1,43 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>bad manifest content type</title>
+
+<script src="/tests/SimpleTest/SimpleTest.js"></script>
+<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+
+<script type="text/javascript">
+
+function expectInvalidState(fn, desc) {
+ var gotInvalidState = false;
+ try {
+ fn();
+ } catch(e) {
+ if (e.name == "InvalidStateError" &&
+ e.code == DOMException.INVALID_STATE_ERR) {
+ gotInvalidState = true;
+ }
+ }
+
+ ok(gotInvalidState, desc);
+}
+
+is(typeof(applicationCache), "object");
+if (SpecialPowers.isMainProcess()) {
+ is(applicationCache.mozLength, 0, "applicationCache.mozLength should be 0");
+}
+is(applicationCache.status, 0, "applicationCache.status should be 0 (UNCACHED)");
+
+expectInvalidState(function() { applicationCache.update(); },
+ "applicationCache.update should throw InvalidStateError");
+expectInvalidState(function() { applicationCache.swapCache(); },
+ "applicationCache.update should throw InvalidStateError");
+
+
+</script>
+
+</head>
+
+<body>
+
+</body>
+</html>
diff --git a/dom/tests/mochitest/ajax/offline/test_obsolete.html b/dom/tests/mochitest/ajax/offline/test_obsolete.html
new file mode 100644
index 0000000000..9318d05825
--- /dev/null
+++ b/dom/tests/mochitest/ajax/offline/test_obsolete.html
@@ -0,0 +1,42 @@
+<html>
+<head>
+<title>Test obsolete application caches</title>
+
+<script src="/tests/SimpleTest/SimpleTest.js"></script>
+<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+
+<script type="text/javascript">
+
+var gTestWin;
+
+SpecialPowers.pushPermissions([{'type': 'offline-app', 'allow': true, 'context': document}], startTest);
+
+function startTest() {
+ // Make the obsoleting.sjs return a valid manifest
+ var req = new XMLHttpRequest();
+ req.open("GET", "https://example.com/tests/dom/tests/mochitest/ajax/offline/obsoletingManifest.sjs?state=manifestPresent");
+ req.setRequestHeader("Content-Type", "text/cache-manifest");
+ req.send("");
+ req.onreadystatechange = function() {
+ if (req.readyState == 4) {
+ // now this will properly load the manifest.
+ gTestWin = window.open("obsolete.html");
+ }
+ }
+}
+
+function finish() {
+ gTestWin.close();
+ SimpleTest.finish();
+}
+
+SimpleTest.waitForExplicitFinish();
+
+</script>
+
+</head>
+
+<body>
+
+</body>
+</html>
diff --git a/dom/tests/mochitest/ajax/offline/test_offlineIFrame.html b/dom/tests/mochitest/ajax/offline/test_offlineIFrame.html
new file mode 100644
index 0000000000..5683470405
--- /dev/null
+++ b/dom/tests/mochitest/ajax/offline/test_offlineIFrame.html
@@ -0,0 +1,46 @@
+<html xmlns="http://www.w3.org/1999/xhtml" manifest="https://example.com/tests/dom/tests/mochitest/ajax/offline/simpleManifest.cacheManifest">
+<head>
+<title>offline iframe test</title>
+
+<script src="/tests/SimpleTest/SimpleTest.js"></script>
+<script type="text/javascript" src="/tests/dom/tests/mochitest/ajax/offline/offlineTests.js"></script>
+<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+
+<script type="text/javascript">
+
+
+function checkEntries() {
+ var entries = [
+ // The manifest itself should be in the cache
+ ["https://example.com/tests/dom/tests/mochitest/ajax/offline/simpleManifest.cacheManifest", true],
+
+ // The entries from the manifest should be in the cache
+ ["https://example.com/tests/SimpleTest/SimpleTest.js", true],
+ ["https://example.com/tests/dom/tests/mochitest/ajax/offline/offlineTests.js", true]
+ ];
+ OfflineTest.checkCacheEntries(entries, function() { window.frames["offlineChild"].doneLoading(); });
+}
+
+function childFinished()
+{
+ OfflineTest.teardownAndFinish();
+}
+
+if (OfflineTest.setup()) {
+ applicationCache.onerror = OfflineTest.failEvent;
+
+ applicationCache.oncached = OfflineTest.priv(checkEntries);
+}
+
+SimpleTest.waitForExplicitFinish();
+
+</script>
+
+</head>
+
+<body>
+
+<iframe name="offlineChild" src="offlineChild.html"></iframe>
+
+</body>
+</html>
diff --git a/dom/tests/mochitest/ajax/offline/test_offlineMode.html b/dom/tests/mochitest/ajax/offline/test_offlineMode.html
new file mode 100644
index 0000000000..39e7feab79
--- /dev/null
+++ b/dom/tests/mochitest/ajax/offline/test_offlineMode.html
@@ -0,0 +1,165 @@
+<html xmlns="http://www.w3.org/1999/xhtml" manifest="https://example.com/tests/dom/tests/mochitest/ajax/offline/updatingManifest.sjs">
+<head>
+<title>Offline mode test</title>
+
+<script src="/tests/SimpleTest/SimpleTest.js"></script>
+<script type="text/javascript" src="/tests/dom/tests/mochitest/ajax/offline/offlineTests.js"></script>
+<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+
+<script class="testbody" type="text/javascript">
+/* globals aFrame */
+
+/**
+ * The test loads a manifest and cache it.
+ * Then tests if all works in online mode
+ * as expected. Then switches firefox to offline
+ * mode and tries the page load still works as
+ * expected, i.e. all items from the cache load.
+ */
+
+var gImplicitWindow = null;
+var gCompleteTimeout = null;
+var gGotExplicitVersion = 0;
+var gGotImplicitVersion = 0;
+var gGotDynamicVersion = 0;
+var gGotOnError = false;
+
+function createURI(urispec)
+{
+ var ioServ = Components.classes["@mozilla.org/network/io-service;1"]
+ .getService(Components.interfaces.nsIIOService);
+ return ioServ.newURI(urispec);
+}
+
+// test
+
+function manifestUpdated()
+{
+ applicationCache.mozAdd("https://example.com/tests/dom/tests/mochitest/ajax/offline/notonwhitelist.html");
+ OfflineTest.waitForAdd("https://example.com/tests/dom/tests/mochitest/ajax/offline/notonwhitelist.html", dynamicAdded);
+}
+
+function dynamicAdded()
+{
+ aFrame.location = "https://example.com/tests/dom/tests/mochitest/ajax/offline/notonwhitelist.html";
+}
+
+// Called by the dynamically added iframe on load
+function notwhitelistOnLoad()
+{
+ gGotDynamicVersion = 1;
+ aFrame.location = "https://example.com/tests/dom/tests/mochitest/ajax/offline/updatingIframe.sjs";
+}
+
+// Called by the explicit iframe on load
+function frameLoad(version)
+{
+ gGotExplicitVersion = version;
+ gImplicitWindow = window.open("https://example.com/tests/dom/tests/mochitest/ajax/offline/updatingImplicit.html");
+}
+
+// Called by the implicit window on load
+function implicitLoaded(aWindow, errorOccured)
+{
+ aWindow.close();
+
+ gGotImplicitVersion = 1;
+ OfflineTest.waitForAdd("https://example.com/tests/dom/tests/mochitest/ajax/offline/updatingImplicit.html", implicitAdded);
+}
+
+function implicitAdded()
+{
+ OfflineTest.priv(finalize)();
+}
+
+function finalize()
+{
+ window.clearTimeout(gCompleteTimeout);
+
+ var ioserv = Cc["@mozilla.org/network/io-service;1"]
+ .getService(Ci.nsIIOService);
+
+ if (!ioserv.offline)
+ {
+ OfflineTest.is(gGotExplicitVersion, 1, "Explicit entry loaded");
+ OfflineTest.is(gGotImplicitVersion, 1, "Implicit entry loaded");
+ OfflineTest.is(gGotDynamicVersion, 1, "Dynamic entry loaded");
+
+ gGotExplicitVersion = 0;
+ gGotImplicitVersion = 0;
+ gGotDynamicVersion = 0;
+
+ var entries = [
+ ["https://example.com/tests/dom/tests/mochitest/ajax/offline/notonwhitelist.html", true],
+ ["https://example.com/tests/dom/tests/mochitest/ajax/offline/updatingIframe.sjs", true],
+ ["https://example.com/tests/dom/tests/mochitest/ajax/offline/updatingImplicit.html", true]
+ ];
+ OfflineTest.checkCacheEntries(entries, goOffline);
+ }
+ else
+ {
+ gImplicitWindow.close();
+
+ ioserv.offline = false;
+
+ OfflineTest.is(gGotExplicitVersion, 1, "Explicit entry loaded");
+ OfflineTest.is(gGotImplicitVersion, 1, "Bug 461325 - Implicit entry loaded");
+ OfflineTest.is(gGotDynamicVersion, 1, "Dynamic entry loaded");
+ OfflineTest.ok(gGotOnError, "Got onerror event invoked by implicit page load in offline mode");
+
+ OfflineTest.teardownAndFinish();
+ }
+}
+
+function goOffline()
+{
+ var listener = {
+ onCacheEntryDoomed: function (status) {
+ OfflineTest.priv(goOfflineContinue)();
+ }
+ };
+
+ // Delete HTTP cache to ensure we are going from offline cache
+ var cache = Cc["@mozilla.org/network/cache-storage-service;1"]
+ .getService(Ci.nsICacheStorageService);
+ var storage = cache.diskCacheStorage(LoadContextInfo.default, false);
+ storage.asyncDoomURI(createURI("https://example.com/tests/dom/tests/mochitest/ajax/offline/notonwhitelist.html"), "", null);
+ storage.asyncDoomURI(createURI("https://example.com/tests/dom/tests/mochitest/ajax/offline/updatingIframe.sjs"), "", null);
+ storage.asyncDoomURI(createURI("https://example.com/tests/dom/tests/mochitest/ajax/offline/updatingImplicit.html"), "", listener);
+}
+
+function goOfflineContinue()
+{
+ var ioserv = Cc["@mozilla.org/network/io-service;1"]
+ .getService(Ci.nsIIOService);
+
+ ioserv.offline = true;
+
+ gCompleteTimeout = window.setTimeout(OfflineTest.priv(finalize), 10000);
+
+ // remove error handling. in offline mode
+ // is correct to get error message
+ applicationCache.onerror = function() {gGotOnError = true;}
+
+ aFrame.location = "https://example.com/tests/dom/tests/mochitest/ajax/offline/notonwhitelist.html";
+ // Starts the chain all over again but in offline mode.
+}
+
+SimpleTest.waitForExplicitFinish();
+
+if (OfflineTest.setup()) {
+ applicationCache.onerror = OfflineTest.failEvent;
+ applicationCache.onupdateready = OfflineTest.failEvent;
+ applicationCache.oncached = OfflineTest.priv(manifestUpdated);
+}
+
+</script>
+
+</head>
+
+<body>
+
+<iframe name="aFrame" src=""></iframe>
+
+</body>
+</html>
diff --git a/dom/tests/mochitest/ajax/offline/test_overlap.html b/dom/tests/mochitest/ajax/offline/test_overlap.html
new file mode 100644
index 0000000000..85f71c72a1
--- /dev/null
+++ b/dom/tests/mochitest/ajax/offline/test_overlap.html
@@ -0,0 +1,35 @@
+<html xmlns="http://www.w3.org/1999/xhtml" manifest="https://example.com/tests/dom/tests/mochitest/ajax/offline/overlap.cacheManifest">
+<head>
+<title>overlapping namespaces test</title>
+
+<script src="/tests/SimpleTest/SimpleTest.js"></script>
+<script type="text/javascript" src="/tests/dom/tests/mochitest/ajax/offline/offlineTests.js"></script>
+<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+
+<script type="text/javascript">
+
+function manifestUpdated()
+{
+ var xhr = new XMLHttpRequest();
+ xhr.open("GET", "bogus/specific/test.html", false);
+ xhr.send();
+
+ OfflineTest.is(xhr.status, 200, "Should have fallen back.");
+ OfflineTest.teardownAndFinish();
+}
+
+if (OfflineTest.setup()) {
+ applicationCache.onerror = OfflineTest.failEvent;
+ applicationCache.oncached = OfflineTest.priv(manifestUpdated);
+}
+
+SimpleTest.waitForExplicitFinish();
+
+</script>
+
+</head>
+
+<body>
+
+</body>
+</html>
diff --git a/dom/tests/mochitest/ajax/offline/test_redirectManifest.html b/dom/tests/mochitest/ajax/offline/test_redirectManifest.html
new file mode 100644
index 0000000000..43701a3d08
--- /dev/null
+++ b/dom/tests/mochitest/ajax/offline/test_redirectManifest.html
@@ -0,0 +1,44 @@
+<html xmlns="http://www.w3.org/1999/xhtml" manifest="https://example.com/tests/dom/tests/mochitest/ajax/offline/manifestRedirect.sjs">
+<head>
+<title>Fail update on manifest redirection test</title>
+
+<script src="/tests/SimpleTest/SimpleTest.js"></script>
+<script type="text/javascript" src="/tests/dom/tests/mochitest/ajax/offline/offlineTests.js"></script>
+<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+
+<script class="testbody" type="text/javascript">
+
+/**
+ */
+
+function manifestCached()
+{
+ OfflineTests.ok(false, "Manifest must not be cached");
+ finish();
+}
+
+function manifestError()
+{
+ OfflineTest.ok(true, "Error expected");
+ finish();
+}
+
+function finish()
+{
+ OfflineTest.teardownAndFinish();
+}
+
+SimpleTest.waitForExplicitFinish();
+
+if (OfflineTest.setup()) {
+ applicationCache.onerror = OfflineTest.priv(manifestError);
+ applicationCache.oncached = OfflineTest.priv(manifestCached);
+}
+
+</script>
+
+</head>
+
+<body>
+</body>
+</html>
diff --git a/dom/tests/mochitest/ajax/offline/test_redirectUpdateItem.html b/dom/tests/mochitest/ajax/offline/test_redirectUpdateItem.html
new file mode 100755
index 0000000000..21bc1897e1
--- /dev/null
+++ b/dom/tests/mochitest/ajax/offline/test_redirectUpdateItem.html
@@ -0,0 +1,137 @@
+<html xmlns="http://www.w3.org/1999/xhtml" manifest="https://example.com/tests/dom/tests/mochitest/ajax/offline/redirects.sjs">
+<head>
+<title>Entries redirection handling during update test</title>
+
+<script src="/tests/SimpleTest/SimpleTest.js"></script>
+<script type="text/javascript" src="/tests/dom/tests/mochitest/ajax/offline/offlineTests.js"></script>
+<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+
+<script class="testbody" type="text/javascript">
+
+var gCurrentManifestVersion = 1;
+
+function manifestCached()
+{
+ var entries = [
+ ["https://example.com/tests/dom/tests/mochitest/ajax/offline/dynamicRedirect.sjs", false],
+ ["https://example.com/tests/dom/tests/mochitest/ajax/offline/explicitRedirect.sjs", true],
+ ];
+ OfflineTest.checkCacheEntries(entries, manifestCachedContinue);
+}
+
+function manifestCachedContinue()
+{
+ OfflineTest.is(gCurrentManifestVersion, 1, "Cached event for manifest version one");
+
+ // Now add one dynamic entry (now with content overriden redirect sjs)
+ applicationCache.mozAdd(
+ "https://example.com/tests/dom/tests/mochitest/ajax/offline/dynamicRedirect.sjs");
+
+ // Wait for the dynamic entry be added to the cache...
+ OfflineTest.waitForAdd(
+ "https://example.com/tests/dom/tests/mochitest/ajax/offline/dynamicRedirect.sjs",
+ function() {
+ // ...check it is there...
+ OfflineTest.checkCache(
+ "https://example.com/tests/dom/tests/mochitest/ajax/offline/dynamicRedirect.sjs",
+ true,
+ function() {
+ // ...revert state of the dynamic entry on the server, now we get the redirect...
+ OfflineTest.setSJSState(
+ "https://example.com/tests/dom/tests/mochitest/ajax/offline/dynamicRedirect.sjs",
+ "");
+
+ // ...update manifest to the new version on the server...
+ OfflineTest.setSJSState(
+ "https://example.com/tests/dom/tests/mochitest/ajax/offline/redirects.sjs",
+ "second");
+ gCurrentManifestVersion = 2;
+
+ // ...and finally invoke the cache update.
+ applicationCache.update();
+ });
+ });
+}
+
+function manifestUpdated()
+{
+ switch (gCurrentManifestVersion)
+ {
+ case 2:
+ // Check the dynamic entry was removed from the cache (because of the redirect)...
+ OfflineTest.checkCache(
+ "https://example.com/tests/dom/tests/mochitest/ajax/offline/dynamicRedirect.sjs",
+ false,
+ function () {
+ // ...return back redirect for the explicit entry...
+ OfflineTest.setSJSState(
+ "https://example.com/tests/dom/tests/mochitest/ajax/offline/explicitRedirect.sjs",
+ "");
+
+ // ...update the manifest to the third version...
+ OfflineTest.setSJSState(
+ "https://example.com/tests/dom/tests/mochitest/ajax/offline/redirects.sjs",
+ "third");
+ gCurrentManifestVersion = 3;
+
+ // ...and invoke the cache update, now we must get error.
+ applicationCache.update();
+ });
+
+ break;
+
+ case 3:
+ OfflineTest.ok(false, "Update didn't fail for third version of the manifest");
+ finish();
+ break;
+ }
+}
+
+function manifestError()
+{
+ switch (gCurrentManifestVersion)
+ {
+ case 1:
+ OfflineTest.ok(false, "Error not expected when caching the first version of the manifest");
+ finish();
+ break;
+ case 2:
+ OfflineTest.ok(false, "Error not expected when updating to second version of the manifest");
+ finish();
+ break;
+ case 3:
+ OfflineTest.ok(true, "Error expected when updating to third version of the manifest");
+ finish();
+ break;
+ }
+}
+
+function finish()
+{
+ OfflineTest.teardownAndFinish();
+}
+
+SimpleTest.waitForExplicitFinish();
+SimpleTest.requestFlakyTimeout("untriaged");
+
+if (OfflineTest.setup()) {
+ applicationCache.onerror = OfflineTest.priv(manifestError);
+ applicationCache.onupdateready = OfflineTest.priv(manifestUpdated);
+ applicationCache.oncached = OfflineTest.priv(manifestCached);
+
+ // Override sjs redirects on the server, it will now return 200 OK and the content
+ OfflineTest.setSJSState(
+ "https://example.com/tests/dom/tests/mochitest/ajax/offline/explicitRedirect.sjs",
+ "on");
+ OfflineTest.setSJSState(
+ "https://example.com/tests/dom/tests/mochitest/ajax/offline/dynamicRedirect.sjs",
+ "on");
+}
+
+</script>
+
+</head>
+
+<body>
+</body>
+</html>
diff --git a/dom/tests/mochitest/ajax/offline/test_refetchManifest.html b/dom/tests/mochitest/ajax/offline/test_refetchManifest.html
new file mode 100644
index 0000000000..a580edc1a3
--- /dev/null
+++ b/dom/tests/mochitest/ajax/offline/test_refetchManifest.html
@@ -0,0 +1,88 @@
+<html xmlns="http://www.w3.org/1999/xhtml" manifest="https://example.com/tests/dom/tests/mochitest/ajax/offline/changingManifest.sjs">
+<head>
+<title>refetch manifest test</title>
+
+<script src="/tests/SimpleTest/SimpleTest.js"></script>
+<script type="text/javascript" src="/tests/dom/tests/mochitest/ajax/offline/offlineTests.js"></script>
+
+<script type="text/javascript">
+
+function finish()
+{
+ OfflineTest.teardownAndFinish();
+}
+
+function failAndFinish(e)
+{
+ OfflineTest.ok(false, "Unexpected event: " + e.type);
+ finish();
+}
+
+function manifestUpdated()
+{
+ // Replace this manifest with a new one.
+
+ // XXX: After this put, we will no longer have Cache-Control:
+ // no-cache on the manifest, so future updates will just use the
+ // cached manifest.
+
+ // Get the initial contents of the first two files.
+ fetcher = new OfflineCacheContents([g1SecUrl, g1HourUrl]);
+ fetcher.fetch(function(contents) {
+ gCacheContents = contents;
+
+ // Now make sure applicationCache.update() does what we expect.
+ applicationCache.onupdateready = OfflineTest.priv(manifestUpdatedAgain);
+ applicationCache.onnoupdate = failAndFinish;
+ applicationCache.oncached = failAndFinish;
+
+ gGotChecking = false;
+ gGotDownloading = false;
+
+ // The changing versions give out a new version each second,
+ // make sure it has time to grab a new version, and for the
+ // 1-second cache timeout to pass.
+ window.setTimeout("applicationCache.update()", 5000);
+ });
+}
+
+function replaceManifest()
+{
+ // If we replace the manifest after a downloading event, the update
+ // should fail when it revalidates the manifest at the end of the update.
+ OfflineTest.setSJSState("changingManifest.sjs", "2");
+}
+
+function cached()
+{
+ OfflineTest.ok(true, "Got the expected cached event.");
+ finish();
+}
+
+function gotError()
+{
+ OfflineTest.ok(true, "Got the expected error event.");
+
+ // Now this update will be rescheduled, and it should succeed.
+ applicationCache.onerror = failAndFinish;
+ applicationCache.oncached = cached;
+}
+
+if (OfflineTest.setup()) {
+ applicationCache.onerror = gotError;
+ applicationCache.onnoupdate = failAndFinish;
+
+ applicationCache.ondownloading = replaceManifest;
+ applicationCache.oncached = failAndFinish;
+}
+
+SimpleTest.waitForExplicitFinish();
+
+</script>
+
+</head>
+
+<body>
+
+</body>
+</html>
diff --git a/dom/tests/mochitest/ajax/offline/test_simpleManifest.html b/dom/tests/mochitest/ajax/offline/test_simpleManifest.html
new file mode 100644
index 0000000000..3e18a340a8
--- /dev/null
+++ b/dom/tests/mochitest/ajax/offline/test_simpleManifest.html
@@ -0,0 +1,130 @@
+<html xmlns="http://www.w3.org/1999/xhtml" manifest="https://example.com/tests/dom/tests/mochitest/ajax/offline/simpleManifest.cacheManifest">
+<head>
+<title>simple manifest test</title>
+
+<script src="/tests/SimpleTest/SimpleTest.js"></script>
+<script type="text/javascript" src="/tests/dom/tests/mochitest/ajax/offline/offlineTests.js"></script>
+<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+
+<script type="text/javascript">
+
+var gGotChecking = false;
+var gGotDownloading = false;
+
+ok(applicationCache.mozItems.length == 0,
+ "applicationCache.mozItems should be available and empty before associating with a cache.");
+
+function addFinished()
+{
+ OfflineTest.ok(applicationCache.mozLength == 1, "applicationCache should have one dynamic entry (deprecated API)");
+ OfflineTest.ok(applicationCache.mozItem(0) == "https://example.com/tests/SimpleTest/EventUtils.js",
+ "applicationCache's dynamic entry should be the one we expect (deprecated API)");
+
+ OfflineTest.ok(applicationCache.mozItems.length == 1, "applicationCache should have one dynamic entry");
+ OfflineTest.ok(applicationCache.mozItems[0] == "https://example.com/tests/SimpleTest/EventUtils.js",
+ "applicationCache's dynamic entry should be the one we expect");
+
+ OfflineTest.ok(applicationCache.mozHasItem("https://example.com/tests/SimpleTest/EventUtils.js"),
+ "applicationCache.mozHasItem() should see the dynamic entry");
+
+ // Check that the entry was added successfully
+ OfflineTest.checkCache("https://example.com/tests/SimpleTest/EventUtils.js",
+ true,
+ removeItem);
+}
+
+function removeItem()
+{
+ // Now test that removes work
+ applicationCache.mozRemove("https://example.com/tests/SimpleTest/EventUtils.js");
+
+ OfflineTest.ok(applicationCache.mozLength == 0,
+ "applicationCache should have no dynamic entries (deprecated API)");
+ OfflineTest.ok(applicationCache.mozItems.length == 0,
+ "applicationCache should have no dynamic entries");
+ OfflineTest.ok(!applicationCache.mozHasItem("https://example.com/tests/SimpleTest/EventUtils.js"),
+ "applicationCache.mozHasItem() should not see the removed dynamic entry");
+
+ OfflineTest.checkCache("https://example.com/tests/SimpleTest/EventUtils.js",
+ false,
+ function() {
+ // We're done
+ OfflineTest.teardownAndFinish();
+ });
+}
+
+function manifestUpdated()
+{
+ OfflineTest.ok(gGotChecking, "Should get a checking event");
+ OfflineTest.ok(gGotDownloading, "Should get a downloading event");
+
+ OfflineTest.is(applicationCache.status, 1, "Cache status should be 1 (CACHED)");
+
+ var entries = [
+ // The manifest itself should be in the cache
+ ["https://example.com/tests/dom/tests/mochitest/ajax/offline/simpleManifest.cacheManifest", true],
+
+ // The document that requested the manifest should be in the cache
+ [window.location.href, true],
+
+ // The entries from the manifest should be in the cache
+ ["https://example.com/tests/SimpleTest/SimpleTest.js", true],
+ ["https://example.com/tests/dom/tests/mochitest/ajax/offline/offlineTests.js", true],
+
+ // The bad entries from the manifest should not be in the cache
+ ["bad:/uri/invalid", false]
+ ];
+ OfflineTest.checkCacheEntries(
+ entries,
+ function() {
+ try {
+ applicationCache.swapCache();
+ OfflineTest.ok(false, "application.swapCache() should fail after initial update.");
+ } catch(ex) {
+ OfflineTest.ok(true, "application.swapCache() should fail after initial update.");
+ }
+
+ // XXX: make sure that the previous version went away after the swapCache().
+
+ // Now add a file using the applicationCache API
+ applicationCache.mozAdd("https://example.com/tests/SimpleTest/EventUtils.js");
+
+ // Wait for the add() to be downloaded
+ OfflineTest.waitForAdd("https://example.com/tests/SimpleTest/EventUtils.js",
+ OfflineTest.priv(addFinished));
+ });
+}
+
+if (OfflineTest.setup()) {
+ OfflineTest.ok(applicationCache instanceof EventTarget,
+ "applicationCache should be an event target");
+
+ applicationCache.onerror = OfflineTest.failEvent;
+
+ applicationCache.addEventListener("checking", function() {
+ // We should get the "checking" event during an initial update,
+ // but until we are associated it will not affect applicationCache.status
+ OfflineTest.is(applicationCache.status, applicationCache.UNCACHED,
+ "CHECKING state during initial update");
+ gGotChecking = true;
+ }, true);
+ applicationCache.ondownloading = function() {
+ // We should get the "downloading" event during an initial update,
+ // but until we are associated it will not affect applicationCache.status
+ OfflineTest.is(applicationCache.status, applicationCache.UNCACHED,
+ "DOWNLOADING state during initial update")
+ gGotDownloading = true; };
+ applicationCache.oncached = OfflineTest.priv(manifestUpdated);
+}
+
+SimpleTest.waitForExplicitFinish();
+SimpleTest.requestFlakyTimeout("untriaged");
+
+</script>
+
+</head>
+
+<body>
+
+</body>
+</html>
diff --git a/dom/tests/mochitest/ajax/offline/test_updateCheck.html b/dom/tests/mochitest/ajax/offline/test_updateCheck.html
new file mode 100644
index 0000000000..fb675c3261
--- /dev/null
+++ b/dom/tests/mochitest/ajax/offline/test_updateCheck.html
@@ -0,0 +1,87 @@
+<html xmlns="http://www.w3.org/1999/xhtml" manifest="https://example.com/tests/dom/tests/mochitest/ajax/offline/updatingManifest.sjs">
+<head>
+<title>Cache update test</title>
+
+<script src="/tests/SimpleTest/SimpleTest.js"></script>
+<script type="text/javascript" src="/tests/dom/tests/mochitest/ajax/offline/offlineTests.js"></script>
+<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+
+<script class="testbody" type="text/javascript">
+
+/*
+ * The test is checking nsIOfflineCacheUpdateService.checkForUpdate API:
+ * - cache a manifest
+ * - check for an update of it, expected is "no update avail"
+ * - modify the manifest on the server
+ * - check for an update again, expected is "update avail"
+ * - check for an update ones again, expected is "update avail" (secondary check to probe
+ * we didn't screw state of the manifest in the current cache with the first check)
+ * - cache the modified manifest, new version is now in the cache
+ * - last check for an update, expected is "no update avail" again
+ */
+
+SimpleTest.waitForExplicitFinish();
+
+var manifest = "https://example.com/tests/dom/tests/mochitest/ajax/offline/updatingManifest.sjs";
+var manifestURI = Cc["@mozilla.org/network/io-service;1"]
+ .getService(Ci.nsIIOService)
+ .newURI(manifest);
+var updateService = Cc['@mozilla.org/offlinecacheupdate-service;1']
+ .getService(Ci.nsIOfflineCacheUpdateService);
+
+var systemPrincipal = SpecialPowers.Services.scriptSecurityManager.getSystemPrincipal();
+
+function manifestCached()
+{
+ // Run first check for an update
+ updateService.checkForUpdate(manifestURI, systemPrincipal, SpecialPowers.wrapCallbackObject({
+ observe: function(subject, topic, data) {
+ OfflineTest.is(topic, "offline-cache-update-unavailable", "No update avail");
+
+ // Change the manifest content
+ OfflineTest.setSJSState(manifest, "second");
+
+ // Check we now get notification on update ready
+ updateService.checkForUpdate(manifestURI, systemPrincipal, SpecialPowers.wrapCallbackObject({
+ observe: function(subject, topic, data) {
+ OfflineTest.is(topic, "offline-cache-update-available", "Update avail (1)");
+
+ // Do the check again. We must get the same result. Double check is here
+ // to make sure we don't overwrite any data in the cache by the check it self.
+ updateService.checkForUpdate(manifestURI, systemPrincipal, SpecialPowers.wrapCallbackObject({
+ observe: function(subject, topic, data) {
+ OfflineTest.is(topic, "offline-cache-update-available", "Update avail (2)");
+
+ // Update the manifest, invokes manifestUpdated()
+ applicationCache.onupdateready = OfflineTest.priv(manifestUpdated);
+ applicationCache.update();
+ }
+ }));
+ }
+ }));
+ }
+ }));
+}
+
+function manifestUpdated()
+{
+ // Check for an update after manifest has been updated
+ updateService.checkForUpdate(manifestURI, systemPrincipal, SpecialPowers.wrapCallbackObject({
+ observe: function(subject, topic, data) {
+ OfflineTest.is(topic, "offline-cache-update-unavailable", "No update avail (2)");
+
+ OfflineTest.teardownAndFinish();
+ }
+ }));
+}
+
+if (OfflineTest.setup()) {
+ applicationCache.onerror = OfflineTest.failEvent;
+ applicationCache.oncached = OfflineTest.priv(manifestCached);
+}
+
+</script>
+</head>
+<body>
+</body>
+</html>
diff --git a/dom/tests/mochitest/ajax/offline/test_updatingManifest.html b/dom/tests/mochitest/ajax/offline/test_updatingManifest.html
new file mode 100644
index 0000000000..c15555761a
--- /dev/null
+++ b/dom/tests/mochitest/ajax/offline/test_updatingManifest.html
@@ -0,0 +1,346 @@
+<html xmlns="http://www.w3.org/1999/xhtml" manifest="https://example.com/tests/dom/tests/mochitest/ajax/offline/updatingManifest.sjs">
+<head>
+<title>Cache update test</title>
+
+<script src="/tests/SimpleTest/SimpleTest.js"></script>
+<script type="text/javascript" src="/tests/dom/tests/mochitest/ajax/offline/offlineTests.js"></script>
+<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+
+<script class="testbody" type="text/javascript">
+
+/**
+ * This test loads manifest and checks presence of all items.
+ * Then it modifies the manifest and updates the cache again.
+ * Then test presence of items according to the spec and also
+ * if the cache associated with the document is still the old
+ * one. Then again modifies the manifest, checks items and finally
+ * swaps cache for this document, reloads and checks document state.
+ */
+
+const NAMESPACE_BYPASS = SpecialPowers.Ci.nsIApplicationCacheNamespace.NAMESPACE_BYPASS;
+const NAMESPACE_FALLBACK = SpecialPowers.Ci.nsIApplicationCacheNamespace.NAMESPACE_FALLBACK;
+
+var gStep = 0;
+var gGotFrameVersion = 0;
+var gCallOnUpdatingFrameLoad = null;
+
+// Helpers
+
+function reloadLocations(frames)
+{
+ for (frame in frames)
+ frames[frame].location.reload();
+}
+
+function waitForLocations(frames, doneFunc)
+{
+ frame = frames.shift();
+ if (frame)
+ // toString() might cause problems when this test will
+ // completely be changed to test IDN behavior.
+ OfflineTest.waitForAdd(frame, function()
+ {
+ waitForLocations(frames, doneFunc);
+ }
+ );
+ else
+ {
+ doneFunc();
+ }
+}
+
+function checkFallbackAndWhitelisting(key, fallback, onwhitelist)
+{
+ // Get matching namespace for the key
+ var matchingNamespace = OfflineTest.getActiveCache()
+ .getMatchingNamespace(key);
+
+ // If we are not expecting the key is to be on white list or
+ // has been assigned a fallback check there is not any matching
+ // namespace found and exit
+ if (!fallback && !onwhitelist) {
+ is(matchingNamespace, null, "No namespace found for "+key);
+ return;
+ }
+
+ // We expect this entry is on the white list or has a fallback
+ // entry assigned, check we found a matching namespace
+ ok(matchingNamespace, "We have a namespace for "+key);
+ if (!matchingNamespace)
+ return;
+
+ // We expect the key be assigned a fallback URI, check the namespace
+ // type is of fallback type
+ OfflineTest.is(!!(matchingNamespace.itemType & NAMESPACE_FALLBACK), !!fallback,
+ (fallback ? "Namespace type is fallback for " : "Namespace type is not fallback for ")+key);
+
+ // We expect the key be assigned a fallback URI, check the URI is
+ // equal to expected one
+ OfflineTest.is(matchingNamespace.data, fallback,
+ (fallback ? "Expected correct fallback for " : "No fallback for ")+key);
+
+ // We expect the key be on the white list, check the namespace type
+ // is of bypass type
+ OfflineTest.is(!!(matchingNamespace.itemType & NAMESPACE_BYPASS), onwhitelist,
+ (onwhitelist ? "On white list " : "Not on white list ")+key);
+}
+
+// Events
+
+function frameLoad(version)
+{
+ gGotFrameVersion = version;
+ if (gCallOnUpdatingFrameLoad)
+ {
+ var call = gCallOnUpdatingFrameLoad;
+ gCallOnUpdatingFrameLoad = null;
+ SimpleTest.executeSoon(OfflineTest.priv(call));
+ }
+}
+
+function whitelistOnLoad(version)
+{
+ // Whitelisting is not tested by this test...
+}
+
+
+// Start of the test function chain
+// ================================
+
+function manifestCached()
+{
+ OfflineTest.is(gStep, 0, "Got manifestCached in step 0, gStep=" + gStep);
+
+ reloadLocations([fallbackFrame1, fallbackFrame2]);
+ waitForLocations(
+ ["https://example.com/tests/dom/tests/mochitest/ajax/offline/fallback.html"],
+ fallbackLoaded
+ );
+}
+
+function fallbackLoaded()
+{
+ dump("in fallbackLoaded\n");
+ applicationCache.mozAdd("https://example.com/tests/SimpleTest/EventUtils.js");
+ OfflineTest.waitForAdd("https://example.com/tests/SimpleTest/EventUtils.js",
+ dynamicLoaded);
+}
+
+function dynamicLoaded()
+{
+ window.open("https://example.com/tests/dom/tests/mochitest/ajax/offline/updatingImplicit.html");
+ // window.applicationCache.noupdate invokes implicitLoaded()
+}
+
+function implicitLoaded(aWindow, errorOccured)
+{
+ aWindow.close();
+
+ OfflineTest.ok(!errorOccured, "No error on new implicit page manifest update");
+
+ OfflineTest.waitForAdd("https://example.com/tests/dom/tests/mochitest/ajax/offline/updatingImplicit.html",
+ implicitCached);
+}
+
+function implicitCached()
+{
+ // Checking first version of the manifest + another implict page caching
+
+ // Whitelist entries
+ checkFallbackAndWhitelisting("https://example.com/tests/dom/tests/mochitest/ajax/offline/onwhitelist.html", "", true);
+
+ // Fallback URI selection check
+ checkFallbackAndWhitelisting("https://example.com/tests/dom/tests/mochitest/ajax/offline/namespace1/opp.html",
+ "https://example.com/tests/dom/tests/mochitest/ajax/offline/fallback.html", false);
+ checkFallbackAndWhitelisting("https://example.com/tests/dom/tests/mochitest/ajax/offline/namespace1/sub/opp.html",
+ "https://example.com/tests/dom/tests/mochitest/ajax/offline/fallback.html", false);
+
+ // Cache object status
+ OfflineTest.is(applicationCache.status, OfflineResourceList.IDLE,
+ "we have associated application cache (1)");
+
+ OfflineTest.is(gGotFrameVersion, 1, "IFrame version 1");
+
+ var entries = [
+ // Explicit entries
+ ["https://example.com/tests/SimpleTest/SimpleTest.js", false],
+ ["https://example.com/tests/dom/tests/mochitest/ajax/offline/offlineTests.js", true],
+
+ // Fallback entries
+ ["https://example.com/tests/dom/tests/mochitest/ajax/offline/fallback.html", true],
+ ["https://example.com/tests/dom/tests/mochitest/ajax/offline/fallback2.html", false],
+
+ // Whitelist entries
+ ["https://example.com/tests/dom/tests/mochitest/ajax/offline/onwhitelist.html", false],
+
+ // Implicit entries
+ ["https://example.com/tests/dom/tests/mochitest/ajax/offline/updatingImplicit.html", true],
+
+ // Dynamic entries
+ ["https://example.com/tests/SimpleTest/EventUtils.js", true]
+ ];
+ OfflineTest.checkCacheEntries(
+ entries,
+ function() {
+ ++gStep;
+
+ OfflineTest.setSJSState("https://example.com/tests/dom/tests/mochitest/ajax/offline/updatingManifest.sjs", "second");
+
+ applicationCache.update();
+ // Invokes manifestUpdated()
+ });
+}
+
+function manifestUpdated()
+{
+ OfflineTest.ok(gStep == 1 || gStep == 2, "Got manifestUpdated in step 1 or 2, gStep=" + gStep);
+
+ switch (gStep)
+ {
+ case 1:
+ // Processing second version of the manifest.
+
+ // Whitelist entries
+ checkFallbackAndWhitelisting("https://example.com/tests/dom/tests/mochitest/ajax/offline/onwhitelist.html", "", false);
+
+ // Fallback URI selection check
+ checkFallbackAndWhitelisting("https://example.com/tests/dom/tests/mochitest/ajax/offline/namespace1/opp.html",
+ "https://example.com/tests/dom/tests/mochitest/ajax/offline/fallback.html", false);
+ checkFallbackAndWhitelisting("https://example.com/tests/dom/tests/mochitest/ajax/offline/namespace1/sub/opp.html",
+ "https://example.com/tests/dom/tests/mochitest/ajax/offline/fallback2.html", false);
+
+ // Cache object status
+ OfflineTest.is(applicationCache.status, OfflineResourceList.UPDATEREADY,
+ "we have associated application cache and update is pending (2)");
+
+ var entries = [
+ // Explicit entries
+ ["https://example.com/tests/SimpleTest/SimpleTest.js", true],
+ ["https://example.com/tests/dom/tests/mochitest/ajax/offline/offlineTests.js", true],
+
+ // Fallback entries
+ ["https://example.com/tests/dom/tests/mochitest/ajax/offline/fallback.html", true],
+ ["https://example.com/tests/dom/tests/mochitest/ajax/offline/fallback2.html", true],
+
+ // Whitelist entries
+ ["https://example.com/tests/dom/tests/mochitest/ajax/offline/onwhitelist.html", false],
+
+ // Implicit entries
+ ["https://example.com/tests/dom/tests/mochitest/ajax/offline/updatingImplicit.html", true],
+
+ // Dynamic entries
+ ["https://example.com/tests/SimpleTest/EventUtils.js", true]
+ ];
+ OfflineTest.checkCacheEntries(
+ entries,
+ function() {
+ ++gStep;
+
+ OfflineTest.setSJSState("https://example.com/tests/dom/tests/mochitest/ajax/offline/updatingManifest.sjs", "third");
+ OfflineTest.setSJSState("https://example.com/tests/dom/tests/mochitest/ajax/offline/updatingIframe.sjs", "second");
+
+ gGotFrameVersion = 0;
+ updatingFrame.location.reload();
+ // Since the frame is offline-cached, reload of it invokes update
+ });
+
+ break;
+
+ case 2:
+ // Processing third version of the manifest.
+
+ // Whitelist entries
+ checkFallbackAndWhitelisting("https://example.com/tests/dom/tests/mochitest/ajax/offline/onwhitelist.html", "", true);
+
+ // Fallback URI selection check
+ checkFallbackAndWhitelisting("https://example.com/tests/dom/tests/mochitest/ajax/offline/namespace1/opp.html",
+ "", false);
+ checkFallbackAndWhitelisting("https://example.com/tests/dom/tests/mochitest/ajax/offline/namespace1/sub/opp.html",
+ "https://example.com/tests/dom/tests/mochitest/ajax/offline/fallback2.html", false);
+
+ // Cache object status
+ OfflineTest.is(applicationCache.status, OfflineResourceList.UPDATEREADY,
+ "we have associated application cache and update is pending (3)");
+
+ OfflineTest.is(gGotFrameVersion, 1, "IFrame version 1 because cache was not swapped");
+
+ var entries = [
+ // Explicit entries
+ ["https://example.com/tests/SimpleTest/SimpleTest.js", false],
+ ["https://example.com/tests/dom/tests/mochitest/ajax/offline/offlineTests.js", true],
+
+ // Fallback entries
+ ["https://example.com/tests/dom/tests/mochitest/ajax/offline/fallback.html", false],
+ ["https://example.com/tests/dom/tests/mochitest/ajax/offline/fallback2.html", true],
+
+ // Whitelist entries
+ ["https://example.com/tests/dom/tests/mochitest/ajax/offline/onwhitelist.html", false],
+
+ // Implicit entries
+ ["https://example.com/tests/dom/tests/mochitest/ajax/offline/updatingImplicit.html", true],
+
+ // Dynamic entries
+ ["https://example.com/tests/SimpleTest/EventUtils.js", true]
+ ];
+ OfflineTest.checkCacheEntries(
+ entries,
+ function() {
+ ++gStep;
+
+ applicationCache.onnoupdate = OfflineTest.priv(manifestNoUpdate);
+ applicationCache.update();
+ // Invokes manifestNoUpdate()
+ });
+
+ break;
+ }
+}
+
+function manifestNoUpdate()
+{
+ applicationCache.onnoupdate = null;
+
+ OfflineTest.ok(gStep == 3, "Got manifestNoUpdate in step 3, gStep=" + gStep);
+ ++gStep;
+
+ OfflineTest.is(applicationCache.status, OfflineResourceList.UPDATEREADY,
+ "we have associated application cache and update is pending (4)");
+ applicationCache.swapCache();
+ OfflineTest.is(applicationCache.status, OfflineResourceList.IDLE,
+ "we have associated application cache (4)");
+
+ gGotFrameVersion = 0;
+ gCallOnUpdatingFrameLoad = checkNewVersionOfIFrame;
+ updatingFrame.location.reload();
+}
+
+function checkNewVersionOfIFrame()
+{
+ OfflineTest.is(gGotFrameVersion, 2, "IFrame version 2");
+
+ OfflineTest.teardownAndFinish();
+}
+
+// End of the test function chain
+// ==============================
+
+SimpleTest.waitForExplicitFinish();
+SimpleTest.requestFlakyTimeout("untriaged");
+
+if (OfflineTest.setup()) {
+ applicationCache.onerror = OfflineTest.failEvent;
+ applicationCache.onupdateready = OfflineTest.priv(manifestUpdated);
+ applicationCache.oncached = OfflineTest.priv(manifestCached);
+}
+
+</script>
+
+</head>
+
+<body>
+ <iframe name="updatingFrame" src="https://example.com/tests/dom/tests/mochitest/ajax/offline/updatingIframe.sjs"></iframe>
+ <iframe name="fallbackFrame1" src="https://example.com/tests/dom/tests/mochitest/ajax/offline/namespace1/opp.html"></iframe>
+ <iframe name="fallbackFrame2" src="https://example.com/tests/dom/tests/mochitest/ajax/offline/namespace1/sub/opp.html"></iframe>
+ <iframe name="whitelistFrame" src="https://example.com/tests/dom/tests/mochitest/ajax/offline/onwhitelist.html"></iframe>
+</body>
+</html>
diff --git a/dom/tests/mochitest/ajax/offline/test_xhtmlManifest.xhtml b/dom/tests/mochitest/ajax/offline/test_xhtmlManifest.xhtml
new file mode 100644
index 0000000000..3efc8eee23
--- /dev/null
+++ b/dom/tests/mochitest/ajax/offline/test_xhtmlManifest.xhtml
@@ -0,0 +1,32 @@
+<html xmlns="http://www.w3.org/1999/xhtml" manifest="https://example.com/tests/dom/tests/mochitest/ajax/offline/simpleManifest.cacheManifest">
+<head>
+<title>xhtml manifest test</title>
+
+<script src="/tests/SimpleTest/SimpleTest.js"></script>
+<script type="text/javascript" src="/tests/dom/tests/mochitest/ajax/offline/offlineTests.js"></script>
+<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+
+<script type="text/javascript">
+
+function manifestUpdated()
+{
+ OfflineTest.ok(true, "Application cache updated.");
+
+ OfflineTest.teardownAndFinish();
+}
+
+if (OfflineTest.setup()) {
+ applicationCache.onerror = OfflineTest.failEvent;
+ applicationCache.oncached = OfflineTest.priv(manifestUpdated);
+}
+
+SimpleTest.waitForExplicitFinish();
+
+</script>
+
+</head>
+
+<body>
+
+</body>
+</html>
diff --git a/dom/tests/mochitest/ajax/offline/unknownSection.cacheManifest b/dom/tests/mochitest/ajax/offline/unknownSection.cacheManifest
new file mode 100644
index 0000000000..ae88e75278
--- /dev/null
+++ b/dom/tests/mochitest/ajax/offline/unknownSection.cacheManifest
@@ -0,0 +1,10 @@
+CACHE MANIFEST
+https://example.com/tests/SimpleTest/SimpleTest.js
+
+UNKNOWN-SECTION:
+https://example.com/tests/dom/tests/mochitest/ajax/offline/jupiter.jpg
+here can be anything the current implementaion
+is not able to parse at all and is just silently ignored
+
+CACHE:
+https://example.com/tests/dom/tests/mochitest/ajax/offline/offlineTests.js
diff --git a/dom/tests/mochitest/ajax/offline/unknownSection.cacheManifest^headers^ b/dom/tests/mochitest/ajax/offline/unknownSection.cacheManifest^headers^
new file mode 100644
index 0000000000..5efde3c5b0
--- /dev/null
+++ b/dom/tests/mochitest/ajax/offline/unknownSection.cacheManifest^headers^
@@ -0,0 +1,2 @@
+Content-Type: text/cache-manifest
+
diff --git a/dom/tests/mochitest/ajax/offline/updatingIframe.sjs b/dom/tests/mochitest/ajax/offline/updatingIframe.sjs
new file mode 100644
index 0000000000..91325d2820
--- /dev/null
+++ b/dom/tests/mochitest/ajax/offline/updatingIframe.sjs
@@ -0,0 +1,45 @@
+ver1iframe =
+ "<html xmlns=\"http://www.w3.org/1999/xhtml\">\n" +
+ "<head>\n" +
+ "<title>Update iframe</title>\n" +
+ "</head>\n" +
+ "<body onload=\"parent.frameLoad(1)\">\n" +
+ "First version of updating iframe.\n" +
+ "</body>\n" +
+ "</html>\n";
+
+ver2iframe =
+ "<html xmlns=\"http://www.w3.org/1999/xhtml\">\n" +
+ "<head>\n" +
+ "<title>Update iframe</title>\n" +
+ "</head>\n" +
+ "<body onload=\"parent.frameLoad(2)\">\n" +
+ "Second version of updating iframe.\n" +
+ "</body>\n" +
+ "</html>\n";
+
+function handleRequest(request, response)
+{
+ var match = request.queryString.match(/^state=(.*)$/);
+ if (match)
+ {
+ response.setStatusLine(request.httpVersion, 204, "No content");
+ setState("offline.updatingIframe", match[1]);
+ }
+
+ if (request.queryString == "")
+ {
+ response.setStatusLine(request.httpVersion, 200, "Ok");
+ response.setHeader("Content-Type", "text/html");
+ response.setHeader("Cache-Control", "no-cache");
+ switch (getState("offline.updatingIframe"))
+ {
+ case "": // The default value
+ response.write(ver1iframe);
+ break;
+ case "second":
+ response.write(ver2iframe);
+ break;
+ }
+ }
+}
diff --git a/dom/tests/mochitest/ajax/offline/updatingImplicit.html b/dom/tests/mochitest/ajax/offline/updatingImplicit.html
new file mode 100644
index 0000000000..44931dd9da
--- /dev/null
+++ b/dom/tests/mochitest/ajax/offline/updatingImplicit.html
@@ -0,0 +1,53 @@
+<html xmlns="http://www.w3.org/1999/xhtml" manifest="https://example.com/tests/dom/tests/mochitest/ajax/offline/updatingManifest.sjs">
+<head>
+<title>Updating implicit</title>
+
+<script src="/tests/SimpleTest/SimpleTest.js"></script>
+<script type="text/javascript" src="/tests/dom/tests/mochitest/ajax/offline/offlineTests.js"></script>
+
+<script type="text/javascript">
+
+function manifestUpdated()
+{
+ // Assert that we are properly associated with the application
+ // cache.
+ var req = new XMLHttpRequest;
+ req.open("GET", "namespace2/script3.js", false);
+ try {
+ req.send(null);
+ window.opener.OfflineTest.ok(false, "Able to fetch unlisted resource, not properly associated.");
+ } catch(ex) {
+ window.opener.OfflineTest.ok(true, "Unable to fetch unlisted resource, properly associated.");
+ }
+
+ req = new XMLHttpRequest;
+ req.open("GET", "updatingImplicit.html", false);
+ try {
+ req.send(null);
+ window.opener.OfflineTest.ok(true, "Able to fetch listed resource, properly associated.");
+ } catch(ex) {
+ window.opener.OfflineTest.ok(false, "Unable to fetch listed resource, not properly associated.");
+ }
+
+ window.opener.implicitLoaded(window, false);
+}
+
+function manifestError()
+{
+ window.opener.implicitLoaded(window, true);
+}
+
+if (OfflineTest.setupChild()) {
+ applicationCache.onerror = OfflineTest.priv(manifestError);
+ applicationCache.onupdateready = OfflineTest.failEvent;
+ applicationCache.oncached = OfflineTest.failEvent;
+ applicationCache.onnoupdate = OfflineTest.priv(manifestUpdated);
+}
+
+</script>
+
+</head>
+
+<body>
+</body>
+</html>
diff --git a/dom/tests/mochitest/ajax/offline/updatingManifest.sjs b/dom/tests/mochitest/ajax/offline/updatingManifest.sjs
new file mode 100644
index 0000000000..d6e3411cab
--- /dev/null
+++ b/dom/tests/mochitest/ajax/offline/updatingManifest.sjs
@@ -0,0 +1,66 @@
+ver1manifest =
+ "CACHE MANIFEST\n" +
+ "# v1\n" +
+ "\n" +
+ "https://example.com/tests/dom/tests/mochitest/ajax/offline/offlineTests.js\n" +
+ "https://example.com/tests/dom/tests/mochitest/ajax/offline/updatingIframe.sjs\n" +
+ "\n" +
+ "FALLBACK:\n" +
+ "namespace1/ fallback.html\n" +
+ "\n" +
+ "NETWORK:\n" +
+ "onwhitelist.html\n";
+
+ver2manifest =
+ "CACHE MANIFEST\n" +
+ "# v2\n" +
+ "\n" +
+ "https://example.com/tests/SimpleTest/SimpleTest.js\n" +
+ "https://example.com/tests/dom/tests/mochitest/ajax/offline/offlineTests.js\n" +
+ "https://example.com/tests/dom/tests/mochitest/ajax/offline/updatingIframe.sjs" +
+ "\n" +
+ "FALLBACK:\n" +
+ "namespace1/ fallback.html\n" +
+ "namespace1/sub/ fallback2.html\n";
+
+ver3manifest =
+ "CACHE MANIFEST\n" +
+ "# v3\n" +
+ "\n" +
+ "https://example.com/tests/dom/tests/mochitest/ajax/offline/offlineTests.js\n" +
+ "https://example.com/tests/dom/tests/mochitest/ajax/offline/updatingIframe.sjs" +
+ "\n" +
+ "FALLBACK:\n" +
+ "namespace1/sub fallback2.html\n" +
+ "\n" +
+ "NETWORK:\n" +
+ "onwhitelist.html\n";
+
+function handleRequest(request, response)
+{
+ var match = request.queryString.match(/^state=(.*)$/);
+ if (match)
+ {
+ response.setStatusLine(request.httpVersion, 204, "No content");
+ setState("offline.updatingManifest", match[1]);
+ }
+
+ if (request.queryString == "")
+ {
+ response.setStatusLine(request.httpVersion, 200, "Ok");
+ response.setHeader("Content-Type", "text/cache-manifest");
+ response.setHeader("Cache-Control", "no-cache");
+ switch (getState("offline.updatingManifest"))
+ {
+ case "": // The default value
+ response.write(ver1manifest + "\n#" + getState("offline.updatingManifest"));
+ break;
+ case "second":
+ response.write(ver2manifest + "\n#" + getState("offline.updatingManifest"));
+ break;
+ case "third":
+ response.write(ver3manifest + "\n#" + getState("offline.updatingManifest"));
+ break;
+ }
+ }
+}
diff --git a/dom/tests/mochitest/ajax/offline/wildcardManifest.cacheManifest b/dom/tests/mochitest/ajax/offline/wildcardManifest.cacheManifest
new file mode 100644
index 0000000000..27a5ca1d56
--- /dev/null
+++ b/dom/tests/mochitest/ajax/offline/wildcardManifest.cacheManifest
@@ -0,0 +1,7 @@
+CACHE MANIFEST
+
+https://example.com/tests/SimpleTest/SimpleTest.js
+https://example.com/tests/dom/tests/mochitest/ajax/offline/offlineTests.js
+
+NETWORK:
+*
diff --git a/dom/tests/mochitest/ajax/offline/wildcardManifest.cacheManifest^headers^ b/dom/tests/mochitest/ajax/offline/wildcardManifest.cacheManifest^headers^
new file mode 100644
index 0000000000..5efde3c5b0
--- /dev/null
+++ b/dom/tests/mochitest/ajax/offline/wildcardManifest.cacheManifest^headers^
@@ -0,0 +1,2 @@
+Content-Type: text/cache-manifest
+