tor-browser

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

nsHttpActivityDistributor.cpp (9875B)


      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 // HttpLog.h should generally be included first
      6 #include "HttpLog.h"
      7 
      8 #include "mozilla/net/SocketProcessChild.h"
      9 #include "mozilla/net/SocketProcessParent.h"
     10 #include "nsHttpActivityDistributor.h"
     11 #include "nsHttpHandler.h"
     12 #include "nsCOMPtr.h"
     13 #include "nsIOService.h"
     14 #include "nsNetUtil.h"
     15 #include "nsQueryObject.h"
     16 #include "nsThreadUtils.h"
     17 #include "NullHttpChannel.h"
     18 
     19 namespace mozilla {
     20 namespace net {
     21 
     22 using ObserverHolder = nsMainThreadPtrHolder<nsIHttpActivityObserver>;
     23 using ObserverHandle = nsMainThreadPtrHandle<nsIHttpActivityObserver>;
     24 
     25 NS_IMPL_ISUPPORTS(nsHttpActivityDistributor, nsIHttpActivityDistributor,
     26                  nsIHttpActivityObserver)
     27 
     28 NS_IMETHODIMP
     29 nsHttpActivityDistributor::ObserveActivity(nsISupports* aHttpChannel,
     30                                           uint32_t aActivityType,
     31                                           uint32_t aActivitySubtype,
     32                                           PRTime aTimestamp,
     33                                           uint64_t aExtraSizeData,
     34                                           const nsACString& aExtraStringData) {
     35  MOZ_ASSERT(XRE_IsParentProcess() && NS_IsMainThread());
     36 
     37  for (size_t i = 0; i < mObservers.Length(); i++) {
     38    (void)mObservers[i]->ObserveActivity(aHttpChannel, aActivityType,
     39                                         aActivitySubtype, aTimestamp,
     40                                         aExtraSizeData, aExtraStringData);
     41  }
     42  return NS_OK;
     43 }
     44 
     45 NS_IMETHODIMP
     46 nsHttpActivityDistributor::ObserveConnectionActivity(
     47    const nsACString& aHost, int32_t aPort, bool aSSL, bool aHasECH,
     48    bool aIsHttp3, uint32_t aActivityType, uint32_t aActivitySubtype,
     49    PRTime aTimestamp, const nsACString& aExtraStringData) {
     50  MOZ_ASSERT(XRE_IsParentProcess() && NS_IsMainThread());
     51 
     52  for (size_t i = 0; i < mObservers.Length(); i++) {
     53    (void)mObservers[i]->ObserveConnectionActivity(
     54        aHost, aPort, aSSL, aHasECH, aIsHttp3, aActivityType, aActivitySubtype,
     55        aTimestamp, aExtraStringData);
     56  }
     57  return NS_OK;
     58 }
     59 
     60 NS_IMETHODIMP
     61 nsHttpActivityDistributor::ObserveActivityWithArgs(
     62    const HttpActivityArgs& aArgs, uint32_t aActivityType,
     63    uint32_t aActivitySubtype, PRTime aTimestamp, uint64_t aExtraSizeData,
     64    const nsACString& aExtraStringData) {
     65  HttpActivityArgs args(aArgs);
     66  nsCString extraStringData(aExtraStringData);
     67  if (XRE_IsSocketProcess()) {
     68    auto task = [args{std::move(args)}, aActivityType, aActivitySubtype,
     69                 aTimestamp, aExtraSizeData,
     70                 extraStringData{std::move(extraStringData)}]() {
     71      SocketProcessChild::GetSingleton()->SendObserveHttpActivity(
     72          args, aActivityType, aActivitySubtype, aTimestamp, aExtraSizeData,
     73          extraStringData);
     74    };
     75 
     76    if (!NS_IsMainThread()) {
     77      return NS_DispatchToMainThread(NS_NewRunnableFunction(
     78          "net::nsHttpActivityDistributor::ObserveActivityWithArgs", task));
     79    }
     80 
     81    task();
     82    return NS_OK;
     83  }
     84 
     85  MOZ_ASSERT(XRE_IsParentProcess());
     86 
     87  RefPtr<nsHttpActivityDistributor> self = this;
     88  auto task = [args{std::move(args)}, aActivityType, aActivitySubtype,
     89               aTimestamp, aExtraSizeData,
     90               extraStringData{std::move(extraStringData)},
     91               self{std::move(self)}]() {
     92    if (args.type() == HttpActivityArgs::Tuint64_t) {
     93      nsWeakPtr weakPtr = gHttpHandler->GetWeakHttpChannel(args.get_uint64_t());
     94      if (nsCOMPtr<nsIHttpChannel> channel = do_QueryReferent(weakPtr)) {
     95        (void)self->ObserveActivity(channel, aActivityType, aActivitySubtype,
     96                                    aTimestamp, aExtraSizeData,
     97                                    extraStringData);
     98      }
     99    } else if (args.type() == HttpActivityArgs::THttpActivity) {
    100      nsCOMPtr<nsIURI> uri;
    101      nsAutoCString portStr(""_ns);
    102      int32_t port = args.get_HttpActivity().port();
    103      bool endToEndSSL = args.get_HttpActivity().endToEndSSL();
    104      if (port != -1 &&
    105          ((endToEndSSL && port != 443) || (!endToEndSSL && port != 80))) {
    106        portStr.AppendInt(port);
    107      }
    108 
    109      nsresult rv =
    110          NS_NewURI(getter_AddRefs(uri),
    111                    (endToEndSSL ? "https://"_ns : "http://"_ns) +
    112                        args.get_HttpActivity().host() + ":"_ns + portStr);
    113      if (NS_FAILED(rv)) {
    114        return;
    115      }
    116 
    117      RefPtr<NullHttpChannel> channel = new NullHttpChannel();
    118      rv = channel->Init(uri, 0, nullptr, 0, nullptr);
    119      MOZ_ASSERT(NS_SUCCEEDED(rv));
    120 
    121      (void)self->ObserveActivity(static_cast<nsIChannel*>(channel),
    122                                  aActivityType, aActivitySubtype, aTimestamp,
    123                                  aExtraSizeData, extraStringData);
    124    } else if (args.type() == HttpActivityArgs::THttpConnectionActivity) {
    125      const HttpConnectionActivity& activity =
    126          args.get_HttpConnectionActivity();
    127      (void)self->ObserveConnectionActivity(
    128          activity.host(), activity.port(), activity.ssl(), activity.hasECH(),
    129          activity.isHttp3(), aActivityType, aActivitySubtype, aTimestamp,
    130          activity.connInfoKey());
    131    }
    132  };
    133 
    134  if (!NS_IsMainThread()) {
    135    return NS_DispatchToMainThread(NS_NewRunnableFunction(
    136        "net::nsHttpActivityDistributor::ObserveActivityWithArgs", task));
    137  }
    138 
    139  task();
    140  return NS_OK;
    141 }
    142 
    143 bool nsHttpActivityDistributor::Activated() { return mActivated; }
    144 
    145 bool nsHttpActivityDistributor::ObserveProxyResponseEnabled() {
    146  return mObserveProxyResponse;
    147 }
    148 
    149 bool nsHttpActivityDistributor::ObserveConnectionEnabled() {
    150  return mObserveConnection;
    151 }
    152 
    153 NS_IMETHODIMP
    154 nsHttpActivityDistributor::GetIsActive(bool* isActive) {
    155  NS_ENSURE_ARG_POINTER(isActive);
    156  if (XRE_IsSocketProcess()) {
    157    *isActive = mActivated;
    158    return NS_OK;
    159  }
    160 
    161  MutexAutoLock lock(mLock);
    162  *isActive = mActivated = !!mObservers.Length();
    163  return NS_OK;
    164 }
    165 
    166 NS_IMETHODIMP nsHttpActivityDistributor::SetIsActive(bool aActived) {
    167  MOZ_RELEASE_ASSERT(XRE_IsSocketProcess());
    168 
    169  mActivated = aActived;
    170  return NS_OK;
    171 }
    172 
    173 NS_IMETHODIMP
    174 nsHttpActivityDistributor::AddObserver(nsIHttpActivityObserver* aObserver) {
    175  MOZ_ASSERT(XRE_IsParentProcess());
    176  if (!NS_IsMainThread()) {
    177    // We only support calling this from the main thread.
    178    return NS_ERROR_FAILURE;
    179  }
    180 
    181  ObserverHandle observer(
    182      new ObserverHolder("nsIHttpActivityObserver", aObserver));
    183 
    184  bool wasEmpty = false;
    185  {
    186    MutexAutoLock lock(mLock);
    187    wasEmpty = mObservers.IsEmpty();
    188    // XXX(Bug 1631371) Check if this should use a fallible operation as it
    189    // pretended earlier.
    190    mObservers.AppendElement(observer);
    191  }
    192 
    193  if (wasEmpty) {
    194    mActivated = true;
    195    if (nsIOService::UseSocketProcess()) {
    196      auto task = []() {
    197        RefPtr<SocketProcessParent> parent =
    198            SocketProcessParent::GetSingleton();
    199        if (parent && parent->CanSend()) {
    200          (void)parent->SendOnHttpActivityDistributorActivated(true);
    201        }
    202      };
    203      gIOService->CallOrWaitForSocketProcess(task);
    204    }
    205  }
    206  return NS_OK;
    207 }
    208 
    209 NS_IMETHODIMP
    210 nsHttpActivityDistributor::RemoveObserver(nsIHttpActivityObserver* aObserver) {
    211  MOZ_ASSERT(XRE_IsParentProcess());
    212  if (!NS_IsMainThread()) {
    213    // We only support calling this from the main thread.
    214    return NS_ERROR_FAILURE;
    215  }
    216 
    217  ObserverHandle observer(
    218      new ObserverHolder("nsIHttpActivityObserver", aObserver));
    219 
    220  {
    221    MutexAutoLock lock(mLock);
    222    if (!mObservers.RemoveElement(observer)) {
    223      return NS_ERROR_FAILURE;
    224    }
    225    mActivated = mObservers.IsEmpty();
    226  }
    227 
    228  if (nsIOService::UseSocketProcess() && !mActivated) {
    229    auto task = []() {
    230      RefPtr<SocketProcessParent> parent = SocketProcessParent::GetSingleton();
    231      if (parent && parent->CanSend()) {
    232        (void)parent->SendOnHttpActivityDistributorActivated(false);
    233      }
    234    };
    235    gIOService->CallOrWaitForSocketProcess(task);
    236  }
    237  return NS_OK;
    238 }
    239 
    240 NS_IMETHODIMP
    241 nsHttpActivityDistributor::GetObserveProxyResponse(
    242    bool* aObserveProxyResponse) {
    243  NS_ENSURE_ARG_POINTER(aObserveProxyResponse);
    244  bool result = mObserveProxyResponse;
    245  *aObserveProxyResponse = result;
    246  return NS_OK;
    247 }
    248 
    249 NS_IMETHODIMP
    250 nsHttpActivityDistributor::SetObserveProxyResponse(bool aObserveProxyResponse) {
    251  if (!NS_IsMainThread()) {
    252    // We only support calling this from the main thread.
    253    return NS_ERROR_FAILURE;
    254  }
    255 
    256  mObserveProxyResponse = aObserveProxyResponse;
    257  if (nsIOService::UseSocketProcess()) {
    258    auto task = [aObserveProxyResponse]() {
    259      RefPtr<SocketProcessParent> parent = SocketProcessParent::GetSingleton();
    260      if (parent && parent->CanSend()) {
    261        (void)parent->SendOnHttpActivityDistributorObserveProxyResponse(
    262            aObserveProxyResponse);
    263      }
    264    };
    265    gIOService->CallOrWaitForSocketProcess(task);
    266  }
    267  return NS_OK;
    268 }
    269 
    270 NS_IMETHODIMP
    271 nsHttpActivityDistributor::GetObserveConnection(bool* aObserveConnection) {
    272  NS_ENSURE_ARG_POINTER(aObserveConnection);
    273 
    274  *aObserveConnection = mObserveConnection;
    275  return NS_OK;
    276 }
    277 
    278 NS_IMETHODIMP
    279 nsHttpActivityDistributor::SetObserveConnection(bool aObserveConnection) {
    280  if (!NS_IsMainThread()) {
    281    // We only support calling this from the main thread.
    282    return NS_ERROR_FAILURE;
    283  }
    284 
    285  mObserveConnection = aObserveConnection;
    286  if (nsIOService::UseSocketProcess()) {
    287    auto task = [aObserveConnection]() {
    288      RefPtr<SocketProcessParent> parent = SocketProcessParent::GetSingleton();
    289      if (parent && parent->CanSend()) {
    290        (void)parent->SendOnHttpActivityDistributorObserveConnection(
    291            aObserveConnection);
    292      }
    293    };
    294    gIOService->CallOrWaitForSocketProcess(task);
    295  }
    296  return NS_OK;
    297 }
    298 
    299 }  // namespace net
    300 }  // namespace mozilla