/** * @fileoverview Test case for mixed-content in Web Platform Tests. * @author burnik@google.com (Kristijan Burnik) */ /** * MixedContentTestCase exercises all the tests for checking browser behavior * when resources regarded as mixed-content are requested. A single run covers * only a single scenario. * @param {object} scenario A JSON describing the test arrangement and * expectation(s). Refer to /mixed-content/spec.src.json for details. * @param {string} description The test scenario verbose description. * @param {SanityChecker} sanityChecker Instance of an object used to check the * running scenario. Useful in debug mode. See ./sanity-checker.js. * Run {@code ./tools/generate.py -h} for info on test generating modes. * @return {object} Object wrapping the start method used to run the test. */ function MixedContentTestCase(scenario, description, sanityChecker) { var httpProtocol = "http"; var httpsProtocol = "https"; var wsProtocol = "ws"; var wssProtocol = "wss"; var sameOriginHost = location.hostname; var crossOriginHost = "{{domains[www1]}}"; // These values can evaluate to either empty strings or a ":port" string. var httpPort = getNormalizedPort(parseInt("{{ports[http][0]}}", 10)); var httpsPort = getNormalizedPort(parseInt("{{ports[https][0]}}", 10)); var wsPort = getNormalizedPort(parseInt("{{ports[ws][0]}}", 10)); var wssPort = getNormalizedPort(parseInt("{{ports[wss][0]}}", 10)); var resourcePath = "/mixed-content/generic/expect.py"; var wsResourcePath = "/stash_responder"; // Map all endpoints to scenario for use in the test. var endpoint = { "same-origin": location.origin + resourcePath, "same-host-https": httpsProtocol + "://" + sameOriginHost + httpsPort + resourcePath, "same-host-http": httpProtocol + "://" + sameOriginHost + httpPort + resourcePath, "cross-origin-https": httpsProtocol + "://" + crossOriginHost + httpsPort + resourcePath, "cross-origin-http": httpProtocol + "://" + crossOriginHost + httpPort + resourcePath, "same-host-wss": wssProtocol + "://" + sameOriginHost + wssPort + wsResourcePath, "same-host-ws": wsProtocol + "://" + sameOriginHost + wsPort + wsResourcePath, "cross-origin-wss": wssProtocol + "://" + crossOriginHost + wssPort + wsResourcePath, "cross-origin-ws": wsProtocol + "://" + crossOriginHost + wsPort + wsResourcePath }; // Mapping all the resource requesting methods to the scenario. var resourceMap = { "a-tag": requestViaAnchor, "area-tag": requestViaArea, "fetch-request": requestViaFetch, "form-tag": requestViaForm, "iframe-tag": requestViaIframe, "img-tag": requestViaImage, "script-tag": requestViaScript, "worker-request": requestViaWorker, "xhr-request": requestViaXhr, "audio-tag": requestViaAudio, "video-tag": requestViaVideo, "picture-tag": requestViaPicture, "object-tag": requestViaObject, "link-css-tag": requestViaLinkStylesheet, "link-prefetch-tag": requestViaLinkPrefetch, "websocket-request": requestViaWebSocket }; sanityChecker.checkScenario(scenario, resourceMap); // Mapping all expected MIME types to the scenario. var contentType = { "a-tag": "text/html", "area-tag": "text/html", "fetch-request": "application/json", "form-tag": "text/html", "iframe-tag": "text/html", "img-tag": "image/png", "script-tag": "text/javascript", "worker-request": "application/javascript", "xhr-request": "application/json", "audio-tag": "audio/mpeg", "video-tag": "video/mp4", "picture-tag": "image/png", "object-tag": "text/html", "link-css-tag": "text/css", "link-prefetch-tag": "text/html", "websocket-request": "application/json" }; var mixed_content_test = async_test(description); function runTest() { sanityChecker.setFailTimeout(mixed_content_test); var key = guid(); var value = guid(); // We use the same path for both HTTP/S and WS/S stash requests. var stash_path = encodeURIComponent("/mixed-content"); var announceResourceRequestUrl = endpoint['same-origin'] + "?action=put&key=" + key + "&value=" + value + "&path=" + stash_path; var assertResourceRequestUrl = endpoint['same-origin'] + "?action=take&key=" + key + "&path=" + stash_path; var resourceRequestUrl = endpoint[scenario.origin] + "?redirection=" + scenario.redirection + "&action=purge&key=" + key + "&path=" + stash_path + "&content_type=" + contentType[scenario.subresource]; xhrRequest(announceResourceRequestUrl) .then(function(response) { // Send out the real resource request. // This should tear down the key if it's not blocked. return resourceMap[scenario.subresource](resourceRequestUrl); }) .then(function() { mixed_content_test.step(function() { assert_equals("allowed", scenario.expectation, "The triggered event should match '" + scenario.expectation + "'."); }, "Check if success event was triggered."); // Send request to check if the key has been torn down. return xhrRequest(assertResourceRequestUrl); }, function(error) { mixed_content_test.step(function() { assert_equals("blocked", scenario.expectation, "The triggered event should match '" + scenario.expectation + "'."); // TODO(kristijanburnik): param "error" can be an event or error. // Map assertion by resource. // e.g.: assert_equals(e.type, "error"); }, "Check if error event was triggered."); // When requestResource fails, we also check the key state. return xhrRequest(assertResourceRequestUrl); }) .then(function(response) { // Now check if the value has been torn down. If it's still there, // we have blocked the request to mixed-content. mixed_content_test.step(function() { assert_equals(response.status, scenario.expectation, "The resource request should be '" + scenario.expectation + "'."); }, "Check if request was sent."); mixed_content_test.done(); }); } // runTest return {start: runTest}; } // MixedContentTestCase