Bug 1448500: Add speculative request content policy type. r=bz, r=kmag
Adds a new TYPE_SPECULATIVE to nsIContentPolicy uses it as the type for
speculative connection channels from the IO service. I believe I've added it to
all the content policies in tree to make sure it behaves the same as TYPE_OTHER
used to.
The webextension test shows that the webextension proxy API sees speculative
lookups requested through the IO service.
MozReview-Commit-ID: DQ4Kq0xdUOD
--- a/dom/base/nsContentPolicyUtils.h
+++ b/dom/base/nsContentPolicyUtils.h
@@ -109,17 +109,16 @@ NS_CP_ContentTypeName(uint32_t contentTy
CASE_RETURN( TYPE_MEDIA );
CASE_RETURN( TYPE_WEBSOCKET );
CASE_RETURN( TYPE_CSP_REPORT );
CASE_RETURN( TYPE_XSLT );
CASE_RETURN( TYPE_BEACON );
CASE_RETURN( TYPE_FETCH );
CASE_RETURN( TYPE_IMAGESET );
CASE_RETURN( TYPE_WEB_MANIFEST );
- CASE_RETURN( TYPE_SAVEAS_DOWNLOAD );
CASE_RETURN( TYPE_INTERNAL_SCRIPT );
CASE_RETURN( TYPE_INTERNAL_WORKER );
CASE_RETURN( TYPE_INTERNAL_SHARED_WORKER );
CASE_RETURN( TYPE_INTERNAL_EMBED );
CASE_RETURN( TYPE_INTERNAL_OBJECT );
CASE_RETURN( TYPE_INTERNAL_FRAME );
CASE_RETURN( TYPE_INTERNAL_IFRAME );
CASE_RETURN( TYPE_INTERNAL_AUDIO );
@@ -130,16 +129,18 @@ NS_CP_ContentTypeName(uint32_t contentTy
CASE_RETURN( TYPE_INTERNAL_SERVICE_WORKER );
CASE_RETURN( TYPE_INTERNAL_SCRIPT_PRELOAD );
CASE_RETURN( TYPE_INTERNAL_IMAGE );
CASE_RETURN( TYPE_INTERNAL_IMAGE_PRELOAD );
CASE_RETURN( TYPE_INTERNAL_IMAGE_FAVICON );
CASE_RETURN( TYPE_INTERNAL_STYLESHEET );
CASE_RETURN( TYPE_INTERNAL_STYLESHEET_PRELOAD );
CASE_RETURN( TYPE_INTERNAL_WORKER_IMPORT_SCRIPTS );
+ CASE_RETURN( TYPE_SAVEAS_DOWNLOAD );
+ CASE_RETURN( TYPE_SPECULATIVE );
default:
return "<Unknown Type>";
}
}
#undef CASE_RETURN
/* Passes on parameters from its "caller"'s context. */
--- a/dom/base/nsIContentPolicy.idl
+++ b/dom/base/nsIContentPolicy.idl
@@ -176,21 +176,16 @@ interface nsIContentPolicy : nsISupports
const nsContentPolicyType TYPE_IMAGESET = 21;
/**
* Indicates a web manifest.
*/
const nsContentPolicyType TYPE_WEB_MANIFEST = 22;
/**
- * Indicates an save-as link download from the front-end code.
- */
- const nsContentPolicyType TYPE_SAVEAS_DOWNLOAD = 43;
-
- /**
* Indicates an internal constant for scripts loaded through script
* elements.
*
* This will be mapped to TYPE_SCRIPT before being passed to content policy
* implementations.
*/
const nsContentPolicyType TYPE_INTERNAL_SCRIPT = 23;
@@ -336,21 +331,32 @@ interface nsIContentPolicy : nsISupports
/**
* Indicates an importScripts() inside a worker script.
*
* This will be mapped to TYPE_SCRIPT before being passed to content policy
* implementations.
*/
const nsContentPolicyType TYPE_INTERNAL_WORKER_IMPORT_SCRIPTS = 42;
+ /**
+ * Indicates an save-as link download from the front-end code.
+ */
+ const nsContentPolicyType TYPE_SAVEAS_DOWNLOAD = 43;
+
+ /**
+ * Indicates a speculative connection.
+ */
+ const nsContentPolicyType TYPE_SPECULATIVE = 44;
+
/* When adding new content types, please update nsContentBlocker,
- * NS_CP_ContentTypeName, nsCSPContext, all nsIContentPolicy
- * implementations, the static_assert in dom/cache/DBSchema.cpp,
- * ChannelWrapper.webidl, ChannelWrapper.cpp, and other things that
- * are not listed here that are related to nsIContentPolicy. */
+ * NS_CP_ContentTypeName, nsCSPContext, CSP_ContentTypeToDirective,
+ * DoContentSecurityChecks, all nsIContentPolicy implementations, the
+ * static_assert in dom/cache/DBSchema.cpp, ChannelWrapper.webidl,
+ * ChannelWrapper.cpp, nsPermissionManager.cpp, and other things that are not
+ * listed here that are related to nsIContentPolicy. */
//////////////////////////////////////////////////////////////////////
/**
* Returned from shouldLoad or shouldProcess if the load or process request
* is rejected based on details of the request.
*/
const short REJECT_REQUEST = -1;
--- a/dom/cache/DBSchema.cpp
+++ b/dom/cache/DBSchema.cpp
@@ -306,17 +306,16 @@ static_assert(nsIContentPolicy::TYPE_INV
nsIContentPolicy::TYPE_MEDIA == 15 &&
nsIContentPolicy::TYPE_WEBSOCKET == 16 &&
nsIContentPolicy::TYPE_CSP_REPORT == 17 &&
nsIContentPolicy::TYPE_XSLT == 18 &&
nsIContentPolicy::TYPE_BEACON == 19 &&
nsIContentPolicy::TYPE_FETCH == 20 &&
nsIContentPolicy::TYPE_IMAGESET == 21 &&
nsIContentPolicy::TYPE_WEB_MANIFEST == 22 &&
- nsIContentPolicy::TYPE_SAVEAS_DOWNLOAD == 43 &&
nsIContentPolicy::TYPE_INTERNAL_SCRIPT == 23 &&
nsIContentPolicy::TYPE_INTERNAL_WORKER == 24 &&
nsIContentPolicy::TYPE_INTERNAL_SHARED_WORKER == 25 &&
nsIContentPolicy::TYPE_INTERNAL_EMBED == 26 &&
nsIContentPolicy::TYPE_INTERNAL_OBJECT == 27 &&
nsIContentPolicy::TYPE_INTERNAL_FRAME == 28 &&
nsIContentPolicy::TYPE_INTERNAL_IFRAME == 29 &&
nsIContentPolicy::TYPE_INTERNAL_AUDIO == 30 &&
@@ -326,17 +325,19 @@ static_assert(nsIContentPolicy::TYPE_INV
nsIContentPolicy::TYPE_INTERNAL_EVENTSOURCE == 34 &&
nsIContentPolicy::TYPE_INTERNAL_SERVICE_WORKER == 35 &&
nsIContentPolicy::TYPE_INTERNAL_SCRIPT_PRELOAD == 36 &&
nsIContentPolicy::TYPE_INTERNAL_IMAGE == 37 &&
nsIContentPolicy::TYPE_INTERNAL_IMAGE_PRELOAD == 38 &&
nsIContentPolicy::TYPE_INTERNAL_STYLESHEET == 39 &&
nsIContentPolicy::TYPE_INTERNAL_STYLESHEET_PRELOAD == 40 &&
nsIContentPolicy::TYPE_INTERNAL_IMAGE_FAVICON == 41 &&
- nsIContentPolicy::TYPE_INTERNAL_WORKER_IMPORT_SCRIPTS == 42,
+ nsIContentPolicy::TYPE_INTERNAL_WORKER_IMPORT_SCRIPTS == 42 &&
+ nsIContentPolicy::TYPE_SAVEAS_DOWNLOAD == 43 &&
+ nsIContentPolicy::TYPE_SPECULATIVE == 44,
"nsContentPolicyType values are as expected");
namespace {
typedef int32_t EntryId;
struct IdCount
{
--- a/dom/chrome-webidl/ChannelWrapper.webidl
+++ b/dom/chrome-webidl/ChannelWrapper.webidl
@@ -28,16 +28,17 @@ enum MozContentPolicyType {
"beacon",
"xml_dtd",
"font",
"media",
"websocket",
"csp_report",
"imageset",
"web_manifest",
+ "speculative",
"other"
};
/**
* A thin wrapper around nsIChannel and nsIHttpChannel that allows JS
* callers to access them without XPConnect overhead.
*/
[ChromeOnly, Exposed=System]
--- a/dom/fetch/InternalRequest.cpp
+++ b/dom/fetch/InternalRequest.cpp
@@ -328,16 +328,19 @@ InternalRequest::MapContentPolicyTypeToR
context = RequestContext::Imageset;
break;
case nsIContentPolicy::TYPE_WEB_MANIFEST:
context = RequestContext::Manifest;
break;
case nsIContentPolicy::TYPE_SAVEAS_DOWNLOAD:
context = RequestContext::Internal;
break;
+ case nsIContentPolicy::TYPE_SPECULATIVE:
+ context = RequestContext::Internal;
+ break;
default:
MOZ_ASSERT(false, "Unhandled nsContentPolicyType value");
break;
}
return context;
}
// static
--- a/dom/security/nsCSPUtils.cpp
+++ b/dom/security/nsCSPUtils.cpp
@@ -248,16 +248,17 @@ CSP_ContentTypeToDirective(nsContentPoli
case nsIContentPolicy::TYPE_OBJECT:
case nsIContentPolicy::TYPE_OBJECT_SUBREQUEST:
return nsIContentSecurityPolicy::OBJECT_SRC_DIRECTIVE;
case nsIContentPolicy::TYPE_XBL:
case nsIContentPolicy::TYPE_DTD:
case nsIContentPolicy::TYPE_OTHER:
+ case nsIContentPolicy::TYPE_SPECULATIVE:
return nsIContentSecurityPolicy::DEFAULT_SRC_DIRECTIVE;
// csp shold not block top level loads, e.g. in case
// of a redirect.
case nsIContentPolicy::TYPE_DOCUMENT:
// CSP can not block csp reports
case nsIContentPolicy::TYPE_CSP_REPORT:
return nsIContentSecurityPolicy::NO_DIRECTIVE;
--- a/dom/security/nsContentSecurityManager.cpp
+++ b/dom/security/nsContentSecurityManager.cpp
@@ -511,16 +511,21 @@ DoContentSecurityChecks(nsIChannel* aCha
break;
}
case nsIContentPolicy::TYPE_SAVEAS_DOWNLOAD: {
mimeTypeGuess = EmptyCString();
break;
}
+ case nsIContentPolicy::TYPE_SPECULATIVE: {
+ mimeTypeGuess = EmptyCString();
+ break;
+ }
+
default:
// nsIContentPolicy::TYPE_INVALID
MOZ_ASSERT(false, "can not perform security check without a valid contentType");
}
int16_t shouldLoad = nsIContentPolicy::ACCEPT;
rv = NS_CheckContentLoadPolicy(uri,
aLoadInfo,
--- a/dom/security/nsMixedContentBlocker.cpp
+++ b/dom/security/nsMixedContentBlocker.cpp
@@ -560,16 +560,17 @@ nsMixedContentBlocker::ShouldLoad(bool a
case TYPE_STYLESHEET:
case TYPE_SUBDOCUMENT:
case TYPE_PING:
case TYPE_WEB_MANIFEST:
case TYPE_XBL:
case TYPE_XMLHTTPREQUEST:
case TYPE_XSLT:
case TYPE_OTHER:
+ case TYPE_SPECULATIVE:
break;
// This content policy works as a whitelist.
default:
MOZ_ASSERT(false, "Mixed content of unknown type");
}
--- a/extensions/cookie/nsPermissionManager.cpp
+++ b/extensions/cookie/nsPermissionManager.cpp
@@ -123,16 +123,17 @@ static const char* kPreloadPermissions[]
"media",
"websocket",
"csp_report",
"xslt",
"beacon",
"fetch",
"image",
"manifest",
+ "speculative",
// This permission is preloaded to support properly blocking service worker
// interception when a user has disabled storage for a specific site. Once
// service worker interception moves to the parent process this should be
// removed. See bug 1428130.
"cookie"
};
--- a/extensions/permissions/nsContentBlocker.cpp
+++ b/extensions/permissions/nsContentBlocker.cpp
@@ -61,16 +61,18 @@ static const char *kTypeString[] = {
"", // TYPE_INTERNAL_SERVICE_WORKER
"", // TYPE_INTERNAL_SCRIPT_PRELOAD
"", // TYPE_INTERNAL_IMAGE
"", // TYPE_INTERNAL_IMAGE_PRELOAD
"", // TYPE_INTERNAL_STYLESHEET
"", // TYPE_INTERNAL_STYLESHEET_PRELOAD
"", // TYPE_INTERNAL_IMAGE_FAVICON
"", // TYPE_INTERNAL_WORKERS_IMPORT_SCRIPTS
+ "saveas_download",
+ "speculative",
};
#define NUMBER_OF_TYPES MOZ_ARRAY_LENGTH(kTypeString)
uint8_t nsContentBlocker::mBehaviorPref[NUMBER_OF_TYPES];
NS_IMPL_ISUPPORTS(nsContentBlocker,
nsIContentPolicy,
nsIObserver,
--- a/netwerk/base/nsIOService.cpp
+++ b/netwerk/base/nsIOService.cpp
@@ -1881,17 +1881,17 @@ nsIOService::SpeculativeConnectInternal(
// channel we create underneath - hence it's safe to use
// the systemPrincipal as the loadingPrincipal for this channel.
nsCOMPtr<nsIChannel> channel;
rv = NewChannelFromURI2(aURI,
nullptr, // aLoadingNode,
loadingPrincipal,
nullptr, //aTriggeringPrincipal,
nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_DATA_IS_NULL,
- nsIContentPolicy::TYPE_OTHER,
+ nsIContentPolicy::TYPE_SPECULATIVE,
getter_AddRefs(channel));
NS_ENSURE_SUCCESS(rv, rv);
if (aAnonymous) {
nsLoadFlags loadFlags = 0;
channel->GetLoadFlags(&loadFlags);
loadFlags |= nsIRequest::LOAD_ANONYMOUS;
channel->SetLoadFlags(loadFlags);
new file mode 100644
--- /dev/null
+++ b/toolkit/components/extensions/test/xpcshell/test_ext_proxy_speculative.js
@@ -0,0 +1,38 @@
+"use strict";
+
+ChromeUtils.import("resource://gre/modules/ExtensionUtils.jsm");
+
+const proxy = createHttpServer();
+
+add_task(async function test_speculative_connect() {
+ function background() {
+ // Handle the proxy request.
+ browser.proxy.onRequest.addListener(details => {
+ browser.test.log(`onRequest ${JSON.stringify(details)}`);
+ browser.test.assertEq(details.type, "speculative", "Should have seen a speculative proxy request.");
+ return [{type: "direct"}];
+ }, {urls: ["<all_urls>"]}, ["requestHeaders"]);
+ }
+
+ let handlingExt = ExtensionTestUtils.loadExtension({
+ manifest: {
+ permissions: [
+ "proxy",
+ "<all_urls>",
+ ],
+ },
+ background: `(${background})()`,
+ });
+
+ Services.prefs.setBoolPref("network.http.debug-observations", true);
+
+ await handlingExt.startup();
+
+ let notificationPromise = ExtensionUtils.promiseObserved("speculative-connect-request");
+
+ let uri = Services.io.newURI(`http://${proxy.identity.primaryHost}:${proxy.identity.primaryPort}`);
+ Services.io.speculativeConnect2(uri, Services.scriptSecurityManager.getSystemPrincipal(), null);
+ await notificationPromise;
+
+ await handlingExt.unload();
+});
--- a/toolkit/components/extensions/test/xpcshell/xpcshell-common.ini
+++ b/toolkit/components/extensions/test/xpcshell/xpcshell-common.ini
@@ -62,16 +62,17 @@ skip-if = (os == "win" && !debug) #Bug 1
skip-if = true # This test no longer tests what it is meant to test.
[test_ext_permission_xhr.js]
[test_ext_privacy.js]
[test_ext_privacy_disable.js]
[test_ext_privacy_update.js]
[test_ext_proxy_auth.js]
[test_ext_proxy_onauthrequired.js]
[test_ext_proxy_socks.js]
+[test_ext_proxy_speculative.js]
[test_ext_redirects.js]
[test_ext_runtime_connect_no_receiver.js]
[test_ext_runtime_getBrowserInfo.js]
[test_ext_runtime_getPlatformInfo.js]
[test_ext_runtime_id.js]
[test_ext_runtime_onInstalled_and_onStartup.js]
skip-if = true # bug 1315829
[test_ext_runtime_sendMessage.js]
--- a/toolkit/components/extensions/webrequest/ChannelWrapper.cpp
+++ b/toolkit/components/extensions/webrequest/ChannelWrapper.cpp
@@ -717,16 +717,18 @@ GetContentPolicyType(uint32_t aType)
case nsIContentPolicy::TYPE_WEBSOCKET:
return MozContentPolicyType::Websocket;
case nsIContentPolicy::TYPE_CSP_REPORT:
return MozContentPolicyType::Csp_report;
case nsIContentPolicy::TYPE_IMAGESET:
return MozContentPolicyType::Imageset;
case nsIContentPolicy::TYPE_WEB_MANIFEST:
return MozContentPolicyType::Web_manifest;
+ case nsIContentPolicy::TYPE_SPECULATIVE:
+ return MozContentPolicyType::Speculative;
default:
return MozContentPolicyType::Other;
}
}
MozContentPolicyType
ChannelWrapper::Type() const
{