tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

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