EarlyHintPreconnect.cpp (2893B)
1 /* This Source Code Form is subject to the terms of the Mozilla Public 2 * License, v. 2.0. If a copy of the MPL was not distributed with this 3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 5 #include "EarlyHintPreconnect.h" 6 7 #include "mozilla/CORSMode.h" 8 #include "mozilla/dom/Element.h" 9 #include "mozilla/StaticPrefs_network.h" 10 #include "nsIOService.h" 11 #include "nsIURI.h" 12 #include "SpeculativeTransaction.h" 13 14 namespace mozilla::net { 15 16 namespace { 17 class EarlyHintsPreConnectOverride : public nsIInterfaceRequestor, 18 public nsISpeculativeConnectionOverrider { 19 public: 20 NS_DECL_THREADSAFE_ISUPPORTS 21 NS_DECL_NSISPECULATIVECONNECTIONOVERRIDER 22 NS_DECL_NSIINTERFACEREQUESTOR 23 24 explicit EarlyHintsPreConnectOverride(uint32_t aConnectionLimit) 25 : mConnectionLimit(aConnectionLimit) {} 26 27 private: 28 virtual ~EarlyHintsPreConnectOverride() = default; 29 30 // Only set once on main thread and can be read on multiple threads. 31 const uint32_t mConnectionLimit; 32 }; 33 34 NS_IMPL_ISUPPORTS(EarlyHintsPreConnectOverride, nsIInterfaceRequestor, 35 nsISpeculativeConnectionOverrider) 36 37 NS_IMETHODIMP 38 EarlyHintsPreConnectOverride::GetInterface(const nsIID& iid, void** result) { 39 if (NS_SUCCEEDED(QueryInterface(iid, result)) && *result) { 40 return NS_OK; 41 } 42 43 return NS_ERROR_NO_INTERFACE; 44 } 45 46 NS_IMETHODIMP 47 EarlyHintsPreConnectOverride::GetIgnoreIdle(bool* ignoreIdle) { 48 *ignoreIdle = true; 49 return NS_OK; 50 } 51 52 NS_IMETHODIMP 53 EarlyHintsPreConnectOverride::GetParallelSpeculativeConnectLimit( 54 uint32_t* parallelSpeculativeConnectLimit) { 55 *parallelSpeculativeConnectLimit = mConnectionLimit; 56 return NS_OK; 57 } 58 59 NS_IMETHODIMP 60 EarlyHintsPreConnectOverride::GetAllow1918(bool* allow) { 61 *allow = false; 62 return NS_OK; 63 } 64 65 } // namespace 66 67 void EarlyHintPreconnect::MaybePreconnect( 68 const LinkHeader& aHeader, nsIURI* aBaseURI, 69 OriginAttributes&& aOriginAttributes) { 70 if (!StaticPrefs::network_early_hints_preconnect_enabled()) { 71 return; 72 } 73 74 if (!gIOService) { 75 return; 76 } 77 78 nsCOMPtr<nsIURI> uri; 79 if (NS_FAILED(aHeader.NewResolveHref(getter_AddRefs(uri), aBaseURI))) { 80 return; 81 } 82 83 // only preconnect secure context urls 84 if (!uri->SchemeIs("https")) { 85 return; 86 } 87 88 uint32_t maxPreconnectCount = 89 StaticPrefs::network_early_hints_preconnect_max_connections(); 90 nsCOMPtr<nsIInterfaceRequestor> callbacks = 91 new EarlyHintsPreConnectOverride(maxPreconnectCount); 92 // Note that the http connection manager will limit the number of 93 // connections we can make, so it should be fine we don't check duplicate 94 // preconnect attempts here. 95 CORSMode corsMode = dom::Element::StringToCORSMode(aHeader.mCrossOrigin); 96 gIOService->SpeculativeConnectWithOriginAttributesNative( 97 uri, std::move(aOriginAttributes), callbacks, corsMode == CORS_ANONYMOUS); 98 } 99 100 } // namespace mozilla::net