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