summaryrefslogtreecommitdiffstats
path: root/netwerk/protocol/http/EarlyHintPreconnect.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'netwerk/protocol/http/EarlyHintPreconnect.cpp')
-rw-r--r--netwerk/protocol/http/EarlyHintPreconnect.cpp106
1 files changed, 106 insertions, 0 deletions
diff --git a/netwerk/protocol/http/EarlyHintPreconnect.cpp b/netwerk/protocol/http/EarlyHintPreconnect.cpp
new file mode 100644
index 0000000000..4282ae554e
--- /dev/null
+++ b/netwerk/protocol/http/EarlyHintPreconnect.cpp
@@ -0,0 +1,106 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "EarlyHintPreconnect.h"
+
+#include "mozilla/CORSMode.h"
+#include "mozilla/dom/Element.h"
+#include "mozilla/StaticPrefs_network.h"
+#include "nsIOService.h"
+#include "nsIURI.h"
+#include "SpeculativeTransaction.h"
+
+namespace mozilla::net {
+
+namespace {
+class EarlyHintsPreConnectOverride : public nsIInterfaceRequestor,
+ public nsISpeculativeConnectionOverrider {
+ public:
+ NS_DECL_THREADSAFE_ISUPPORTS
+ NS_DECL_NSISPECULATIVECONNECTIONOVERRIDER
+ NS_DECL_NSIINTERFACEREQUESTOR
+
+ explicit EarlyHintsPreConnectOverride(uint32_t aConnectionLimit)
+ : mConnectionLimit(aConnectionLimit) {}
+
+ private:
+ virtual ~EarlyHintsPreConnectOverride() = default;
+
+ // Only set once on main thread and can be read on multiple threads.
+ const uint32_t mConnectionLimit;
+};
+
+NS_IMPL_ISUPPORTS(EarlyHintsPreConnectOverride, nsIInterfaceRequestor,
+ nsISpeculativeConnectionOverrider)
+
+NS_IMETHODIMP
+EarlyHintsPreConnectOverride::GetInterface(const nsIID& iid, void** result) {
+ if (NS_SUCCEEDED(QueryInterface(iid, result)) && *result) {
+ return NS_OK;
+ }
+
+ return NS_ERROR_NO_INTERFACE;
+}
+
+NS_IMETHODIMP
+EarlyHintsPreConnectOverride::GetIgnoreIdle(bool* ignoreIdle) {
+ *ignoreIdle = true;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+EarlyHintsPreConnectOverride::GetParallelSpeculativeConnectLimit(
+ uint32_t* parallelSpeculativeConnectLimit) {
+ *parallelSpeculativeConnectLimit = mConnectionLimit;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+EarlyHintsPreConnectOverride::GetIsFromPredictor(bool* isFromPredictor) {
+ *isFromPredictor = false;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+EarlyHintsPreConnectOverride::GetAllow1918(bool* allow) {
+ *allow = false;
+ return NS_OK;
+}
+
+} // namespace
+
+void EarlyHintPreconnect::MaybePreconnect(
+ const LinkHeader& aHeader, nsIURI* aBaseURI,
+ OriginAttributes&& aOriginAttributes) {
+ if (!StaticPrefs::network_early_hints_preconnect_enabled()) {
+ return;
+ }
+
+ if (!gIOService) {
+ return;
+ }
+
+ nsCOMPtr<nsIURI> uri;
+ if (NS_FAILED(aHeader.NewResolveHref(getter_AddRefs(uri), aBaseURI))) {
+ return;
+ }
+
+ // only preconnect secure context urls
+ if (!uri->SchemeIs("https")) {
+ return;
+ }
+
+ uint32_t maxPreconnectCount =
+ StaticPrefs::network_early_hints_preconnect_max_connections();
+ nsCOMPtr<nsIInterfaceRequestor> callbacks =
+ new EarlyHintsPreConnectOverride(maxPreconnectCount);
+ // Note that the http connection manager will limit the number of
+ // connections we can make, so it should be fine we don't check duplicate
+ // preconnect attempts here.
+ CORSMode corsMode = dom::Element::StringToCORSMode(aHeader.mCrossOrigin);
+ gIOService->SpeculativeConnectWithOriginAttributesNative(
+ uri, std::move(aOriginAttributes), callbacks, corsMode == CORS_ANONYMOUS);
+}
+
+} // namespace mozilla::net