|
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 } |