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