// This file tests nsIContentSniffer, introduced in bug 324985 "use strict"; const { HttpServer } = ChromeUtils.importESModule( "resource://testing-common/httpd.sys.mjs" ); const unknownType = "application/x-unknown-content-type"; const sniffedType = "application/x-sniffed"; const snifferCID = Components.ID("{4c93d2db-8a56-48d7-b261-9cf2a8d998eb}"); const snifferContract = "@mozilla.org/network/unittest/contentsniffer;1"; const categoryName = "net-content-sniffers"; var sniffing_enabled = true; var isNosniff = false; /** * This object is both a factory and an nsIContentSniffer implementation (so, it * is de-facto a service) */ var sniffer = { QueryInterface: ChromeUtils.generateQI(["nsIFactory", "nsIContentSniffer"]), createInstance: function sniffer_ci(iid) { return this.QueryInterface(iid); }, getMIMETypeFromContent() { return sniffedType; }, }; var listener = { onStartRequest: function test_onStartR(request) { try { var chan = request.QueryInterface(Ci.nsIChannel); if (chan.contentType == unknownType) { do_throw("Type should not be unknown!"); } if (isNosniff) { if (chan.contentType == sniffedType) { do_throw("Sniffer called for X-Content-Type-Options:nosniff"); } } else if ( sniffing_enabled && this._iteration > 2 && chan.contentType != sniffedType ) { do_throw( "Expecting <" + sniffedType + "> but got <" + chan.contentType + "> for " + chan.URI.spec ); } else if (!sniffing_enabled && chan.contentType == sniffedType) { do_throw( "Sniffing not enabled but sniffer called for " + chan.URI.spec ); } } catch (e) { do_throw("Unexpected exception: " + e); } throw Components.Exception("", Cr.NS_ERROR_ABORT); }, onDataAvailable: function test_ODA() { throw Components.Exception("", Cr.NS_ERROR_UNEXPECTED); }, onStopRequest: function test_onStopR() { run_test_iteration(this._iteration); do_test_finished(); }, _iteration: 1, }; function makeChan(url) { var chan = NetUtil.newChannel({ uri: url, loadUsingSystemPrincipal: true }); if (sniffing_enabled) { chan.loadFlags |= Ci.nsIChannel.LOAD_CALL_CONTENT_SNIFFERS; } return chan; } var httpserv = null; var urls = null; function run_test() { httpserv = new HttpServer(); httpserv.registerPathHandler("/nosniff", nosniffHandler); httpserv.start(-1); urls = [ // NOTE: First URL here runs without our content sniffer "data:" + unknownType + ", Some text", "data:" + unknownType + ", Text", // Make sure sniffing works even if we // used the unknown content sniffer too "data:text/plain, Some more text", "http://localhost:" + httpserv.identity.primaryPort, "http://localhost:" + httpserv.identity.primaryPort + "/nosniff", ]; Components.manager.nsIComponentRegistrar.registerFactory( snifferCID, "Unit test content sniffer", snifferContract, sniffer ); run_test_iteration(1); } function nosniffHandler(request, response) { response.setHeader("X-Content-Type-Options", "nosniff"); } function run_test_iteration(index) { if (index > urls.length) { if (sniffing_enabled) { sniffing_enabled = false; index = listener._iteration = 1; } else { do_test_pending(); httpserv.stop(do_test_finished); return; // we're done } } if (sniffing_enabled && index == 2) { // Register our sniffer only here // This also makes sure that dynamic registration is working var catMan = Services.catMan; catMan.nsICategoryManager.addCategoryEntry( categoryName, "unit test", snifferContract, false, true ); } else if (sniffing_enabled && index == 5) { isNosniff = true; } var chan = makeChan(urls[index - 1]); listener._iteration++; chan.asyncOpen(listener); do_test_pending(); }