|
1 /* This Source Code Form is subject to the terms of the Mozilla Public |
|
2 * License, v. 2.0. If a copy of the MPL was not distributed with this file, |
|
3 * You can obtain one at http://mozilla.org/MPL/2.0/. */ |
|
4 |
|
5 /** |
|
6 * This test executes nsIOfflineCacheUpdateService.scheduleAppUpdate API |
|
7 * 1. preloads an app with a manifest to a custom sudir in the profile (for simplicity) |
|
8 * 2. observes progress and completion of the update |
|
9 * 3. checks presence of index.sql and files in the expected location |
|
10 */ |
|
11 |
|
12 Cu.import("resource://testing-common/httpd.js"); |
|
13 |
|
14 var httpServer = null; |
|
15 var cacheUpdateObserver = null; |
|
16 |
|
17 function make_channel(url, callback, ctx) { |
|
18 var ios = Cc["@mozilla.org/network/io-service;1"]. |
|
19 getService(Ci.nsIIOService); |
|
20 return ios.newChannel(url, "", null); |
|
21 } |
|
22 |
|
23 function make_uri(url) { |
|
24 var ios = Cc["@mozilla.org/network/io-service;1"]. |
|
25 getService(Ci.nsIIOService); |
|
26 return ios.newURI(url, null, null); |
|
27 } |
|
28 |
|
29 // start the test with loading this master entry referencing the manifest |
|
30 function masterEntryHandler(metadata, response) |
|
31 { |
|
32 var masterEntryContent = "<html manifest='/manifest'></html>"; |
|
33 response.setHeader("Content-Type", "text/html"); |
|
34 response.bodyOutputStream.write(masterEntryContent, masterEntryContent.length); |
|
35 } |
|
36 |
|
37 // manifest defines fallback namespace from any /redirect path to /content |
|
38 function manifestHandler(metadata, response) |
|
39 { |
|
40 var manifestContent = "CACHE MANIFEST\n"; |
|
41 response.setHeader("Content-Type", "text/cache-manifest"); |
|
42 response.bodyOutputStream.write(manifestContent, manifestContent.length); |
|
43 } |
|
44 |
|
45 // finally check we got fallback content |
|
46 function finish_test(customDir) |
|
47 { |
|
48 var offlineCacheDir = customDir.clone(); |
|
49 offlineCacheDir.append("OfflineCache"); |
|
50 |
|
51 var indexSqlFile = offlineCacheDir.clone(); |
|
52 indexSqlFile.append('index.sqlite'); |
|
53 do_check_eq(indexSqlFile.exists(), true); |
|
54 |
|
55 var file1 = offlineCacheDir.clone(); |
|
56 file1.append("2"); |
|
57 file1.append("E"); |
|
58 file1.append("2C99DE6E7289A5-0"); |
|
59 do_check_eq(file1.exists(), true); |
|
60 |
|
61 var file2 = offlineCacheDir.clone(); |
|
62 file2.append("8"); |
|
63 file2.append("6"); |
|
64 file2.append("0B457F75198B29-0"); |
|
65 do_check_eq(file2.exists(), true); |
|
66 |
|
67 // This must not throw an exception. After the update has finished |
|
68 // the index file can be freely removed. This way we check this process |
|
69 // is no longer keeping the file open. Check like this will probably |
|
70 // work only Windows systems. |
|
71 |
|
72 // This test could potentially randomaly fail when we start closing |
|
73 // the offline cache database off the main thread. Tries in a loop |
|
74 // may be a solution then. |
|
75 try { |
|
76 indexSqlFile.remove(false); |
|
77 do_check_true(true); |
|
78 } |
|
79 catch (ex) { |
|
80 do_throw("Could not remove the sqlite.index file, we still keep it open \n" + ex + "\n"); |
|
81 } |
|
82 |
|
83 httpServer.stop(do_test_finished); |
|
84 } |
|
85 |
|
86 function run_test() |
|
87 { |
|
88 httpServer = new HttpServer(); |
|
89 httpServer.registerPathHandler("/masterEntry", masterEntryHandler); |
|
90 httpServer.registerPathHandler("/manifest", manifestHandler); |
|
91 httpServer.start(4444); |
|
92 |
|
93 var profileDir = do_get_profile(); |
|
94 var customDir = profileDir.clone(); |
|
95 customDir.append("customOfflineCacheDir" + Math.random()); |
|
96 |
|
97 var pm = Cc["@mozilla.org/permissionmanager;1"] |
|
98 .getService(Ci.nsIPermissionManager); |
|
99 var uri = make_uri("http://localhost:4444"); |
|
100 var principal = Cc["@mozilla.org/scriptsecuritymanager;1"] |
|
101 .getService(Ci.nsIScriptSecurityManager) |
|
102 .getNoAppCodebasePrincipal(uri); |
|
103 |
|
104 if (pm.testPermissionFromPrincipal(principal, "offline-app") != 0) { |
|
105 dump("Previous test failed to clear offline-app permission! Expect failures.\n"); |
|
106 } |
|
107 pm.addFromPrincipal(principal, "offline-app", Ci.nsIPermissionManager.ALLOW_ACTION); |
|
108 |
|
109 var ps = Cc["@mozilla.org/preferences-service;1"] |
|
110 .getService(Ci.nsIPrefBranch); |
|
111 ps.setBoolPref("browser.cache.offline.enable", true); |
|
112 // Set this pref to mimic the default browser behavior. |
|
113 ps.setComplexValue("browser.cache.offline.parent_directory", Ci.nsILocalFile, profileDir); |
|
114 |
|
115 var us = Cc["@mozilla.org/offlinecacheupdate-service;1"]. |
|
116 getService(Ci.nsIOfflineCacheUpdateService); |
|
117 var update = us.scheduleAppUpdate( |
|
118 make_uri("http://localhost:4444/manifest"), |
|
119 make_uri("http://localhost:4444/masterEntry"), |
|
120 0 /* no AppID */, false /* not in browser*/, |
|
121 customDir); |
|
122 |
|
123 var expectedStates = [ |
|
124 Ci.nsIOfflineCacheUpdateObserver.STATE_DOWNLOADING, |
|
125 Ci.nsIOfflineCacheUpdateObserver.STATE_ITEMSTARTED, |
|
126 Ci.nsIOfflineCacheUpdateObserver.STATE_ITEMPROGRESS, |
|
127 Ci.nsIOfflineCacheUpdateObserver.STATE_ITEMCOMPLETED, |
|
128 Ci.nsIOfflineCacheUpdateObserver.STATE_FINISHED |
|
129 ]; |
|
130 |
|
131 update.addObserver({ |
|
132 updateStateChanged: function(update, state) |
|
133 { |
|
134 do_check_eq(state, expectedStates.shift()); |
|
135 |
|
136 if (state == Ci.nsIOfflineCacheUpdateObserver.STATE_FINISHED) |
|
137 finish_test(customDir); |
|
138 }, |
|
139 |
|
140 applicationCacheAvailable: function(appCache) |
|
141 { |
|
142 } |
|
143 }, false); |
|
144 |
|
145 do_test_pending(); |
|
146 } |