зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1268962 - Add load / error event to prefetch link. r=bz
--HG-- extra : rebase_source : e62d8f12b0a4b4e047869ff005161df15cb6ab42
This commit is contained in:
Родитель
0936be8e70
Коммит
a4bc3b938a
|
@ -0,0 +1,90 @@
|
||||||
|
// Test server for bug 1268962
|
||||||
|
'use strict';
|
||||||
|
Components.utils.importGlobalProperties(["URLSearchParams"]);
|
||||||
|
const HTTPStatus = new Map([
|
||||||
|
[100, 'Continue'],
|
||||||
|
[101, 'Switching Protocol'],
|
||||||
|
[200, 'OK'],
|
||||||
|
[201, 'Created'],
|
||||||
|
[202, 'Accepted'],
|
||||||
|
[203, 'Non-Authoritative Information'],
|
||||||
|
[204, 'No Content'],
|
||||||
|
[205, 'Reset Content'],
|
||||||
|
[206, 'Partial Content'],
|
||||||
|
[300, 'Multiple Choice'],
|
||||||
|
[301, 'Moved Permanently'],
|
||||||
|
[302, 'Found'],
|
||||||
|
[303, 'See Other'],
|
||||||
|
[304, 'Not Modified'],
|
||||||
|
[305, 'Use Proxy'],
|
||||||
|
[306, 'unused'],
|
||||||
|
[307, 'Temporary Redirect'],
|
||||||
|
[308, 'Permanent Redirect'],
|
||||||
|
[400, 'Bad Request'],
|
||||||
|
[401, 'Unauthorized'],
|
||||||
|
[402, 'Payment Required'],
|
||||||
|
[403, 'Forbidden'],
|
||||||
|
[404, 'Not Found'],
|
||||||
|
[405, 'Method Not Allowed'],
|
||||||
|
[406, 'Not Acceptable'],
|
||||||
|
[407, 'Proxy Authentication Required'],
|
||||||
|
[408, 'Request Timeout'],
|
||||||
|
[409, 'Conflict'],
|
||||||
|
[410, 'Gone'],
|
||||||
|
[411, 'Length Required'],
|
||||||
|
[412, 'Precondition Failed'],
|
||||||
|
[413, 'Request Entity Too Large'],
|
||||||
|
[414, 'Request-URI Too Long'],
|
||||||
|
[415, 'Unsupported Media Type'],
|
||||||
|
[416, 'Requested Range Not Satisfiable'],
|
||||||
|
[417, 'Expectation Failed'],
|
||||||
|
[500, 'Internal Server Error'],
|
||||||
|
[501, 'Not Implemented'],
|
||||||
|
[502, 'Bad Gateway'],
|
||||||
|
[503, 'Service Unavailable'],
|
||||||
|
[504, 'Gateway Timeout'],
|
||||||
|
[505, 'HTTP Version Not Supported']
|
||||||
|
]);
|
||||||
|
|
||||||
|
const SAME_ORIGIN = 'http://mochi.test:8888/tests/dom/base/test/file_bug1268962.sjs';
|
||||||
|
const CROSS_ORIGIN = 'http://example.com/tests/dom/base/test/file_bug1268962.sjs';
|
||||||
|
|
||||||
|
function handleRequest(request, response) {
|
||||||
|
const queryMap = new URLSearchParams(request.queryString);
|
||||||
|
|
||||||
|
// Check redirection before everything else.
|
||||||
|
if (queryMap.has('redirect')) {
|
||||||
|
let redirect = queryMap.get('redirect');
|
||||||
|
let location;
|
||||||
|
if (redirect == 'sameorigin') {
|
||||||
|
location = SAME_ORIGIN;
|
||||||
|
} else if (redirect == 'crossorigin') {
|
||||||
|
location = CROSS_ORIGIN;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (location) {
|
||||||
|
// Use HTTP 302 redirection.
|
||||||
|
response.setStatusLine('1.1', 302, HTTPStatus.get(302));
|
||||||
|
|
||||||
|
// Forward query strings except the redirect option.
|
||||||
|
queryMap.delete('redirect');
|
||||||
|
response.setHeader('Location', location + '?' + queryMap.toString());
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (queryMap.has('statusCode')) {
|
||||||
|
let statusCode = parseInt(queryMap.get('statusCode'));
|
||||||
|
let statusText = HTTPStatus.get(statusCode);
|
||||||
|
response.setStatusLine('1.1', statusCode, statusText);
|
||||||
|
}
|
||||||
|
if (queryMap.has('cacheControl')) {
|
||||||
|
let cacheControl = queryMap.get('cacheControl');
|
||||||
|
response.setHeader('Cache-Control', cacheControl);
|
||||||
|
}
|
||||||
|
if (queryMap.has('allowOrigin')) {
|
||||||
|
let allowOrigin = queryMap.get('allowOrigin');
|
||||||
|
response.setHeader('Access-Control-Allow-Origin', allowOrigin);
|
||||||
|
}
|
||||||
|
}
|
|
@ -226,6 +226,7 @@ support-files =
|
||||||
file_change_policy_redirect.html
|
file_change_policy_redirect.html
|
||||||
file_bug1198095.js
|
file_bug1198095.js
|
||||||
file_bug1250148.sjs
|
file_bug1250148.sjs
|
||||||
|
file_bug1268962.sjs
|
||||||
mozbrowser_api_utils.js
|
mozbrowser_api_utils.js
|
||||||
websocket_helpers.js
|
websocket_helpers.js
|
||||||
websocket_tests.js
|
websocket_tests.js
|
||||||
|
@ -627,6 +628,7 @@ skip-if = buildapp == 'b2g'
|
||||||
[test_bug1250148.html]
|
[test_bug1250148.html]
|
||||||
[test_bug1259588.html]
|
[test_bug1259588.html]
|
||||||
[test_bug1263696.html]
|
[test_bug1263696.html]
|
||||||
|
[test_bug1268962.html]
|
||||||
[test_bug1274806.html]
|
[test_bug1274806.html]
|
||||||
[test_bug1281963.html]
|
[test_bug1281963.html]
|
||||||
[test_caretPositionFromPoint.html]
|
[test_caretPositionFromPoint.html]
|
||||||
|
|
|
@ -0,0 +1,105 @@
|
||||||
|
<!DOCTYPE HTML>
|
||||||
|
<html>
|
||||||
|
<!--
|
||||||
|
https://bugzilla.mozilla.org/show_bug.cgi?id=1268962
|
||||||
|
-->
|
||||||
|
<head>
|
||||||
|
<title>Test for Bug 1268962</title>
|
||||||
|
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||||
|
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1268962">Mozilla Bug 1268962</a>
|
||||||
|
<p id="display"></p>
|
||||||
|
<div id="content" style="display: none"></div>
|
||||||
|
<script class="testbody" type="text/javascript">
|
||||||
|
|
||||||
|
/** Test for Bug 1268962 **/
|
||||||
|
|
||||||
|
function testPrefetchEvent(url, crossorigin, expectLoad) {
|
||||||
|
return new Promise((resolve) => {
|
||||||
|
var link = document.createElement("LINK");
|
||||||
|
link.setAttribute("rel", "prefetch");
|
||||||
|
link.setAttribute("href", url);
|
||||||
|
if (crossorigin) {
|
||||||
|
link.setAttribute("crossorigin", "");
|
||||||
|
}
|
||||||
|
|
||||||
|
link.addEventListener("load", () => {
|
||||||
|
ok(expectLoad, "not expecting load event for " + url);
|
||||||
|
link.remove();
|
||||||
|
resolve();
|
||||||
|
});
|
||||||
|
link.addEventListener("error", () => {
|
||||||
|
ok(!expectLoad, "not expecting error event for " + url);
|
||||||
|
link.remove();
|
||||||
|
resolve();
|
||||||
|
});
|
||||||
|
document.head.appendChild(link);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function testCancelPrefetchNotCrash(url) {
|
||||||
|
var ios = SpecialPowers.Cc["@mozilla.org/network/io-service;1"].
|
||||||
|
getService(SpecialPowers.Ci.nsIIOService);
|
||||||
|
var prefetch = SpecialPowers.Cc["@mozilla.org/prefetch-service;1"].
|
||||||
|
getService(SpecialPowers.Ci.nsIPrefetchService);
|
||||||
|
|
||||||
|
var link = document.createElement("LINK");
|
||||||
|
link.setAttribute("rel", "prefetch");
|
||||||
|
link.setAttribute("href", url);
|
||||||
|
document.head.appendChild(link);
|
||||||
|
|
||||||
|
// Not actually verifying any value, just to ensure cancelPrefetch
|
||||||
|
// won't cause crash.
|
||||||
|
prefetch.cancelPrefetchURI(ios.newURI(url, null, null), link);
|
||||||
|
}
|
||||||
|
|
||||||
|
const SJS_PATH = window.location.pathname.replace(/[^/]+$/, "file_bug1268962.sjs");
|
||||||
|
const SAME_ORIGIN = "http://mochi.test:8888" + SJS_PATH;
|
||||||
|
const CROSS_ORIGIN = "http://example.com" + SJS_PATH;
|
||||||
|
|
||||||
|
SimpleTest.waitForExplicitFinish();
|
||||||
|
|
||||||
|
new Promise(resolve =>
|
||||||
|
SpecialPowers.pushPrefEnv({"set": [["network.prefetch-next.aggressive", true]]}, resolve))
|
||||||
|
|
||||||
|
// test same origin
|
||||||
|
.then(() => testPrefetchEvent(SAME_ORIGIN + "?statusCode=200&cacheControl=no-cache", false, false))
|
||||||
|
.then(() => testPrefetchEvent(SAME_ORIGIN + "?statusCode=404&cacheControl=no-cache", false, false))
|
||||||
|
.then(() => testPrefetchEvent(SAME_ORIGIN + "?statusCode=200&cacheControl=max-age%3D120", false, true))
|
||||||
|
.then(() => testPrefetchEvent(SAME_ORIGIN + "?statusCode=404&cacheControl=max-age%3D120", false, false))
|
||||||
|
|
||||||
|
// test cross origin without CORS
|
||||||
|
.then(() => testPrefetchEvent(CROSS_ORIGIN + "?statusCode=200&cacheControl=no-cache", false, true))
|
||||||
|
.then(() => testPrefetchEvent(CROSS_ORIGIN + "?statusCode=404&cacheControl=no-cache", false, true))
|
||||||
|
.then(() => testPrefetchEvent(CROSS_ORIGIN + "?statusCode=200&cacheControl=max-age%3D120", false, true))
|
||||||
|
.then(() => testPrefetchEvent(CROSS_ORIGIN + "?statusCode=404&cacheControl=max-age%3D120", false, true))
|
||||||
|
|
||||||
|
// test cross origin by redirection without CORS
|
||||||
|
.then(() => testPrefetchEvent(SAME_ORIGIN + "?redirect=crossorigin&statusCode=200&cacheControl=no-cache", false, true))
|
||||||
|
.then(() => testPrefetchEvent(SAME_ORIGIN + "?redirect=crossorigin&statusCode=404&cacheControl=no-cache", false, true))
|
||||||
|
.then(() => testPrefetchEvent(SAME_ORIGIN + "?redirect=crossorigin&statusCode=200&cacheControl=max-age%3D120", false, true))
|
||||||
|
.then(() => testPrefetchEvent(SAME_ORIGIN + "?redirect=crossorigin&statusCode=404&cacheControl=max-age%3D120", false, true))
|
||||||
|
|
||||||
|
// test cross origin with CORS request but no CORS response
|
||||||
|
.then(() => testPrefetchEvent(CROSS_ORIGIN + "?statusCode=200&cacheControl=no-cache", true, true))
|
||||||
|
.then(() => testPrefetchEvent(CROSS_ORIGIN + "?statusCode=404&cacheControl=no-cache", true, true))
|
||||||
|
.then(() => testPrefetchEvent(CROSS_ORIGIN + "?statusCode=200&cacheControl=max-age%3D120", true, true))
|
||||||
|
.then(() => testPrefetchEvent(CROSS_ORIGIN + "?statusCode=404&cacheControl=max-age%3D120", true, true))
|
||||||
|
|
||||||
|
// test cross origin with CORS request and CORS response
|
||||||
|
.then(() => testPrefetchEvent(CROSS_ORIGIN + "?statusCode=200&cacheControl=no-cache&allowOrigin=*", true, false))
|
||||||
|
.then(() => testPrefetchEvent(CROSS_ORIGIN + "?statusCode=404&cacheControl=no-cache&allowOrigin=*", true, false))
|
||||||
|
.then(() => testPrefetchEvent(CROSS_ORIGIN + "?statusCode=200&cacheControl=max-age%3D120&allowOrigin=*", true, true))
|
||||||
|
.then(() => testPrefetchEvent(CROSS_ORIGIN + "?statusCode=404&cacheControl=max-age%3D120&allowOrigin=*", true, false))
|
||||||
|
|
||||||
|
// test the crash issue: https://bugzilla.mozilla.org/show_bug.cgi?id=1294159
|
||||||
|
.then(() => testCancelPrefetchNotCrash(SAME_ORIGIN + "?statusCode=200&cacheControl=max-age%3D120"))
|
||||||
|
|
||||||
|
.catch((err) => ok(false, "promise rejected: " + err))
|
||||||
|
.then(() => SimpleTest.finish());
|
||||||
|
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -160,17 +160,6 @@
|
||||||
<script type="application/javascript;version=1.7" src="/tests/dom/base/test/referrer_helper.js"></script>
|
<script type="application/javascript;version=1.7" src="/tests/dom/base/test/referrer_helper.js"></script>
|
||||||
</head>
|
</head>
|
||||||
<body onload="tests.next();">
|
<body onload="tests.next();">
|
||||||
<script type="application/javascript;version=1.7">
|
|
||||||
/**
|
|
||||||
* Listen for notifications that pretching finishes.
|
|
||||||
* XXX Bug 1268962 - Fire load/error events on <link rel="prefetch">
|
|
||||||
* Because there's no onload/onerror event fired, we catch prefetch-load-completed
|
|
||||||
* to test
|
|
||||||
* Simply remove this after bug 1268962 is fixed
|
|
||||||
*/
|
|
||||||
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
|
|
||||||
SpecialPowers.Services.obs.addObserver(function() { tests.next(); }, "prefetch-load-completed", false);
|
|
||||||
</script>
|
|
||||||
<iframe id="testframe"></iframe>
|
<iframe id="testframe"></iframe>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
[allowed.https.html]
|
[allowed.https.html]
|
||||||
type: testharness
|
type: testharness
|
||||||
expected: TIMEOUT
|
|
||||||
[opt_in_method: http-csp\n origin: same-host-https\n source_scheme: https\n context_nesting: top-level\n redirection: keep-scheme-redirect\n subresource: link-prefetch-tag\n expectation: allowed]
|
[opt_in_method: http-csp\n origin: same-host-https\n source_scheme: https\n context_nesting: top-level\n redirection: keep-scheme-redirect\n subresource: link-prefetch-tag\n expectation: allowed]
|
||||||
expected: NOTRUN
|
expected: FAIL
|
||||||
|
bug: the test case uses "no-cache" HTTP header. send an error until we have conclusion at https://github.com/w3c/resource-hints/issues/62
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
[allowed.https.html]
|
[allowed.https.html]
|
||||||
type: testharness
|
type: testharness
|
||||||
expected: TIMEOUT
|
|
||||||
[opt_in_method: http-csp\n origin: same-host-https\n source_scheme: https\n context_nesting: top-level\n redirection: no-redirect\n subresource: link-prefetch-tag\n expectation: allowed]
|
[opt_in_method: http-csp\n origin: same-host-https\n source_scheme: https\n context_nesting: top-level\n redirection: no-redirect\n subresource: link-prefetch-tag\n expectation: allowed]
|
||||||
expected: NOTRUN
|
expected: FAIL
|
||||||
|
bug: the test case uses "no-cache" HTTP header. send an error until we have conclusion at https://github.com/w3c/resource-hints/issues/62
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
[allowed.https.html]
|
[allowed.https.html]
|
||||||
type: testharness
|
type: testharness
|
||||||
expected: TIMEOUT
|
|
||||||
[opt_in_method: meta-csp\n origin: same-host-https\n source_scheme: https\n context_nesting: top-level\n redirection: no-redirect\n subresource: link-prefetch-tag\n expectation: allowed]
|
[opt_in_method: meta-csp\n origin: same-host-https\n source_scheme: https\n context_nesting: top-level\n redirection: no-redirect\n subresource: link-prefetch-tag\n expectation: allowed]
|
||||||
expected: NOTRUN
|
expected: FAIL
|
||||||
|
bug: the test case uses "no-cache" HTTP header. send an error until we have conclusion at https://github.com/w3c/resource-hints/issues/62
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
[allowed.https.html]
|
[allowed.https.html]
|
||||||
type: testharness
|
type: testharness
|
||||||
expected: TIMEOUT
|
|
||||||
[opt_in_method: no-opt-in\n origin: same-host-https\n source_scheme: https\n context_nesting: top-level\n redirection: keep-scheme-redirect\n subresource: link-prefetch-tag\n expectation: allowed]
|
[opt_in_method: no-opt-in\n origin: same-host-https\n source_scheme: https\n context_nesting: top-level\n redirection: keep-scheme-redirect\n subresource: link-prefetch-tag\n expectation: allowed]
|
||||||
expected: NOTRUN
|
expected: FAIL
|
||||||
|
bug: the test case uses "no-cache" HTTP header. send an error until we have conclusion at https://github.com/w3c/resource-hints/issues/62
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
[allowed.https.html]
|
[allowed.https.html]
|
||||||
type: testharness
|
type: testharness
|
||||||
expected: TIMEOUT
|
|
||||||
[opt_in_method: no-opt-in\n origin: same-host-https\n source_scheme: https\n context_nesting: top-level\n redirection: no-redirect\n subresource: link-prefetch-tag\n expectation: allowed]
|
[opt_in_method: no-opt-in\n origin: same-host-https\n source_scheme: https\n context_nesting: top-level\n redirection: no-redirect\n subresource: link-prefetch-tag\n expectation: allowed]
|
||||||
expected: NOTRUN
|
expected: FAIL
|
||||||
|
bug: the test case uses "no-cache" HTTP header. send an error until we have conclusion at https://github.com/w3c/resource-hints/issues/62
|
||||||
|
|
|
@ -1,6 +0,0 @@
|
||||||
[opt-in-blocks.https.html]
|
|
||||||
type: testharness
|
|
||||||
expected: TIMEOUT
|
|
||||||
[opt_in_method: http-csp\n origin: cross-origin-http\n source_scheme: https\n context_nesting: top-level\n redirection: keep-scheme-redirect\n subresource: link-prefetch-tag\n expectation: blocked]
|
|
||||||
expected: NOTRUN
|
|
||||||
|
|
|
@ -1,6 +0,0 @@
|
||||||
[opt-in-blocks.https.html]
|
|
||||||
type: testharness
|
|
||||||
expected: TIMEOUT
|
|
||||||
[opt_in_method: http-csp\n origin: cross-origin-http\n source_scheme: https\n context_nesting: top-level\n redirection: no-redirect\n subresource: link-prefetch-tag\n expectation: blocked]
|
|
||||||
expected: NOTRUN
|
|
||||||
|
|
|
@ -1,6 +0,0 @@
|
||||||
[opt-in-blocks.https.html]
|
|
||||||
type: testharness
|
|
||||||
expected: TIMEOUT
|
|
||||||
[opt_in_method: http-csp\n origin: cross-origin-http\n source_scheme: https\n context_nesting: top-level\n redirection: swap-scheme-redirect\n subresource: link-prefetch-tag\n expectation: blocked]
|
|
||||||
expected: NOTRUN
|
|
||||||
|
|
|
@ -1,6 +0,0 @@
|
||||||
[opt-in-blocks.https.html]
|
|
||||||
type: testharness
|
|
||||||
expected: TIMEOUT
|
|
||||||
[opt_in_method: http-csp\n origin: same-host-http\n source_scheme: https\n context_nesting: top-level\n redirection: keep-scheme-redirect\n subresource: link-prefetch-tag\n expectation: blocked]
|
|
||||||
expected: NOTRUN
|
|
||||||
|
|
|
@ -1,6 +0,0 @@
|
||||||
[opt-in-blocks.https.html]
|
|
||||||
type: testharness
|
|
||||||
expected: TIMEOUT
|
|
||||||
[opt_in_method: http-csp\n origin: same-host-http\n source_scheme: https\n context_nesting: top-level\n redirection: no-redirect\n subresource: link-prefetch-tag\n expectation: blocked]
|
|
||||||
expected: NOTRUN
|
|
||||||
|
|
|
@ -1,6 +0,0 @@
|
||||||
[opt-in-blocks.https.html]
|
|
||||||
type: testharness
|
|
||||||
expected: TIMEOUT
|
|
||||||
[opt_in_method: http-csp\n origin: same-host-http\n source_scheme: https\n context_nesting: top-level\n redirection: swap-scheme-redirect\n subresource: link-prefetch-tag\n expectation: blocked]
|
|
||||||
expected: NOTRUN
|
|
||||||
|
|
|
@ -1,6 +0,0 @@
|
||||||
[opt-in-blocks.https.html]
|
|
||||||
type: testharness
|
|
||||||
expected: TIMEOUT
|
|
||||||
[opt_in_method: meta-csp\n origin: cross-origin-http\n source_scheme: https\n context_nesting: top-level\n redirection: no-redirect\n subresource: link-prefetch-tag\n expectation: blocked]
|
|
||||||
expected: NOTRUN
|
|
||||||
|
|
|
@ -1,6 +0,0 @@
|
||||||
[opt-in-blocks.https.html]
|
|
||||||
type: testharness
|
|
||||||
expected: TIMEOUT
|
|
||||||
[opt_in_method: meta-csp\n origin: same-host-http\n source_scheme: https\n context_nesting: top-level\n redirection: no-redirect\n subresource: link-prefetch-tag\n expectation: blocked]
|
|
||||||
expected: NOTRUN
|
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
[no-opt-in-allows.https.html]
|
[no-opt-in-allows.https.html]
|
||||||
type: testharness
|
type: testharness
|
||||||
expected: TIMEOUT
|
|
||||||
[opt_in_method: no-opt-in\n origin: cross-origin-http\n source_scheme: https\n context_nesting: top-level\n redirection: keep-scheme-redirect\n subresource: link-prefetch-tag\n expectation: allowed]
|
[opt_in_method: no-opt-in\n origin: cross-origin-http\n source_scheme: https\n context_nesting: top-level\n redirection: keep-scheme-redirect\n subresource: link-prefetch-tag\n expectation: allowed]
|
||||||
expected: NOTRUN
|
expected: FAIL
|
||||||
|
bug: haven't implement prefetch link as an optionally blockable item
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
[no-opt-in-allows.https.html]
|
[no-opt-in-allows.https.html]
|
||||||
type: testharness
|
type: testharness
|
||||||
expected: TIMEOUT
|
|
||||||
[opt_in_method: no-opt-in\n origin: cross-origin-http\n source_scheme: https\n context_nesting: top-level\n redirection: no-redirect\n subresource: link-prefetch-tag\n expectation: allowed]
|
[opt_in_method: no-opt-in\n origin: cross-origin-http\n source_scheme: https\n context_nesting: top-level\n redirection: no-redirect\n subresource: link-prefetch-tag\n expectation: allowed]
|
||||||
expected: NOTRUN
|
expected: FAIL
|
||||||
|
bug: haven't implement prefetch link as an optionally blockable item
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
[no-opt-in-allows.https.html]
|
[no-opt-in-allows.https.html]
|
||||||
type: testharness
|
type: testharness
|
||||||
expected: TIMEOUT
|
|
||||||
[opt_in_method: no-opt-in\n origin: cross-origin-http\n source_scheme: https\n context_nesting: top-level\n redirection: swap-scheme-redirect\n subresource: link-prefetch-tag\n expectation: allowed]
|
[opt_in_method: no-opt-in\n origin: cross-origin-http\n source_scheme: https\n context_nesting: top-level\n redirection: swap-scheme-redirect\n subresource: link-prefetch-tag\n expectation: allowed]
|
||||||
expected: NOTRUN
|
expected: FAIL
|
||||||
|
bug: haven't implement prefetch link as an optionally blockable item
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
[no-opt-in-allows.https.html]
|
[no-opt-in-allows.https.html]
|
||||||
type: testharness
|
type: testharness
|
||||||
expected: TIMEOUT
|
|
||||||
[opt_in_method: no-opt-in\n origin: same-host-http\n source_scheme: https\n context_nesting: top-level\n redirection: keep-scheme-redirect\n subresource: link-prefetch-tag\n expectation: allowed]
|
[opt_in_method: no-opt-in\n origin: same-host-http\n source_scheme: https\n context_nesting: top-level\n redirection: keep-scheme-redirect\n subresource: link-prefetch-tag\n expectation: allowed]
|
||||||
expected: NOTRUN
|
expected: FAIL
|
||||||
|
bug: haven't implement prefetch link as an optionally blockable item
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
[no-opt-in-allows.https.html]
|
[no-opt-in-allows.https.html]
|
||||||
type: testharness
|
type: testharness
|
||||||
expected: TIMEOUT
|
|
||||||
[opt_in_method: no-opt-in\n origin: same-host-http\n source_scheme: https\n context_nesting: top-level\n redirection: no-redirect\n subresource: link-prefetch-tag\n expectation: allowed]
|
[opt_in_method: no-opt-in\n origin: same-host-http\n source_scheme: https\n context_nesting: top-level\n redirection: no-redirect\n subresource: link-prefetch-tag\n expectation: allowed]
|
||||||
expected: NOTRUN
|
expected: FAIL
|
||||||
|
bug: haven't implement prefetch link as an optionally blockable item
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
[no-opt-in-allows.https.html]
|
[no-opt-in-allows.https.html]
|
||||||
type: testharness
|
type: testharness
|
||||||
expected: TIMEOUT
|
|
||||||
[opt_in_method: no-opt-in\n origin: same-host-http\n source_scheme: https\n context_nesting: top-level\n redirection: swap-scheme-redirect\n subresource: link-prefetch-tag\n expectation: allowed]
|
[opt_in_method: no-opt-in\n origin: same-host-http\n source_scheme: https\n context_nesting: top-level\n redirection: swap-scheme-redirect\n subresource: link-prefetch-tag\n expectation: allowed]
|
||||||
expected: NOTRUN
|
expected: FAIL
|
||||||
|
bug: haven't implement prefetch link as an optionally blockable item
|
||||||
|
|
|
@ -54,6 +54,7 @@ static LazyLogModule gPrefetchLog("nsPrefetch");
|
||||||
|
|
||||||
#define PREFETCH_PREF "network.prefetch-next"
|
#define PREFETCH_PREF "network.prefetch-next"
|
||||||
#define PARALLELISM_PREF "network.prefetch-next.parallelism"
|
#define PARALLELISM_PREF "network.prefetch-next.parallelism"
|
||||||
|
#define AGGRESSIVE_PREF "network.prefetch-next.aggressive"
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// helpers
|
// helpers
|
||||||
|
@ -81,6 +82,7 @@ nsPrefetchNode::nsPrefetchNode(nsPrefetchService *aService,
|
||||||
, mService(aService)
|
, mService(aService)
|
||||||
, mChannel(nullptr)
|
, mChannel(nullptr)
|
||||||
, mBytesRead(0)
|
, mBytesRead(0)
|
||||||
|
, mShouldFireLoadEvent(false)
|
||||||
{
|
{
|
||||||
nsCOMPtr<nsIWeakReference> source = do_GetWeakReference(aSource);
|
nsCOMPtr<nsIWeakReference> source = do_GetWeakReference(aSource);
|
||||||
mSources.AppendElement(source);
|
mSources.AppendElement(source);
|
||||||
|
@ -187,6 +189,25 @@ nsPrefetchNode::OnStartRequest(nsIRequest *aRequest,
|
||||||
{
|
{
|
||||||
nsresult rv;
|
nsresult rv;
|
||||||
|
|
||||||
|
nsCOMPtr<nsIHttpChannel> httpChannel =
|
||||||
|
do_QueryInterface(aRequest, &rv);
|
||||||
|
if (NS_FAILED(rv)) return rv;
|
||||||
|
|
||||||
|
// if the load is cross origin without CORS, or the CORS access is rejected,
|
||||||
|
// always fire load event to avoid leaking site information.
|
||||||
|
nsCOMPtr<nsILoadInfo> loadInfo = httpChannel->GetLoadInfo();
|
||||||
|
mShouldFireLoadEvent = loadInfo->GetTainting() == LoadTainting::Opaque ||
|
||||||
|
(loadInfo->GetTainting() == LoadTainting::CORS &&
|
||||||
|
(NS_FAILED(httpChannel->GetStatus(&rv)) ||
|
||||||
|
NS_FAILED(rv)));
|
||||||
|
|
||||||
|
// no need to prefetch http error page
|
||||||
|
bool requestSucceeded;
|
||||||
|
if (NS_FAILED(httpChannel->GetRequestSucceeded(&requestSucceeded)) ||
|
||||||
|
!requestSucceeded) {
|
||||||
|
return NS_BINDING_ABORTED;
|
||||||
|
}
|
||||||
|
|
||||||
nsCOMPtr<nsICacheInfoChannel> cacheInfoChannel =
|
nsCOMPtr<nsICacheInfoChannel> cacheInfoChannel =
|
||||||
do_QueryInterface(aRequest, &rv);
|
do_QueryInterface(aRequest, &rv);
|
||||||
if (NS_FAILED(rv)) return rv;
|
if (NS_FAILED(rv)) return rv;
|
||||||
|
@ -196,6 +217,8 @@ nsPrefetchNode::OnStartRequest(nsIRequest *aRequest,
|
||||||
if (NS_SUCCEEDED(cacheInfoChannel->IsFromCache(&fromCache)) &&
|
if (NS_SUCCEEDED(cacheInfoChannel->IsFromCache(&fromCache)) &&
|
||||||
fromCache) {
|
fromCache) {
|
||||||
LOG(("document is already in the cache; canceling prefetch\n"));
|
LOG(("document is already in the cache; canceling prefetch\n"));
|
||||||
|
// although it's canceled we still want to fire load event
|
||||||
|
mShouldFireLoadEvent = true;
|
||||||
return NS_BINDING_ABORTED;
|
return NS_BINDING_ABORTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -245,6 +268,7 @@ nsPrefetchNode::OnStopRequest(nsIRequest *aRequest,
|
||||||
}
|
}
|
||||||
|
|
||||||
mService->NotifyLoadCompleted(this);
|
mService->NotifyLoadCompleted(this);
|
||||||
|
mService->DispatchEvent(this, mShouldFireLoadEvent || NS_SUCCEEDED(aStatus));
|
||||||
mService->ProcessNextURI(this);
|
mService->ProcessNextURI(this);
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
@ -336,6 +360,7 @@ nsPrefetchService::nsPrefetchService()
|
||||||
, mStopCount(0)
|
, mStopCount(0)
|
||||||
, mHaveProcessed(false)
|
, mHaveProcessed(false)
|
||||||
, mDisabled(true)
|
, mDisabled(true)
|
||||||
|
, mAggressive(false)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -343,6 +368,7 @@ nsPrefetchService::~nsPrefetchService()
|
||||||
{
|
{
|
||||||
Preferences::RemoveObserver(this, PREFETCH_PREF);
|
Preferences::RemoveObserver(this, PREFETCH_PREF);
|
||||||
Preferences::RemoveObserver(this, PARALLELISM_PREF);
|
Preferences::RemoveObserver(this, PARALLELISM_PREF);
|
||||||
|
Preferences::RemoveObserver(this, AGGRESSIVE_PREF);
|
||||||
// cannot reach destructor if prefetch in progress (listener owns reference
|
// cannot reach destructor if prefetch in progress (listener owns reference
|
||||||
// to this service)
|
// to this service)
|
||||||
EmptyQueue();
|
EmptyQueue();
|
||||||
|
@ -363,6 +389,9 @@ nsPrefetchService::Init()
|
||||||
}
|
}
|
||||||
Preferences::AddWeakObserver(this, PARALLELISM_PREF);
|
Preferences::AddWeakObserver(this, PARALLELISM_PREF);
|
||||||
|
|
||||||
|
mAggressive = Preferences::GetBool(AGGRESSIVE_PREF, false);
|
||||||
|
Preferences::AddWeakObserver(this, AGGRESSIVE_PREF);
|
||||||
|
|
||||||
// Observe xpcom-shutdown event
|
// Observe xpcom-shutdown event
|
||||||
nsCOMPtr<nsIObserverService> observerService =
|
nsCOMPtr<nsIObserverService> observerService =
|
||||||
mozilla::services::GetObserverService();
|
mozilla::services::GetObserverService();
|
||||||
|
@ -408,11 +437,14 @@ nsPrefetchService::ProcessNextURI(nsPrefetchNode *aFinished)
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// if opening the channel fails, then just skip to the next uri
|
// if opening the channel fails (e.g. security check returns an error),
|
||||||
|
// send an error event and then just skip to the next uri
|
||||||
//
|
//
|
||||||
rv = node->OpenChannel();
|
rv = node->OpenChannel();
|
||||||
if (NS_SUCCEEDED(rv)) {
|
if (NS_SUCCEEDED(rv)) {
|
||||||
mCurrentNodes.AppendElement(node);
|
mCurrentNodes.AppendElement(node);
|
||||||
|
} else {
|
||||||
|
DispatchEvent(node, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
while (NS_FAILED(rv));
|
while (NS_FAILED(rv));
|
||||||
|
@ -442,6 +474,23 @@ nsPrefetchService::NotifyLoadCompleted(nsPrefetchNode *node)
|
||||||
"prefetch-load-completed", nullptr);
|
"prefetch-load-completed", nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
nsPrefetchService::DispatchEvent(nsPrefetchNode *node, bool aSuccess)
|
||||||
|
{
|
||||||
|
for (uint32_t i = 0; i < node->mSources.Length(); i++) {
|
||||||
|
nsCOMPtr<nsINode> domNode = do_QueryReferent(node->mSources.ElementAt(i));
|
||||||
|
if (domNode && domNode->IsInComposedDoc()) {
|
||||||
|
nsContentUtils::DispatchTrustedEvent(domNode->OwnerDoc(),
|
||||||
|
domNode,
|
||||||
|
aSuccess ?
|
||||||
|
NS_LITERAL_STRING("load") :
|
||||||
|
NS_LITERAL_STRING("error"),
|
||||||
|
/* aCanBubble = */ false,
|
||||||
|
/* aCancelable = */ false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// nsPrefetchService <private>
|
// nsPrefetchService <private>
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
@ -775,6 +824,11 @@ nsPrefetchService::OnStateChange(nsIWebProgress* aWebProgress,
|
||||||
uint32_t progressStateFlags,
|
uint32_t progressStateFlags,
|
||||||
nsresult aStatus)
|
nsresult aStatus)
|
||||||
{
|
{
|
||||||
|
if (mAggressive) {
|
||||||
|
LOG(("Document load state is ignored in aggressive mode"));
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
if (progressStateFlags & STATE_IS_DOCUMENT) {
|
if (progressStateFlags & STATE_IS_DOCUMENT) {
|
||||||
if (progressStateFlags & STATE_STOP)
|
if (progressStateFlags & STATE_STOP)
|
||||||
StartPrefetching();
|
StartPrefetching();
|
||||||
|
@ -862,6 +916,13 @@ nsPrefetchService::Observe(nsISupports *aSubject,
|
||||||
while (!mQueue.empty() && mCurrentNodes.Length() < static_cast<uint32_t>(mMaxParallelism)) {
|
while (!mQueue.empty() && mCurrentNodes.Length() < static_cast<uint32_t>(mMaxParallelism)) {
|
||||||
ProcessNextURI(nullptr);
|
ProcessNextURI(nullptr);
|
||||||
}
|
}
|
||||||
|
} else if (!strcmp(pref, AGGRESSIVE_PREF)) {
|
||||||
|
mAggressive = Preferences::GetBool(AGGRESSIVE_PREF, false);
|
||||||
|
// in aggressive mode, clear stop count and start prefetching immediately
|
||||||
|
if (mAggressive) {
|
||||||
|
mStopCount = 0;
|
||||||
|
StartPrefetching();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -45,6 +45,7 @@ public:
|
||||||
|
|
||||||
void NotifyLoadRequested(nsPrefetchNode *node);
|
void NotifyLoadRequested(nsPrefetchNode *node);
|
||||||
void NotifyLoadCompleted(nsPrefetchNode *node);
|
void NotifyLoadCompleted(nsPrefetchNode *node);
|
||||||
|
void DispatchEvent(nsPrefetchNode *node, bool aSuccess);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
~nsPrefetchService();
|
~nsPrefetchService();
|
||||||
|
@ -70,6 +71,12 @@ private:
|
||||||
// true if pending document loads have ever reached zero.
|
// true if pending document loads have ever reached zero.
|
||||||
int32_t mHaveProcessed;
|
int32_t mHaveProcessed;
|
||||||
bool mDisabled;
|
bool mDisabled;
|
||||||
|
|
||||||
|
// In usual case prefetch does not start until all normal loads are done.
|
||||||
|
// Aggressive mode ignores normal loads and just start prefetch ASAP.
|
||||||
|
// It's mainly for testing purpose and discoraged for normal use;
|
||||||
|
// see https://bugzilla.mozilla.org/show_bug.cgi?id=1281415 for details.
|
||||||
|
bool mAggressive;
|
||||||
};
|
};
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
@ -108,6 +115,7 @@ private:
|
||||||
nsCOMPtr<nsIChannel> mChannel;
|
nsCOMPtr<nsIChannel> mChannel;
|
||||||
nsCOMPtr<nsIChannel> mRedirectChannel;
|
nsCOMPtr<nsIChannel> mRedirectChannel;
|
||||||
int64_t mBytesRead;
|
int64_t mBytesRead;
|
||||||
|
bool mShouldFireLoadEvent;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // !nsPrefetchService_h__
|
#endif // !nsPrefetchService_h__
|
||||||
|
|
Загрузка…
Ссылка в новой задаче