OLD | NEW |
| (Empty) |
1 (function() | |
2 { | |
3 module("Filter storage read/write", { | |
4 setup: function() | |
5 { | |
6 prepareFilterComponents.call(this); | |
7 preparePrefs.call(this); | |
8 | |
9 FilterStorage.addSubscription(Subscription.fromURL("~fl~")); | |
10 }, | |
11 teardown: function() | |
12 { | |
13 restoreFilterComponents.call(this); | |
14 restorePrefs.call(this); | |
15 } | |
16 }); | |
17 | |
18 let {FileUtils} = Cu.import("resource://gre/modules/FileUtils.jsm", null); | |
19 let {NetUtil} = Cu.import("resource://gre/modules/NetUtil.jsm", null); | |
20 | |
21 function loadFilters(file, callback) | |
22 { | |
23 let listener = function(action) | |
24 { | |
25 if (action == "load") | |
26 { | |
27 FilterNotifier.removeListener(listener); | |
28 callback(); | |
29 } | |
30 }; | |
31 FilterNotifier.addListener(listener); | |
32 | |
33 FilterStorage.loadFromDisk(file); | |
34 } | |
35 | |
36 function writeToFile(file, data) | |
37 { | |
38 let converter = Cc["@mozilla.org/intl/scriptableunicodeconverter"].createIns
tance(Ci.nsIScriptableUnicodeConverter); | |
39 converter.charset = "utf-8"; | |
40 data = converter.ConvertFromUnicode(data); | |
41 | |
42 let stream = FileUtils.openFileOutputStream(file); | |
43 stream.write(data, data.length); | |
44 stream.close(); | |
45 } | |
46 | |
47 function saveFilters(file, callback) | |
48 { | |
49 let listener = function(action) | |
50 { | |
51 if (action == "save") | |
52 { | |
53 FilterNotifier.removeListener(listener); | |
54 callback(); | |
55 } | |
56 }; | |
57 FilterNotifier.addListener(listener); | |
58 | |
59 FilterStorage.saveToDisk(file); | |
60 } | |
61 | |
62 function testReadWrite(withExternal) | |
63 { | |
64 let tempFile = FileUtils.getFile("TmpD", ["temp_patterns1.ini"]); | |
65 let tempFile2 = FileUtils.getFile("TmpD", ["temp_patterns2.ini"]); | |
66 tempFile.createUnique(tempFile.NORMAL_FILE_TYPE, FileUtils.PERMS_FILE); | |
67 createTempFile(); | |
68 | |
69 function canonize(data) | |
70 { | |
71 let curSection = null; | |
72 let sections = []; | |
73 for (let line of (data + "\n[end]").split(/[\r\n]+/)) | |
74 { | |
75 if (/^\[.*\]$/.test(line)) | |
76 { | |
77 if (curSection) | |
78 sections.push(curSection); | |
79 | |
80 curSection = {header: line, data: []}; | |
81 } | |
82 else if (curSection && /\S/.test(line)) | |
83 curSection.data.push(line); | |
84 } | |
85 for (let section of sections) | |
86 { | |
87 section.key = section.header + " " + section.data[0]; | |
88 section.data.sort(); | |
89 } | |
90 sections.sort(function(a, b) | |
91 { | |
92 if (a.key < b.key) | |
93 return -1; | |
94 else if (a.key > b.key) | |
95 return 1; | |
96 else | |
97 return 0; | |
98 }); | |
99 return sections.map(function(section) { | |
100 return [section.header].concat(section.data).join("\n"); | |
101 }).join("\n"); | |
102 } | |
103 | |
104 function createTempFile() | |
105 { | |
106 let request = new XMLHttpRequest(); | |
107 request.open("GET", "data/patterns.ini"); | |
108 request.overrideMimeType("text/plain; charset=utf-8"); | |
109 request.addEventListener("load", function() | |
110 { | |
111 writeToFile(tempFile, request.responseText); | |
112 loadFilters(tempFile, saveFile); | |
113 }, false); | |
114 request.send(null); | |
115 } | |
116 | |
117 function saveFile() | |
118 { | |
119 equal(FilterStorage.fileProperties.version, FilterStorage.formatVersion, "
File format version"); | |
120 | |
121 if (withExternal) | |
122 { | |
123 let {AdblockPlus} = Cu.import(Cc["@adblockplus.org/abp/public;1"].getSer
vice(Ci.nsIURI).spec, null); | |
124 AdblockPlus.updateExternalSubscription("~external~external subscription
ID", "External subscription", ["foo", "bar"]); | |
125 | |
126 let externalSubscriptions = FilterStorage.subscriptions.filter(function
(subscription) subscription instanceof ExternalSubscription); | |
127 equal(externalSubscriptions.length, 1, "Number of external subscriptions
after updateExternalSubscription"); | |
128 | |
129 if (externalSubscriptions.length == 1) | |
130 { | |
131 equal(externalSubscriptions[0].url, "~external~external subscription I
D", "ID of external subscription"); | |
132 equal(externalSubscriptions[0].filters.length, 2, "Number of filters i
n external subscription"); | |
133 } | |
134 } | |
135 | |
136 saveFilters(tempFile2, compareFile); | |
137 } | |
138 | |
139 function compareFile() | |
140 { | |
141 let stream = Cc["@mozilla.org/network/file-input-stream;1"].createInstance
(Ci.nsIFileInputStream); | |
142 stream.init(tempFile2, FileUtils.MODE_RDONLY, FileUtils.PERMS_FILE, Ci.nsI
FileInputStream.DEFER_OPEN); | |
143 | |
144 NetUtil.asyncFetch(stream, function(inputStream, nsresult) | |
145 { | |
146 let result = NetUtil.readInputStreamToString(inputStream, inputStream.av
ailable(), {charset: "utf-8"}); | |
147 | |
148 let request = new XMLHttpRequest(); | |
149 request.open("GET", "data/patterns.ini"); | |
150 request.overrideMimeType("text/plain"); | |
151 request.addEventListener("load", function() | |
152 { | |
153 let expected = request.responseText; | |
154 equal(canonize(result), canonize(expected), "Read/write result"); | |
155 | |
156 tempFile.remove(false); | |
157 tempFile2.remove(false); | |
158 start(); | |
159 }, false); | |
160 request.send(null); | |
161 }); | |
162 } | |
163 } | |
164 | |
165 asyncTest("Read and save to file", testReadWrite.bind(false)); | |
166 asyncTest("Read, add external subscription and save to file", testReadWrite.bi
nd(true)); | |
167 | |
168 let groupTests = [ | |
169 ["~wl~", "whitelist"], | |
170 ["~fl~", "blocking"], | |
171 ["~eh~", "elemhide"] | |
172 ]; | |
173 for (let i = 0; i < groupTests.length; i++) | |
174 { | |
175 let [url, defaults] = groupTests[i]; | |
176 asyncTest("Read empty legacy user-defined group (" + url + ")", function() | |
177 { | |
178 let data = "[Subscription]\nurl=" + url; | |
179 let tempFile = FileUtils.getFile("TmpD", ["temp_patterns1.ini"]); | |
180 writeToFile(tempFile, data); | |
181 | |
182 loadFilters(tempFile, function() | |
183 { | |
184 tempFile.remove(false); | |
185 equal(FilterStorage.subscriptions.length, 0, "Number of filter subscript
ions"); | |
186 start(); | |
187 }); | |
188 }); | |
189 asyncTest("Read non-empty legacy user-defined group (" + url + ")", function
() | |
190 { | |
191 let data = "[Subscription]\nurl=" + url + "\n[Subscription filters]\nfoo"; | |
192 let tempFile = FileUtils.getFile("TmpD", ["temp_patterns1.ini"]); | |
193 writeToFile(tempFile, data); | |
194 | |
195 loadFilters(tempFile, function() | |
196 { | |
197 tempFile.remove(false); | |
198 equal(FilterStorage.subscriptions.length, 1, "Number of filter subscript
ions"); | |
199 if (FilterStorage.subscriptions.length == 1) | |
200 { | |
201 let subscription = FilterStorage.subscriptions[0]; | |
202 equal(subscription.url, url, "Subscription ID"); | |
203 equal(subscription.title, Utils.getString(defaults + "Group_title"), "
Subscription title"); | |
204 deepEqual(subscription.defaults, [defaults], "Default types"); | |
205 equal(subscription.filters.length, 1, "Number of subscription filters"
); | |
206 if (subscription.filters.length == 1) | |
207 equal(subscription.filters[0].text, "foo", "First filter"); | |
208 } | |
209 start(); | |
210 }); | |
211 }); | |
212 } | |
213 | |
214 asyncTest("Read legacy user-defined filters", function() | |
215 { | |
216 let data = "[Subscription]\nurl=~user~1234\ntitle=Foo\n[Subscription filters
]\n[User patterns]\nfoo\n\\[bar]\nfoo#bar"; | |
217 let tempFile = FileUtils.getFile("TmpD", ["temp_patterns1.ini"]); | |
218 writeToFile(tempFile, data); | |
219 | |
220 loadFilters(tempFile, function() | |
221 { | |
222 tempFile.remove(false); | |
223 equal(FilterStorage.subscriptions.length, 1, "Number of filter subscriptio
ns"); | |
224 if (FilterStorage.subscriptions.length == 1) | |
225 { | |
226 let subscription = FilterStorage.subscriptions[0]; | |
227 equal(subscription.filters.length, 3, "Number of subscription filters"); | |
228 if (subscription.filters.length == 3) | |
229 { | |
230 equal(subscription.filters[0].text, "foo", "First filter"); | |
231 equal(subscription.filters[1].text, "[bar]", "Second filter"); | |
232 equal(subscription.filters[2].text, "foo#bar", "Third filter"); | |
233 } | |
234 } | |
235 start(); | |
236 }); | |
237 }); | |
238 | |
239 asyncTest("Saving without backups", function() | |
240 { | |
241 Prefs.patternsbackups = 0; | |
242 Prefs.patternsbackupinterval = 24; | |
243 | |
244 let tempFile = FileUtils.getFile("TmpD", ["temp_patterns.ini"]); | |
245 tempFile.createUnique(tempFile.NORMAL_FILE_TYPE, FileUtils.PERMS_FILE); | |
246 FilterStorage.__defineGetter__("sourceFile", () => tempFile.clone()); | |
247 | |
248 saveFilters(null, function() | |
249 { | |
250 saveFilters(null, function() | |
251 { | |
252 let backupFile = tempFile.clone(); | |
253 backupFile.leafName = backupFile.leafName.replace(/\.ini$/, "-backup1.in
i"); | |
254 ok(!backupFile.exists(), "Backup shouldn't be created"); | |
255 start(); | |
256 }); | |
257 }); | |
258 }); | |
259 | |
260 asyncTest("Saving with backups", function() | |
261 { | |
262 Prefs.patternsbackups = 2; | |
263 Prefs.patternsbackupinterval = 24; | |
264 | |
265 let tempFile = FileUtils.getFile("TmpD", ["temp_patterns.ini"]); | |
266 tempFile.createUnique(tempFile.NORMAL_FILE_TYPE, FileUtils.PERMS_FILE); | |
267 FilterStorage.__defineGetter__("sourceFile", () => tempFile.clone()); | |
268 | |
269 let backupFile = tempFile.clone(); | |
270 backupFile.leafName = backupFile.leafName.replace(/\.ini$/, "-backup1.ini"); | |
271 | |
272 let backupFile2 = tempFile.clone(); | |
273 backupFile2.leafName = backupFile2.leafName.replace(/\.ini$/, "-backup2.ini"
); | |
274 | |
275 let backupFile3 = tempFile.clone(); | |
276 backupFile3.leafName = backupFile3.leafName.replace(/\.ini$/, "-backup3.ini"
); | |
277 | |
278 let oldModifiedTime; | |
279 | |
280 saveFilters(null, callback1); | |
281 | |
282 function callback1() | |
283 { | |
284 // Save again immediately | |
285 saveFilters(null, callback2); | |
286 } | |
287 | |
288 function callback2() | |
289 { | |
290 backupFile = backupFile.clone(); // File parameters are cached, clone to
prevent this | |
291 ok(backupFile.exists(), "First backup created"); | |
292 | |
293 backupFile.lastModifiedTime -= 10000; | |
294 oldModifiedTime = backupFile.lastModifiedTime; | |
295 saveFilters(null, callback3); | |
296 } | |
297 | |
298 function callback3() | |
299 { | |
300 backupFile = backupFile.clone(); // File parameters are cached, clone to
prevent this | |
301 equal(backupFile.lastModifiedTime, oldModifiedTime, "Backup not overwritte
n if it is only 10 seconds old"); | |
302 | |
303 backupFile.lastModifiedTime -= 40*60*60*1000; | |
304 oldModifiedTime = backupFile.lastModifiedTime; | |
305 saveFilters(null, callback4); | |
306 } | |
307 | |
308 function callback4() | |
309 { | |
310 backupFile = backupFile.clone(); // File parameters are cached, clone to
prevent this | |
311 notEqual(backupFile.lastModifiedTime, oldModifiedTime, "Backup overwritten
if it is 40 hours old"); | |
312 | |
313 backupFile2 = backupFile2.clone(); // File parameters are cached, clone t
o prevent this | |
314 ok(backupFile2.exists(), "Second backup created when first backup is overw
ritten"); | |
315 | |
316 backupFile.lastModifiedTime -= 20000; | |
317 oldModifiedTime = backupFile2.lastModifiedTime; | |
318 saveFilters(null, callback5); | |
319 } | |
320 | |
321 function callback5() | |
322 { | |
323 backupFile2 = backupFile2.clone(); // File parameters are cached, clone t
o prevent this | |
324 equal(backupFile2.lastModifiedTime, oldModifiedTime, "Second backup not ov
erwritten if first one is only 20 seconds old"); | |
325 | |
326 backupFile.lastModifiedTime -= 25*60*60*1000; | |
327 oldModifiedTime = backupFile2.lastModifiedTime; | |
328 saveFilters(null, callback6); | |
329 } | |
330 | |
331 function callback6() | |
332 { | |
333 backupFile2 = backupFile2.clone(); // File parameters are cached, clone t
o prevent this | |
334 notEqual(backupFile2.lastModifiedTime, oldModifiedTime, "Second backup ove
rwritten if first one is 25 hours old"); | |
335 | |
336 ok(!backupFile3.exists(), "Third backup not created with patternsbackups =
2"); | |
337 | |
338 try | |
339 { | |
340 tempFile.remove(false); | |
341 } catch (e) {} | |
342 try | |
343 { | |
344 backupFile.remove(false); | |
345 } catch (e) {} | |
346 try | |
347 { | |
348 backupFile2.remove(false); | |
349 } catch (e) {} | |
350 try | |
351 { | |
352 backupFile3.remove(false); | |
353 } catch (e) {} | |
354 | |
355 start(); | |
356 } | |
357 }); | |
358 })(); | |
OLD | NEW |