test_private_channel.js (4979B)
1 const { NetUtil } = ChromeUtils.importESModule( 2 "resource://gre/modules/NetUtil.sys.mjs" 3 ); 4 const { HttpServer } = ChromeUtils.importESModule( 5 "resource://testing-common/httpd.sys.mjs" 6 ); 7 8 const ReferrerInfo = Components.Constructor( 9 "@mozilla.org/referrer-info;1", 10 "nsIReferrerInfo", 11 "init" 12 ); 13 14 var server = new HttpServer(); 15 server.registerPathHandler("/image.png", imageHandler); 16 server.start(-1); 17 18 /* import-globals-from image_load_helpers.js */ 19 load("image_load_helpers.js"); 20 21 var gHits = 0; 22 23 var gIoService = Services.io; 24 var gPublicLoader = Cc["@mozilla.org/image/loader;1"].createInstance( 25 Ci.imgILoader 26 ); 27 var gPrivateLoader = Cc["@mozilla.org/image/loader;1"].createInstance( 28 Ci.imgILoader 29 ); 30 gPrivateLoader.QueryInterface(Ci.imgICache).respectPrivacyNotifications(); 31 32 var nonPrivateLoadContext = Cu.createLoadContext(); 33 var privateLoadContext = Cu.createPrivateLoadContext(); 34 35 function imageHandler(metadata, response) { 36 gHits++; 37 response.setHeader("Cache-Control", "max-age=10000", false); 38 response.setStatusLine(metadata.httpVersion, 200, "OK"); 39 response.setHeader("Content-Type", "image/png", false); 40 var body = atob( 41 "iVBORw0KGgoAAAANSUhEUgAAAAMAAAADCAIAAADZSiLoAAAAEUlEQVQImWP4z8AAQTAamQkAhpcI+DeMzFcAAAAASUVORK5CYII=" 42 ); 43 response.bodyOutputStream.write(body, body.length); 44 } 45 46 var requests = []; 47 var listeners = []; 48 49 var gImgPath = "http://localhost:" + server.identity.primaryPort + "/image.png"; 50 51 function setup_chan(path, isPrivate, callback) { 52 var uri = NetUtil.newURI(gImgPath); 53 var securityFlags = Ci.nsILoadInfo.SEC_ALLOW_CROSS_ORIGIN_SEC_CONTEXT_IS_NULL; 54 var principal = Services.scriptSecurityManager.createContentPrincipal(uri, { 55 privateBrowsingId: isPrivate ? 1 : 0, 56 }); 57 var chan = NetUtil.newChannel({ 58 uri, 59 loadingPrincipal: principal, 60 securityFlags, 61 contentPolicyType: Ci.nsIContentPolicy.TYPE_INTERNAL_IMAGE, 62 }); 63 chan.notificationCallbacks = isPrivate 64 ? privateLoadContext 65 : nonPrivateLoadContext; 66 var channelListener = new ChannelListener(); 67 chan.asyncOpen(channelListener); 68 69 var listener = new ImageListener(null, callback); 70 var outlistener = {}; 71 var loader = isPrivate ? gPrivateLoader : gPublicLoader; 72 var outer = Cc["@mozilla.org/image/tools;1"] 73 .getService(Ci.imgITools) 74 .createScriptedObserver(listener); 75 listeners.push(outer); 76 requests.push( 77 loader.loadImageWithChannelXPCOM(chan, outer, null, outlistener) 78 ); 79 channelListener.outputListener = outlistener.value; 80 listener.synchronous = false; 81 } 82 83 function loadImage(isPrivate, callback) { 84 var listener = new ImageListener(null, callback); 85 var outer = Cc["@mozilla.org/image/tools;1"] 86 .getService(Ci.imgITools) 87 .createScriptedObserver(listener); 88 var uri = gIoService.newURI(gImgPath); 89 var loadGroup = Cc["@mozilla.org/network/load-group;1"].createInstance( 90 Ci.nsILoadGroup 91 ); 92 loadGroup.notificationCallbacks = isPrivate 93 ? privateLoadContext 94 : nonPrivateLoadContext; 95 var loader = isPrivate ? gPrivateLoader : gPublicLoader; 96 var referrerInfo = new ReferrerInfo( 97 Ci.nsIReferrerInfo.NO_REFERRER_WHEN_DOWNGRADE, 98 true, 99 null 100 ); 101 requests.push( 102 loader.loadImageXPCOM( 103 uri, 104 null, 105 referrerInfo, 106 null, 107 loadGroup, 108 outer, 109 null, 110 0, 111 null 112 ) 113 ); 114 listener.synchronous = false; 115 } 116 117 function run_loadImage_tests() { 118 function observer() { 119 Services.obs.removeObserver(observer, "cacheservice:empty-cache"); 120 gHits = 0; 121 loadImage(false, function () { 122 loadImage(false, function () { 123 loadImage(true, function () { 124 loadImage(true, function () { 125 Assert.equal(gHits, 2); 126 server.stop(do_test_finished); 127 }); 128 }); 129 }); 130 }); 131 } 132 133 for (let loader of [gPublicLoader, gPrivateLoader]) { 134 loader.QueryInterface(Ci.imgICache).clearCache(); // no parameter=all 135 } 136 Services.obs.addObserver(observer, "cacheservice:empty-cache"); 137 let cs = Services.cache2; 138 cs.clear(); 139 } 140 141 function cleanup() { 142 for (var i = 0; i < requests.length; ++i) { 143 requests[i].cancelAndForgetObserver(0); 144 } 145 } 146 147 function run_test() { 148 registerCleanupFunction(cleanup); 149 150 do_test_pending(); 151 152 Services.prefs.setBoolPref("network.http.rcwn.enabled", false); 153 154 // We create a public channel that loads an image, then an identical 155 // one that should cause a cache read. We then create a private channel 156 // and load the same image, and do that a second time to ensure a cache 157 // read. In total, we should cause two separate http responses to occur, 158 // since the private channels shouldn't be able to use the public cache. 159 setup_chan("/image.png", false, function () { 160 setup_chan("/image.png", false, function () { 161 setup_chan("/image.png", true, function () { 162 setup_chan("/image.png", true, function () { 163 Assert.equal(gHits, 2); 164 run_loadImage_tests(); 165 }); 166 }); 167 }); 168 }); 169 }