test_content_sniffer.js (4029B)
1 // This file tests nsIContentSniffer, introduced in bug 324985 2 3 "use strict"; 4 5 const { HttpServer } = ChromeUtils.importESModule( 6 "resource://testing-common/httpd.sys.mjs" 7 ); 8 9 const unknownType = "application/x-unknown-content-type"; 10 const sniffedType = "application/x-sniffed"; 11 12 const snifferCID = Components.ID("{4c93d2db-8a56-48d7-b261-9cf2a8d998eb}"); 13 const snifferContract = "@mozilla.org/network/unittest/contentsniffer;1"; 14 const categoryName = "net-content-sniffers"; 15 16 var sniffing_enabled = true; 17 18 var isNosniff = false; 19 20 /** 21 * This object is both a factory and an nsIContentSniffer implementation (so, it 22 * is de-facto a service) 23 */ 24 var sniffer = { 25 QueryInterface: ChromeUtils.generateQI(["nsIFactory", "nsIContentSniffer"]), 26 createInstance: function sniffer_ci(iid) { 27 return this.QueryInterface(iid); 28 }, 29 30 getMIMETypeFromContent() { 31 return sniffedType; 32 }, 33 }; 34 35 var listener = { 36 onStartRequest: function test_onStartR(request) { 37 try { 38 var chan = request.QueryInterface(Ci.nsIChannel); 39 if (chan.contentType == unknownType) { 40 do_throw("Type should not be unknown!"); 41 } 42 if (isNosniff) { 43 if (chan.contentType == sniffedType) { 44 do_throw("Sniffer called for X-Content-Type-Options:nosniff"); 45 } 46 } else if ( 47 sniffing_enabled && 48 this._iteration > 2 && 49 chan.contentType != sniffedType 50 ) { 51 do_throw( 52 "Expecting <" + 53 sniffedType + 54 "> but got <" + 55 chan.contentType + 56 "> for " + 57 chan.URI.spec 58 ); 59 } else if (!sniffing_enabled && chan.contentType == sniffedType) { 60 do_throw( 61 "Sniffing not enabled but sniffer called for " + chan.URI.spec 62 ); 63 } 64 } catch (e) { 65 do_throw("Unexpected exception: " + e); 66 } 67 68 throw Components.Exception("", Cr.NS_ERROR_ABORT); 69 }, 70 71 onDataAvailable: function test_ODA() { 72 throw Components.Exception("", Cr.NS_ERROR_UNEXPECTED); 73 }, 74 75 onStopRequest: function test_onStopR() { 76 run_test_iteration(this._iteration); 77 do_test_finished(); 78 }, 79 80 _iteration: 1, 81 }; 82 83 function makeChan(url) { 84 var chan = NetUtil.newChannel({ uri: url, loadUsingSystemPrincipal: true }); 85 if (sniffing_enabled) { 86 chan.loadFlags |= Ci.nsIChannel.LOAD_CALL_CONTENT_SNIFFERS; 87 } 88 89 return chan; 90 } 91 92 var httpserv = null; 93 var urls = null; 94 95 function run_test() { 96 httpserv = new HttpServer(); 97 httpserv.registerPathHandler("/nosniff", nosniffHandler); 98 httpserv.start(-1); 99 100 urls = [ 101 // NOTE: First URL here runs without our content sniffer 102 "data:" + unknownType + ", Some text", 103 "data:" + unknownType + ", Text", // Make sure sniffing works even if we 104 // used the unknown content sniffer too 105 "data:text/plain, Some more text", 106 "http://localhost:" + httpserv.identity.primaryPort, 107 "http://localhost:" + httpserv.identity.primaryPort + "/nosniff", 108 ]; 109 110 Components.manager.nsIComponentRegistrar.registerFactory( 111 snifferCID, 112 "Unit test content sniffer", 113 snifferContract, 114 sniffer 115 ); 116 117 run_test_iteration(1); 118 } 119 120 function nosniffHandler(request, response) { 121 response.setHeader("X-Content-Type-Options", "nosniff"); 122 } 123 124 function run_test_iteration(index) { 125 if (index > urls.length) { 126 if (sniffing_enabled) { 127 sniffing_enabled = false; 128 index = listener._iteration = 1; 129 } else { 130 do_test_pending(); 131 httpserv.stop(do_test_finished); 132 return; // we're done 133 } 134 } 135 136 if (sniffing_enabled && index == 2) { 137 // Register our sniffer only here 138 // This also makes sure that dynamic registration is working 139 var catMan = Services.catMan; 140 catMan.nsICategoryManager.addCategoryEntry( 141 categoryName, 142 "unit test", 143 snifferContract, 144 false, 145 true 146 ); 147 } else if (sniffing_enabled && index == 5) { 148 isNosniff = true; 149 } 150 151 var chan = makeChan(urls[index - 1]); 152 153 listener._iteration++; 154 chan.asyncOpen(listener); 155 156 do_test_pending(); 157 }