| |
1 /** |
| |
2 * Any copyright is dedicated to the Public Domain. |
| |
3 * http://creativecommons.org/publicdomain/zero/1.0/ |
| |
4 */ |
| |
5 |
| |
6 var testGenerator = testSteps(); |
| |
7 |
| |
8 function testSteps() |
| |
9 { |
| |
10 const name = this.window ? window.location.pathname : "Splendid Test"; |
| |
11 |
| |
12 const urls = [ |
| |
13 { url: "http://www.alpha.com", flags: [true, true, false, false] }, |
| |
14 { url: "http://www.beta.com", flags: [true, false, false, false] }, |
| |
15 { url: "http://www.gamma.com", flags: [true, true, false, false] }, |
| |
16 { url: "http://www.delta.com", flags: [true, true, false, false] }, |
| |
17 { url: "http://www.epsilon.com", flags: [true, true, false, false] }, |
| |
18 { url: "http://www2.alpha.com", flags: [true, true, false, false] }, |
| |
19 { url: "http://www2.beta.com", flags: [true, true, false, false] }, |
| |
20 { url: "http://www2.gamma.com", flags: [true, true, true, false] }, |
| |
21 { url: "http://www2.delta.com", flags: [true, true, true, true] }, |
| |
22 { url: "http://www2.epsilon.com", flags: [true, true, true, true] }, |
| |
23 { url: "http://joe.blog.alpha.com", flags: [true, true, true, true] }, |
| |
24 { url: "http://joe.blog.beta.com", flags: [true, true, true, true] }, |
| |
25 { url: "http://joe.blog.gamma.com", flags: [true, true, true, true] }, |
| |
26 { url: "http://joe.blog.delta.com", flags: [true, true, true, true] }, |
| |
27 { url: "http://joe.blog.epsilon.com", flags: [true, true, true, true] }, |
| |
28 { url: "http://www.rudolf.org", flags: [true, true, true, true] }, |
| |
29 { url: "http://www.pauline.org", flags: [true, true, true, true] }, |
| |
30 { url: "http://www.marie.org", flags: [true, true, true, true] }, |
| |
31 { url: "http://www.john.org", flags: [true, true, true, true] }, |
| |
32 { url: "http://www.ema.org", flags: [true, true, true, true] }, |
| |
33 { url: "http://www.trigger.com", flags: [false, true, true, true] } |
| |
34 ]; |
| |
35 const lastIndex = urls.length - 1; |
| |
36 const lastUrl = urls[lastIndex].url; |
| |
37 |
| |
38 let quotaManager = |
| |
39 Components.classes["@mozilla.org/dom/quota/manager;1"] |
| |
40 .getService(Components.interfaces.nsIQuotaManager); |
| |
41 |
| |
42 let ioService = Components.classes["@mozilla.org/network/io-service;1"] |
| |
43 .getService(Components.interfaces.nsIIOService); |
| |
44 |
| |
45 let dbSize = 0; |
| |
46 |
| |
47 let databases = []; |
| |
48 |
| |
49 function setLimit(limit) { |
| |
50 if (limit) { |
| |
51 SpecialPowers.setIntPref("dom.quotaManager.temporaryStorage.fixedLimit", |
| |
52 limit); |
| |
53 return; |
| |
54 } |
| |
55 SpecialPowers.clearUserPref("dom.quotaManager.temporaryStorage.fixedLimit"); |
| |
56 } |
| |
57 |
| |
58 function getPrincipal(url) { |
| |
59 let uri = ioService.newURI(url, null, null); |
| |
60 return Components.classes["@mozilla.org/scriptsecuritymanager;1"] |
| |
61 .getService(Components.interfaces.nsIScriptSecurityManager) |
| |
62 .getNoAppCodebasePrincipal(uri); |
| |
63 } |
| |
64 |
| |
65 function getUsageForUrl(url, usageHandler) { |
| |
66 let uri = ioService.newURI(url, null, null); |
| |
67 function callback(uri, usage, fileUsage) { |
| |
68 usageHandler(usage, fileUsage); |
| |
69 } |
| |
70 quotaManager.getUsageForURI(uri, callback); |
| |
71 } |
| |
72 |
| |
73 function grabUsageAndContinueHandler(usage, fileUsage) { |
| |
74 testGenerator.send(usage); |
| |
75 } |
| |
76 |
| |
77 function checkUsage(stageIndex) { |
| |
78 let handledIndex = 0; |
| |
79 |
| |
80 function usageHandler(usage, fileUsage) { |
| |
81 if (urls[handledIndex].flags[stageIndex - 1]) { |
| |
82 ok(usage > 0, "Correct usage"); |
| |
83 } |
| |
84 else { |
| |
85 ok(usage == 0, "Correct usage"); |
| |
86 } |
| |
87 if (++handledIndex == urls.length) { |
| |
88 continueToNextStep(); |
| |
89 } |
| |
90 } |
| |
91 |
| |
92 for (let i = 0; i < urls.length; i++) { |
| |
93 getUsageForUrl(urls[i].url, usageHandler); |
| |
94 } |
| |
95 } |
| |
96 |
| |
97 // Enable clear() and test() |
| |
98 let testingEnabled = |
| |
99 SpecialPowers.getBoolPref("dom.quotaManager.testing"); |
| |
100 SpecialPowers.setBoolPref("dom.quotaManager.testing", true) |
| |
101 |
| |
102 // Calibration |
| |
103 let request = indexedDB.openForPrincipal(getPrincipal(lastUrl), name, |
| |
104 { storage: "temporary" }); |
| |
105 request.onerror = errorHandler; |
| |
106 request.onsuccess = grabEventAndContinueHandler; |
| |
107 let event = yield undefined; |
| |
108 |
| |
109 getUsageForUrl(lastUrl, grabUsageAndContinueHandler); |
| |
110 dbSize = yield undefined; |
| |
111 |
| |
112 setLimit(lastIndex * dbSize / 1024); |
| |
113 quotaManager.clear(); |
| |
114 |
| |
115 // Stage 1 |
| |
116 for (let i = 0; i < lastIndex; i++) { |
| |
117 let data = urls[i]; |
| |
118 |
| |
119 request = indexedDB.openForPrincipal(getPrincipal(data.url), name, |
| |
120 { storage: "temporary" }); |
| |
121 request.onerror = errorHandler; |
| |
122 request.onupgradeneeded = grabEventAndContinueHandler; |
| |
123 request.onsuccess = grabEventAndContinueHandler; |
| |
124 event = yield undefined; |
| |
125 |
| |
126 is(event.type, "upgradeneeded", "Got correct event type"); |
| |
127 |
| |
128 let db = event.target.result; |
| |
129 db.createObjectStore("foo", { }); |
| |
130 |
| |
131 event = yield undefined; |
| |
132 |
| |
133 is(event.type, "success", "Got correct event type"); |
| |
134 |
| |
135 databases.push(event.target.result); |
| |
136 } |
| |
137 |
| |
138 request = indexedDB.openForPrincipal(getPrincipal(lastUrl), name, |
| |
139 { storage: "temporary" }); |
| |
140 request.addEventListener("error", new ExpectError("QuotaExceededError")); |
| |
141 request.onsuccess = unexpectedSuccessHandler; |
| |
142 event = yield undefined; |
| |
143 |
| |
144 checkUsage(1); |
| |
145 yield undefined; |
| |
146 |
| |
147 // Stage 2 |
| |
148 for (let i = 1; i < urls.length; i++) { |
| |
149 databases[i] = null; |
| |
150 |
| |
151 scheduleGC(); |
| |
152 yield undefined; |
| |
153 |
| |
154 // The origin access time is set to the current system time when the first |
| |
155 // database for an origin is registered or the last one is unregistered. |
| |
156 // The registration happens when the database object is being created and |
| |
157 // the unregistration when it is unlinked/garbage collected. |
| |
158 // Some older windows systems have the system time limited to a maximum |
| |
159 // resolution of 10 or 15 milliseconds, so without a pause here we would |
| |
160 // end up with origins with the same access time which would cause random |
| |
161 // failures. |
| |
162 setTimeout(function() { testGenerator.next(); }, 20); |
| |
163 yield undefined; |
| |
164 } |
| |
165 |
| |
166 request = indexedDB.openForPrincipal(getPrincipal(lastUrl), name, |
| |
167 { storage: "temporary" }); |
| |
168 request.onerror = errorHandler; |
| |
169 request.onupgradeneeded = grabEventAndContinueHandler; |
| |
170 request.onsuccess = grabEventAndContinueHandler; |
| |
171 event = yield undefined; |
| |
172 |
| |
173 is(event.type, "upgradeneeded", "Got correct event type"); |
| |
174 |
| |
175 let db = event.target.result; |
| |
176 db.createObjectStore("foo", { }); |
| |
177 |
| |
178 event = yield undefined; |
| |
179 |
| |
180 is(event.type, "success", "Got correct event type"); |
| |
181 |
| |
182 checkUsage(2); |
| |
183 yield undefined; |
| |
184 |
| |
185 // Stage 3 |
| |
186 setLimit(14 * dbSize / 1024); |
| |
187 quotaManager.reset(); |
| |
188 |
| |
189 request = indexedDB.openForPrincipal(getPrincipal(lastUrl), name, |
| |
190 { storage: "temporary" }); |
| |
191 request.onerror = errorHandler; |
| |
192 request.onsuccess = grabEventAndContinueHandler; |
| |
193 event = yield undefined; |
| |
194 |
| |
195 is(event.type, "success", "Got correct event type"); |
| |
196 |
| |
197 let db = event.target.result; |
| |
198 |
| |
199 checkUsage(3); |
| |
200 yield undefined; |
| |
201 |
| |
202 // Stage 4 |
| |
203 let trans = db.transaction(["foo"], "readwrite"); |
| |
204 |
| |
205 let blob = Blob(["bar"]); |
| |
206 request = trans.objectStore("foo").add(blob, 42); |
| |
207 request.onerror = errorHandler; |
| |
208 request.onsuccess = grabEventAndContinueHandler; |
| |
209 event = yield undefined; |
| |
210 |
| |
211 trans.oncomplete = grabEventAndContinueHandler; |
| |
212 event = yield undefined; |
| |
213 |
| |
214 checkUsage(4); |
| |
215 yield undefined; |
| |
216 |
| |
217 // Cleanup |
| |
218 setLimit(); |
| |
219 quotaManager.reset(); |
| |
220 |
| |
221 SpecialPowers.setBoolPref("dom.quotaManager.testing", testingEnabled); |
| |
222 |
| |
223 finishTest(); |
| |
224 yield undefined; |
| |
225 } |