|
1 const Cc = Components.classes; |
|
2 const Ci = Components.interfaces; |
|
3 const Cr = Components.results; |
|
4 const Cu = Components.utils; |
|
5 |
|
6 Cu.import("resource://gre/modules/Services.jsm"); |
|
7 Cu.import("resource://testing-common/httpd.js"); |
|
8 |
|
9 var server = new HttpServer(); |
|
10 server.registerPathHandler('/image.png', imageHandler); |
|
11 server.start(-1); |
|
12 |
|
13 load('image_load_helpers.js'); |
|
14 |
|
15 var gHits = 0; |
|
16 |
|
17 var gIoService = Cc["@mozilla.org/network/io-service;1"].getService(Ci.nsIIOService); |
|
18 var gPublicLoader = Cc["@mozilla.org/image/loader;1"].createInstance(Ci.imgILoader); |
|
19 var gPrivateLoader = Cc["@mozilla.org/image/loader;1"].createInstance(Ci.imgILoader); |
|
20 gPrivateLoader.QueryInterface(Ci.imgICache).respectPrivacyNotifications(); |
|
21 |
|
22 function imageHandler(metadata, response) { |
|
23 gHits++; |
|
24 response.setHeader("Cache-Control", "max-age=10000", false); |
|
25 response.setStatusLine(metadata.httpVersion, 200, "OK"); |
|
26 response.setHeader("Content-Type", "image/png", false); |
|
27 var body = "iVBORw0KGgoAAAANSUhEUgAAAAMAAAADCAIAAADZSiLoAAAAEUlEQVQImWP4z8AAQTAamQkAhpcI+DeMzFcAAAAASUVORK5CYII="; |
|
28 response.bodyOutputStream.write(body, body.length); |
|
29 } |
|
30 |
|
31 var requests = []; |
|
32 var listeners = []; |
|
33 |
|
34 function NotificationCallbacks(isPrivate) { |
|
35 this.usePrivateBrowsing = isPrivate; |
|
36 } |
|
37 |
|
38 NotificationCallbacks.prototype = { |
|
39 QueryInterface: function (iid) { |
|
40 if (iid.equals(Ci.nsISupports) || |
|
41 iid.equals(Ci.nsILoadContext)) |
|
42 return this; |
|
43 throw Cr.NS_ERROR_NO_INTERFACE; |
|
44 }, |
|
45 getInterface: function(iid) { |
|
46 if (iid.equals(Ci.nsILoadContext)) |
|
47 return this; |
|
48 throw Cr.NS_ERROR_NO_INTERFACE; |
|
49 } |
|
50 }; |
|
51 |
|
52 var gImgPath = 'http://localhost:' + server.identity.primaryPort + '/image.png'; |
|
53 |
|
54 function setup_chan(path, isPrivate, callback) { |
|
55 var uri = gIoService.newURI(gImgPath, null, null); |
|
56 var chan = gIoService.newChannelFromURI(uri); |
|
57 chan.notificationCallbacks = new NotificationCallbacks(isPrivate); |
|
58 var channelListener = new ChannelListener(); |
|
59 chan.asyncOpen(channelListener, null); |
|
60 |
|
61 var listener = new ImageListener(null, callback); |
|
62 var outlistener = {}; |
|
63 var loader = isPrivate ? gPrivateLoader : gPublicLoader; |
|
64 var outer = Cc["@mozilla.org/image/tools;1"].getService(Ci.imgITools) |
|
65 .createScriptedObserver(listener); |
|
66 listeners.push(outer); |
|
67 requests.push(loader.loadImageWithChannelXPCOM(chan, outer, null, outlistener)); |
|
68 channelListener.outputListener = outlistener.value; |
|
69 listener.synchronous = false; |
|
70 } |
|
71 |
|
72 function loadImage(isPrivate, callback) { |
|
73 var listener = new ImageListener(null, callback); |
|
74 var outer = Cc["@mozilla.org/image/tools;1"].getService(Ci.imgITools) |
|
75 .createScriptedObserver(listener); |
|
76 var uri = gIoService.newURI(gImgPath, null, null); |
|
77 var loadGroup = Cc["@mozilla.org/network/load-group;1"].createInstance(Ci.nsILoadGroup); |
|
78 loadGroup.notificationCallbacks = new NotificationCallbacks(isPrivate); |
|
79 var loader = isPrivate ? gPrivateLoader : gPublicLoader; |
|
80 requests.push(loader.loadImageXPCOM(uri, null, null, null, loadGroup, outer, null, 0, null, null)); |
|
81 listener.synchronous = false; |
|
82 } |
|
83 |
|
84 function run_loadImage_tests() { |
|
85 function observer() { |
|
86 Services.obs.removeObserver(observer, "cacheservice:empty-cache"); |
|
87 gHits = 0; |
|
88 loadImage(false, function() { |
|
89 loadImage(false, function() { |
|
90 loadImage(true, function() { |
|
91 loadImage(true, function() { |
|
92 do_check_eq(gHits, 2); |
|
93 server.stop(do_test_finished); |
|
94 }); |
|
95 }); |
|
96 }); |
|
97 }); |
|
98 } |
|
99 |
|
100 Services.obs.addObserver(observer, "cacheservice:empty-cache", false); |
|
101 let cs = Cc["@mozilla.org/netwerk/cache-storage-service;1"] |
|
102 .getService(Ci.nsICacheStorageService); |
|
103 cs.clear(); |
|
104 } |
|
105 |
|
106 function cleanup() |
|
107 { |
|
108 for (var i = 0; i < requests.length; ++i) { |
|
109 requests[i].cancelAndForgetObserver(0); |
|
110 } |
|
111 } |
|
112 |
|
113 function run_test() { |
|
114 do_register_cleanup(cleanup); |
|
115 |
|
116 do_test_pending(); |
|
117 |
|
118 // We create a public channel that loads an image, then an identical |
|
119 // one that should cause a cache read. We then create a private channel |
|
120 // and load the same image, and do that a second time to ensure a cache |
|
121 // read. In total, we should cause two separate http responses to occur, |
|
122 // since the private channels shouldn't be able to use the public cache. |
|
123 setup_chan('/image.png', false, function() { |
|
124 setup_chan('/image.png', false, function() { |
|
125 setup_chan('/image.png', true, function() { |
|
126 setup_chan('/image.png', true, function() { |
|
127 do_check_eq(gHits, 2); |
|
128 run_loadImage_tests(); |
|
129 }); |
|
130 }); |
|
131 }); |
|
132 }); |
|
133 } |