tor-browser

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

EarlyHintRegistrar.cpp (3734B)


      1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
      2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
      3 /* This Source Code Form is subject to the terms of the Mozilla Public
      4 * License, v. 2.0. If a copy of the MPL was not distributed with this
      5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      6 
      7 #include "EarlyHintRegistrar.h"
      8 
      9 #include "EarlyHintPreloader.h"
     10 #include "mozilla/ClearOnShutdown.h"
     11 #include "mozilla/StaticPtr.h"
     12 #include "nsIObserver.h"
     13 #include "nsIObserverService.h"
     14 #include "nsXULAppAPI.h"
     15 
     16 namespace {
     17 mozilla::StaticRefPtr<mozilla::net::EarlyHintRegistrar> gSingleton;
     18 }  // namespace
     19 
     20 namespace mozilla::net {
     21 
     22 namespace {
     23 
     24 class EHShutdownObserver final : public nsIObserver {
     25 public:
     26  EHShutdownObserver() = default;
     27 
     28  NS_DECL_ISUPPORTS
     29  NS_DECL_NSIOBSERVER
     30 
     31 private:
     32  ~EHShutdownObserver() = default;
     33 };
     34 
     35 NS_IMPL_ISUPPORTS(EHShutdownObserver, nsIObserver)
     36 
     37 NS_IMETHODIMP
     38 EHShutdownObserver::Observe(nsISupports* aSubject, const char* aTopic,
     39                            const char16_t* aData) {
     40  EarlyHintRegistrar::CleanUp();
     41  return NS_OK;
     42 }
     43 
     44 }  // namespace
     45 
     46 EarlyHintRegistrar::EarlyHintRegistrar() {
     47  // EarlyHintRegistrar is a main-thread-only object.
     48  // All the operations should be run on main thread.
     49  // It should be used on chrome process only.
     50  MOZ_ASSERT(XRE_IsParentProcess());
     51  MOZ_ASSERT(NS_IsMainThread());
     52 }
     53 
     54 EarlyHintRegistrar::~EarlyHintRegistrar() { MOZ_ASSERT(NS_IsMainThread()); }
     55 
     56 // static
     57 void EarlyHintRegistrar::CleanUp() {
     58  MOZ_ASSERT(NS_IsMainThread());
     59 
     60  if (!gSingleton) {
     61    return;
     62  }
     63 
     64  for (auto& preloader : gSingleton->mEarlyHint) {
     65    if (auto p = preloader.GetData()) {
     66      // Don't delete entry from EarlyHintPreloader, because that would
     67      // invalidate the iterator.
     68 
     69      p->CancelChannel(NS_ERROR_ABORT, "EarlyHintRegistrar::CleanUp"_ns,
     70                       /* aDeleteEntry */ false);
     71    }
     72  }
     73  gSingleton->mEarlyHint.Clear();
     74 }
     75 
     76 // static
     77 already_AddRefed<EarlyHintRegistrar> EarlyHintRegistrar::GetOrCreate() {
     78  MOZ_ASSERT(NS_IsMainThread());
     79 
     80  if (!gSingleton) {
     81    gSingleton = new EarlyHintRegistrar();
     82    nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
     83    if (NS_WARN_IF(!obs)) {
     84      return nullptr;
     85    }
     86    nsCOMPtr<nsIObserver> observer = new EHShutdownObserver();
     87    nsresult rv =
     88        obs->AddObserver(observer, "profile-change-net-teardown", false);
     89    if (NS_WARN_IF(NS_FAILED(rv))) {
     90      return nullptr;
     91    }
     92    mozilla::ClearOnShutdown(&gSingleton);
     93  }
     94  return do_AddRef(gSingleton);
     95 }
     96 
     97 void EarlyHintRegistrar::DeleteEntry(dom::ContentParentId aCpId,
     98                                     uint64_t aEarlyHintPreloaderId) {
     99  MOZ_ASSERT(NS_IsMainThread());
    100 
    101  RefPtr<EarlyHintPreloader> ehp = mEarlyHint.Get(aEarlyHintPreloaderId);
    102  if (ehp && ehp->IsFromContentParent(aCpId)) {
    103    mEarlyHint.Remove(aEarlyHintPreloaderId);
    104  }
    105 }
    106 
    107 void EarlyHintRegistrar::RegisterEarlyHint(uint64_t aEarlyHintPreloaderId,
    108                                           EarlyHintPreloader* aEhp) {
    109  MOZ_ASSERT(NS_IsMainThread());
    110  MOZ_ASSERT(aEhp);
    111 
    112  mEarlyHint.InsertOrUpdate(aEarlyHintPreloaderId, RefPtr{aEhp});
    113 }
    114 
    115 bool EarlyHintRegistrar::LinkParentChannel(dom::ContentParentId aCpId,
    116                                           uint64_t aEarlyHintPreloaderId,
    117                                           nsIParentChannel* aParent) {
    118  MOZ_ASSERT(NS_IsMainThread());
    119  MOZ_ASSERT(aParent);
    120 
    121  RefPtr<EarlyHintPreloader> ehp;
    122  bool found = mEarlyHint.Get(aEarlyHintPreloaderId, getter_AddRefs(ehp));
    123  if (ehp && ehp->IsFromContentParent(aCpId)) {
    124    ehp->OnParentReady(aParent);
    125  }
    126  MOZ_ASSERT(ehp || !found);
    127  return found;
    128 }
    129 
    130 }  // namespace mozilla::net