|
1 /* Any copyright is dedicated to the Public Domain. |
|
2 * http://creativecommons.org/publicdomain/zero/1.0/ */ |
|
3 |
|
4 /* |
|
5 * Tests for mozIAsyncFavicons::replaceFaviconData() |
|
6 */ |
|
7 |
|
8 let iconsvc = PlacesUtils.favicons; |
|
9 let histsvc = PlacesUtils.history; |
|
10 |
|
11 let originalFavicon = { |
|
12 file: do_get_file("favicon-normal16.png"), |
|
13 uri: uri(do_get_file("favicon-normal16.png")), |
|
14 data: readFileData(do_get_file("favicon-normal16.png")), |
|
15 mimetype: "image/png" |
|
16 }; |
|
17 |
|
18 let uniqueFaviconId = 0; |
|
19 function createFavicon(fileName) { |
|
20 let tempdir = Services.dirsvc.get("TmpD", Ci.nsILocalFile); |
|
21 |
|
22 // remove any existing file at the path we're about to copy to |
|
23 let outfile = tempdir.clone(); |
|
24 outfile.append(fileName); |
|
25 try { outfile.remove(false); } catch (e) {} |
|
26 |
|
27 originalFavicon.file.copyToFollowingLinks(tempdir, fileName); |
|
28 |
|
29 let stream = Cc["@mozilla.org/network/file-output-stream;1"] |
|
30 .createInstance(Ci.nsIFileOutputStream); |
|
31 stream.init(outfile, 0x02 | 0x08 | 0x10, 0600, 0); |
|
32 |
|
33 // append some data that sniffers/encoders will ignore that will distinguish |
|
34 // the different favicons we'll create |
|
35 uniqueFaviconId++; |
|
36 let uniqueStr = "uid:" + uniqueFaviconId; |
|
37 stream.write(uniqueStr, uniqueStr.length); |
|
38 stream.close(); |
|
39 |
|
40 do_check_eq(outfile.leafName.substr(0, fileName.length), fileName); |
|
41 |
|
42 return { |
|
43 file: outfile, |
|
44 uri: uri(outfile), |
|
45 data: readFileData(outfile), |
|
46 mimetype: "image/png" |
|
47 }; |
|
48 } |
|
49 |
|
50 function checkCallbackSucceeded(callbackMimetype, callbackData, sourceMimetype, sourceData) { |
|
51 do_check_eq(callbackMimetype, sourceMimetype); |
|
52 do_check_true(compareArrays(callbackData, sourceData)); |
|
53 } |
|
54 |
|
55 function run_test() { |
|
56 // check that the favicon loaded correctly |
|
57 do_check_eq(originalFavicon.data.length, 286); |
|
58 run_next_test(); |
|
59 }; |
|
60 |
|
61 add_task(function test_replaceFaviconData_validHistoryURI() { |
|
62 do_log_info("test replaceFaviconData for valid history uri"); |
|
63 |
|
64 let pageURI = uri("http://test1.bar/"); |
|
65 yield promiseAddVisits(pageURI); |
|
66 |
|
67 let favicon = createFavicon("favicon1.png"); |
|
68 |
|
69 iconsvc.replaceFaviconData(favicon.uri, favicon.data, favicon.data.length, |
|
70 favicon.mimetype); |
|
71 |
|
72 let deferSetAndFetchFavicon = Promise.defer(); |
|
73 iconsvc.setAndFetchFaviconForPage(pageURI, favicon.uri, true, |
|
74 PlacesUtils.favicons.FAVICON_LOAD_NON_PRIVATE, |
|
75 function test_replaceFaviconData_validHistoryURI_check(aURI, aDataLen, aData, aMimeType) { |
|
76 checkCallbackSucceeded(aMimeType, aData, favicon.mimetype, favicon.data); |
|
77 checkFaviconDataForPage( |
|
78 pageURI, favicon.mimetype, favicon.data, |
|
79 function test_replaceFaviconData_validHistoryURI_callback() { |
|
80 favicon.file.remove(false); |
|
81 deferSetAndFetchFavicon.resolve(); |
|
82 }); |
|
83 }); |
|
84 yield deferSetAndFetchFavicon.promise; |
|
85 |
|
86 yield promiseClearHistory(); |
|
87 }); |
|
88 |
|
89 add_task(function test_replaceFaviconData_overrideDefaultFavicon() { |
|
90 do_log_info("test replaceFaviconData to override a later setAndFetchFaviconForPage"); |
|
91 |
|
92 let pageURI = uri("http://test2.bar/"); |
|
93 yield promiseAddVisits(pageURI); |
|
94 |
|
95 let firstFavicon = createFavicon("favicon2.png"); |
|
96 let secondFavicon = createFavicon("favicon3.png"); |
|
97 |
|
98 iconsvc.replaceFaviconData( |
|
99 firstFavicon.uri, secondFavicon.data, secondFavicon.data.length, |
|
100 secondFavicon.mimetype); |
|
101 |
|
102 let deferSetAndFetchFavicon = Promise.defer(); |
|
103 iconsvc.setAndFetchFaviconForPage( |
|
104 pageURI, firstFavicon.uri, true, |
|
105 PlacesUtils.favicons.FAVICON_LOAD_NON_PRIVATE, |
|
106 function test_replaceFaviconData_overrideDefaultFavicon_check(aURI, aDataLen, aData, aMimeType) { |
|
107 checkCallbackSucceeded(aMimeType, aData, secondFavicon.mimetype, secondFavicon.data); |
|
108 checkFaviconDataForPage( |
|
109 pageURI, secondFavicon.mimetype, secondFavicon.data, |
|
110 function test_replaceFaviconData_overrideDefaultFavicon_callback() { |
|
111 firstFavicon.file.remove(false); |
|
112 secondFavicon.file.remove(false); |
|
113 deferSetAndFetchFavicon.resolve(); |
|
114 }); |
|
115 }); |
|
116 yield deferSetAndFetchFavicon.promise; |
|
117 |
|
118 yield promiseClearHistory(); |
|
119 }); |
|
120 |
|
121 add_task(function test_replaceFaviconData_replaceExisting() { |
|
122 do_log_info("test replaceFaviconData to override a previous setAndFetchFaviconForPage"); |
|
123 |
|
124 let pageURI = uri("http://test3.bar"); |
|
125 yield promiseAddVisits(pageURI); |
|
126 |
|
127 let firstFavicon = createFavicon("favicon4.png"); |
|
128 let secondFavicon = createFavicon("favicon5.png"); |
|
129 |
|
130 let deferSetAndFetchFavicon = Promise.defer(); |
|
131 iconsvc.setAndFetchFaviconForPage( |
|
132 pageURI, firstFavicon.uri, true, |
|
133 PlacesUtils.favicons.FAVICON_LOAD_NON_PRIVATE, |
|
134 function test_replaceFaviconData_replaceExisting_firstSet_check(aURI, aDataLen, aData, aMimeType) { |
|
135 checkCallbackSucceeded(aMimeType, aData, firstFavicon.mimetype, firstFavicon.data); |
|
136 checkFaviconDataForPage( |
|
137 pageURI, firstFavicon.mimetype, firstFavicon.data, |
|
138 function test_replaceFaviconData_overrideDefaultFavicon_firstCallback() { |
|
139 iconsvc.replaceFaviconData( |
|
140 firstFavicon.uri, secondFavicon.data, secondFavicon.data.length, |
|
141 secondFavicon.mimetype); |
|
142 promiseAsyncUpdates().then(function() { |
|
143 checkFaviconDataForPage( |
|
144 pageURI, secondFavicon.mimetype, secondFavicon.data, |
|
145 function test_replaceFaviconData_overrideDefaultFavicon_secondCallback() { |
|
146 firstFavicon.file.remove(false); |
|
147 secondFavicon.file.remove(false); |
|
148 deferSetAndFetchFavicon.resolve(); |
|
149 }); |
|
150 }); |
|
151 }); |
|
152 }); |
|
153 yield deferSetAndFetchFavicon.promise; |
|
154 |
|
155 yield promiseClearHistory(); |
|
156 }); |
|
157 |
|
158 add_task(function test_replaceFaviconData_unrelatedReplace() { |
|
159 do_log_info("test replaceFaviconData to not make unrelated changes"); |
|
160 |
|
161 let pageURI = uri("http://test4.bar/"); |
|
162 yield promiseAddVisits(pageURI); |
|
163 |
|
164 let favicon = createFavicon("favicon6.png"); |
|
165 let unrelatedFavicon = createFavicon("favicon7.png"); |
|
166 |
|
167 iconsvc.replaceFaviconData( |
|
168 unrelatedFavicon.uri, unrelatedFavicon.data, unrelatedFavicon.data.length, |
|
169 unrelatedFavicon.mimetype); |
|
170 |
|
171 let deferSetAndFetchFavicon = Promise.defer(); |
|
172 iconsvc.setAndFetchFaviconForPage( |
|
173 pageURI, favicon.uri, true, |
|
174 PlacesUtils.favicons.FAVICON_LOAD_NON_PRIVATE, |
|
175 function test_replaceFaviconData_unrelatedReplace_check(aURI, aDataLen, aData, aMimeType) { |
|
176 checkCallbackSucceeded(aMimeType, aData, favicon.mimetype, favicon.data); |
|
177 checkFaviconDataForPage( |
|
178 pageURI, favicon.mimetype, favicon.data, |
|
179 function test_replaceFaviconData_unrelatedReplace_callback() { |
|
180 favicon.file.remove(false); |
|
181 unrelatedFavicon.file.remove(false); |
|
182 deferSetAndFetchFavicon.resolve(); |
|
183 }); |
|
184 }); |
|
185 yield deferSetAndFetchFavicon.promise; |
|
186 |
|
187 yield promiseClearHistory(); |
|
188 }); |
|
189 |
|
190 add_task(function test_replaceFaviconData_badInputs() { |
|
191 do_log_info("test replaceFaviconData to throw on bad inputs"); |
|
192 |
|
193 let favicon = createFavicon("favicon8.png"); |
|
194 |
|
195 let ex = null; |
|
196 try { |
|
197 iconsvc.replaceFaviconData( |
|
198 favicon.uri, favicon.data, favicon.data.length, ""); |
|
199 } catch (e) { |
|
200 ex = e; |
|
201 } finally { |
|
202 do_check_true(!!ex); |
|
203 } |
|
204 |
|
205 ex = null; |
|
206 try { |
|
207 iconsvc.replaceFaviconData( |
|
208 null, favicon.data, favicon.data.length, favicon.mimeType); |
|
209 } catch (e) { |
|
210 ex = e; |
|
211 } finally { |
|
212 do_check_true(!!ex); |
|
213 } |
|
214 |
|
215 ex = null; |
|
216 try { |
|
217 iconsvc.replaceFaviconData( |
|
218 favicon.uri, null, 0, favicon.mimeType); |
|
219 } catch (e) { |
|
220 ex = e; |
|
221 } finally { |
|
222 do_check_true(!!ex); |
|
223 } |
|
224 |
|
225 favicon.file.remove(false); |
|
226 |
|
227 yield promiseClearHistory(); |
|
228 }); |
|
229 |
|
230 add_task(function test_replaceFaviconData_twiceReplace() { |
|
231 do_log_info("test replaceFaviconData on multiple replacements"); |
|
232 |
|
233 let pageURI = uri("http://test5.bar/"); |
|
234 yield promiseAddVisits(pageURI); |
|
235 |
|
236 let firstFavicon = createFavicon("favicon9.png"); |
|
237 let secondFavicon = createFavicon("favicon10.png"); |
|
238 |
|
239 iconsvc.replaceFaviconData( |
|
240 firstFavicon.uri, firstFavicon.data, firstFavicon.data.length, |
|
241 firstFavicon.mimetype); |
|
242 iconsvc.replaceFaviconData( |
|
243 firstFavicon.uri, secondFavicon.data, secondFavicon.data.length, |
|
244 secondFavicon.mimetype); |
|
245 |
|
246 let deferSetAndFetchFavicon = Promise.defer(); |
|
247 iconsvc.setAndFetchFaviconForPage( |
|
248 pageURI, firstFavicon.uri, true, |
|
249 PlacesUtils.favicons.FAVICON_LOAD_NON_PRIVATE, |
|
250 function test_replaceFaviconData_twiceReplace_check(aURI, aDataLen, aData, aMimeType) { |
|
251 checkCallbackSucceeded(aMimeType, aData, secondFavicon.mimetype, secondFavicon.data); |
|
252 checkFaviconDataForPage( |
|
253 pageURI, secondFavicon.mimetype, secondFavicon.data, |
|
254 function test_replaceFaviconData_twiceReplace_callback() { |
|
255 firstFavicon.file.remove(false); |
|
256 secondFavicon.file.remove(false); |
|
257 deferSetAndFetchFavicon.resolve(); |
|
258 }); |
|
259 }); |
|
260 yield deferSetAndFetchFavicon.promise; |
|
261 |
|
262 yield promiseClearHistory(); |
|
263 }); |