toolkit/components/places/tests/favicons/test_replaceFaviconDataFromDataURL.js

branch
TOR_BUG_9701
changeset 15
b8a032363ba2
equal deleted inserted replaced
-1:000000000000 0:562fae74bb82
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 createDataURLForFavicon(favicon) {
51 return "data:" + favicon.mimetype + ";base64," + toBase64(favicon.data);
52 }
53
54 function checkCallbackSucceeded(callbackMimetype, callbackData, sourceMimetype, sourceData) {
55 do_check_eq(callbackMimetype, sourceMimetype);
56 do_check_true(compareArrays(callbackData, sourceData));
57 }
58
59 function run_test() {
60 // check that the favicon loaded correctly
61 do_check_eq(originalFavicon.data.length, 286);
62 run_next_test();
63 };
64
65 add_task(function test_replaceFaviconDataFromDataURL_validHistoryURI() {
66 do_log_info("test replaceFaviconDataFromDataURL for valid history uri");
67
68 let pageURI = uri("http://test1.bar/");
69 yield promiseAddVisits(pageURI);
70
71 let favicon = createFavicon("favicon1.png");
72 iconsvc.replaceFaviconDataFromDataURL(favicon.uri, createDataURLForFavicon(favicon));
73
74 let deferSetAndFetchFavicon = Promise.defer();
75 iconsvc.setAndFetchFaviconForPage(pageURI, favicon.uri, true,
76 PlacesUtils.favicons.FAVICON_LOAD_NON_PRIVATE,
77 function test_replaceFaviconDataFromDataURL_validHistoryURI_check(aURI, aDataLen, aData, aMimeType) {
78 checkCallbackSucceeded(aMimeType, aData, favicon.mimetype, favicon.data);
79 checkFaviconDataForPage(
80 pageURI, favicon.mimetype, favicon.data,
81 function test_replaceFaviconDataFromDataURL_validHistoryURI_callback() {
82 favicon.file.remove(false);
83 deferSetAndFetchFavicon.resolve();
84 });
85 });
86 yield deferSetAndFetchFavicon.promise;
87
88 yield promiseClearHistory();
89 });
90
91 add_task(function test_replaceFaviconDataFromDataURL_overrideDefaultFavicon() {
92 do_log_info("test replaceFaviconDataFromDataURL to override a later setAndFetchFaviconForPage");
93
94 let pageURI = uri("http://test2.bar/");
95 yield promiseAddVisits(pageURI);
96
97 let firstFavicon = createFavicon("favicon2.png");
98 let secondFavicon = createFavicon("favicon3.png");
99
100 iconsvc.replaceFaviconDataFromDataURL(firstFavicon.uri, createDataURLForFavicon(secondFavicon));
101
102 let deferSetAndFetchFavicon = Promise.defer();
103 iconsvc.setAndFetchFaviconForPage(
104 pageURI, firstFavicon.uri, true,
105 PlacesUtils.favicons.FAVICON_LOAD_NON_PRIVATE,
106 function test_replaceFaviconDataFromDataURL_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_replaceFaviconDataFromDataURL_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_replaceFaviconDataFromDataURL_replaceExisting() {
122 do_log_info("test replaceFaviconDataFromDataURL 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_replaceFaviconDataFromDataURL_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_replaceFaviconDataFromDataURL_replaceExisting_firstCallback() {
139 iconsvc.replaceFaviconDataFromDataURL(firstFavicon.uri, createDataURLForFavicon(secondFavicon));
140 checkFaviconDataForPage(
141 pageURI, secondFavicon.mimetype, secondFavicon.data,
142 function test_replaceFaviconDataFromDataURL_replaceExisting_secondCallback() {
143 firstFavicon.file.remove(false);
144 secondFavicon.file.remove(false);
145 deferSetAndFetchFavicon.resolve();
146 });
147 });
148 });
149 yield deferSetAndFetchFavicon.promise;
150
151 yield promiseClearHistory();
152 });
153
154 add_task(function test_replaceFaviconDataFromDataURL_unrelatedReplace() {
155 do_log_info("test replaceFaviconDataFromDataURL to not make unrelated changes");
156
157 let pageURI = uri("http://test4.bar/");
158 yield promiseAddVisits(pageURI);
159
160 let favicon = createFavicon("favicon6.png");
161 let unrelatedFavicon = createFavicon("favicon7.png");
162
163 iconsvc.replaceFaviconDataFromDataURL(unrelatedFavicon.uri, createDataURLForFavicon(unrelatedFavicon));
164
165 let deferSetAndFetchFavicon = Promise.defer();
166 iconsvc.setAndFetchFaviconForPage(
167 pageURI, favicon.uri, true,
168 PlacesUtils.favicons.FAVICON_LOAD_NON_PRIVATE,
169 function test_replaceFaviconDataFromDataURL_unrelatedReplace_check(aURI, aDataLen, aData, aMimeType) {
170 checkCallbackSucceeded(aMimeType, aData, favicon.mimetype, favicon.data);
171 checkFaviconDataForPage(
172 pageURI, favicon.mimetype, favicon.data,
173 function test_replaceFaviconDataFromDataURL_unrelatedReplace_callback() {
174 favicon.file.remove(false);
175 unrelatedFavicon.file.remove(false);
176 deferSetAndFetchFavicon.resolve();
177 });
178 });
179 yield deferSetAndFetchFavicon.promise;
180
181 yield promiseClearHistory();
182 });
183
184 add_task(function test_replaceFaviconDataFromDataURL_badInputs() {
185 do_log_info("test replaceFaviconDataFromDataURL to throw on bad inputs");
186
187 let favicon = createFavicon("favicon8.png");
188
189 let ex = null;
190 try {
191 iconsvc.replaceFaviconDataFromDataURL(favicon.uri, "");
192 } catch (e) {
193 ex = e;
194 } finally {
195 do_check_true(!!ex);
196 }
197
198 ex = null;
199 try {
200 iconsvc.replaceFaviconDataFromDataURL(null, createDataURLForFavicon(favicon));
201 } catch (e) {
202 ex = e;
203 } finally {
204 do_check_true(!!ex);
205 }
206
207 favicon.file.remove(false);
208
209 yield promiseClearHistory();
210 });
211
212 add_task(function test_replaceFaviconDataFromDataURL_twiceReplace() {
213 do_log_info("test replaceFaviconDataFromDataURL on multiple replacements");
214
215 let pageURI = uri("http://test5.bar/");
216 yield promiseAddVisits(pageURI);
217
218 let firstFavicon = createFavicon("favicon9.png");
219 let secondFavicon = createFavicon("favicon10.png");
220
221 iconsvc.replaceFaviconDataFromDataURL(firstFavicon.uri, createDataURLForFavicon(firstFavicon));
222 iconsvc.replaceFaviconDataFromDataURL(firstFavicon.uri, createDataURLForFavicon(secondFavicon));
223
224 let deferSetAndFetchFavicon = Promise.defer();
225 iconsvc.setAndFetchFaviconForPage(
226 pageURI, firstFavicon.uri, true,
227 PlacesUtils.favicons.FAVICON_LOAD_NON_PRIVATE,
228 function test_replaceFaviconDataFromDataURL_twiceReplace_check(aURI, aDataLen, aData, aMimeType) {
229 checkCallbackSucceeded(aMimeType, aData, secondFavicon.mimetype, secondFavicon.data);
230 checkFaviconDataForPage(
231 pageURI, secondFavicon.mimetype, secondFavicon.data,
232 function test_replaceFaviconDataFromDataURL_twiceReplace_callback() {
233 firstFavicon.file.remove(false);
234 secondFavicon.file.remove(false);
235 deferSetAndFetchFavicon.resolve();
236 });
237 });
238 yield deferSetAndFetchFavicon.promise;
239
240 yield promiseClearHistory();
241 });
242
243 add_task(function test_replaceFaviconDataFromDataURL_afterRegularAssign() {
244 do_log_info("test replaceFaviconDataFromDataURL after replaceFaviconData");
245
246 let pageURI = uri("http://test6.bar/");
247 yield promiseAddVisits(pageURI);
248
249 let firstFavicon = createFavicon("favicon11.png");
250 let secondFavicon = createFavicon("favicon12.png");
251
252 iconsvc.replaceFaviconData(
253 firstFavicon.uri, firstFavicon.data, firstFavicon.data.length,
254 firstFavicon.mimetype);
255 iconsvc.replaceFaviconDataFromDataURL(firstFavicon.uri, createDataURLForFavicon(secondFavicon));
256
257 let deferSetAndFetchFavicon = Promise.defer();
258 iconsvc.setAndFetchFaviconForPage(
259 pageURI, firstFavicon.uri, true,
260 PlacesUtils.favicons.FAVICON_LOAD_NON_PRIVATE,
261 function test_replaceFaviconDataFromDataURL_afterRegularAssign_check(aURI, aDataLen, aData, aMimeType) {
262 checkCallbackSucceeded(aMimeType, aData, secondFavicon.mimetype, secondFavicon.data);
263 checkFaviconDataForPage(
264 pageURI, secondFavicon.mimetype, secondFavicon.data,
265 function test_replaceFaviconDataFromDataURL_afterRegularAssign_callback() {
266 firstFavicon.file.remove(false);
267 secondFavicon.file.remove(false);
268 deferSetAndFetchFavicon.resolve();
269 });
270 });
271 yield deferSetAndFetchFavicon.promise;
272
273 yield promiseClearHistory();
274 });
275
276 add_task(function test_replaceFaviconDataFromDataURL_beforeRegularAssign() {
277 do_log_info("test replaceFaviconDataFromDataURL before replaceFaviconData");
278
279 let pageURI = uri("http://test7.bar/");
280 yield promiseAddVisits(pageURI);
281
282 let firstFavicon = createFavicon("favicon13.png");
283 let secondFavicon = createFavicon("favicon14.png");
284
285 iconsvc.replaceFaviconDataFromDataURL(firstFavicon.uri, createDataURLForFavicon(firstFavicon));
286 iconsvc.replaceFaviconData(
287 firstFavicon.uri, secondFavicon.data, secondFavicon.data.length,
288 secondFavicon.mimetype);
289
290 let deferSetAndFetchFavicon = Promise.defer();
291 iconsvc.setAndFetchFaviconForPage(
292 pageURI, firstFavicon.uri, true,
293 PlacesUtils.favicons.FAVICON_LOAD_NON_PRIVATE,
294 function test_replaceFaviconDataFromDataURL_beforeRegularAssign_check(aURI, aDataLen, aData, aMimeType) {
295 checkCallbackSucceeded(aMimeType, aData, secondFavicon.mimetype, secondFavicon.data);
296 checkFaviconDataForPage(
297 pageURI, secondFavicon.mimetype, secondFavicon.data,
298 function test_replaceFaviconDataFromDataURL_beforeRegularAssign_callback() {
299 firstFavicon.file.remove(false);
300 secondFavicon.file.remove(false);
301 deferSetAndFetchFavicon.resolve();
302 });
303 });
304 yield deferSetAndFetchFavicon.promise;
305
306 yield promiseClearHistory();
307 });
308
309 /* toBase64 copied from image/test/unit/test_encoder_png.js */
310
311 /* Convert data (an array of integers) to a Base64 string. */
312 const toBase64Table = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz' +
313 '0123456789+/';
314 const base64Pad = '=';
315 function toBase64(data) {
316 let result = '';
317 let length = data.length;
318 let i;
319 // Convert every three bytes to 4 ascii characters.
320 for (i = 0; i < (length - 2); i += 3) {
321 result += toBase64Table[data[i] >> 2];
322 result += toBase64Table[((data[i] & 0x03) << 4) + (data[i+1] >> 4)];
323 result += toBase64Table[((data[i+1] & 0x0f) << 2) + (data[i+2] >> 6)];
324 result += toBase64Table[data[i+2] & 0x3f];
325 }
326
327 // Convert the remaining 1 or 2 bytes, pad out to 4 characters.
328 if (length%3) {
329 i = length - (length%3);
330 result += toBase64Table[data[i] >> 2];
331 if ((length%3) == 2) {
332 result += toBase64Table[((data[i] & 0x03) << 4) + (data[i+1] >> 4)];
333 result += toBase64Table[(data[i+1] & 0x0f) << 2];
334 result += base64Pad;
335 } else {
336 result += toBase64Table[(data[i] & 0x03) << 4];
337 result += base64Pad + base64Pad;
338 }
339 }
340
341 return result;
342 }

mercurial