Bug 1771337 [wpt PR 34217] - Convert `popup=popup` to `popup=auto` or just `popup...
[gecko.git] / dom / performance / PerformanceStorageWorker.cpp
blob6a6fbea6d0426ddc2031dda99a80d876fe36c296
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/. */
7 #include "PerformanceStorageWorker.h"
8 #include "Performance.h"
9 #include "PerformanceResourceTiming.h"
10 #include "PerformanceTiming.h"
11 #include "mozilla/dom/WorkerRef.h"
12 #include "mozilla/dom/WorkerRunnable.h"
13 #include "mozilla/dom/WorkerScope.h"
15 namespace mozilla::dom {
17 class PerformanceProxyData {
18 public:
19 PerformanceProxyData(UniquePtr<PerformanceTimingData>&& aData,
20 const nsAString& aInitiatorType,
21 const nsAString& aEntryName)
22 : mData(std::move(aData)),
23 mInitiatorType(aInitiatorType),
24 mEntryName(aEntryName) {
25 MOZ_RELEASE_ASSERT(mData);
28 UniquePtr<PerformanceTimingData> mData; // always non-null
29 nsString mInitiatorType;
30 nsString mEntryName;
33 namespace {
35 // Here we use control runnable because this code must be executed also when in
36 // a sync event loop
37 class PerformanceEntryAdder final : public WorkerControlRunnable {
38 public:
39 PerformanceEntryAdder(WorkerPrivate* aWorkerPrivate,
40 PerformanceStorageWorker* aStorage,
41 UniquePtr<PerformanceProxyData>&& aData)
42 : WorkerControlRunnable(aWorkerPrivate, WorkerThreadUnchangedBusyCount),
43 mStorage(aStorage),
44 mData(std::move(aData)) {}
46 bool WorkerRun(JSContext* aCx, WorkerPrivate* aWorkerPrivate) override {
47 mStorage->AddEntryOnWorker(std::move(mData));
48 return true;
51 nsresult Cancel() override {
52 mStorage->ShutdownOnWorker();
53 return WorkerRunnable::Cancel();
56 bool PreDispatch(WorkerPrivate* aWorkerPrivate) override { return true; }
58 void PostDispatch(WorkerPrivate* aWorkerPrivate,
59 bool aDispatchResult) override {}
61 private:
62 RefPtr<PerformanceStorageWorker> mStorage;
63 UniquePtr<PerformanceProxyData> mData;
66 } // namespace
68 /* static */
69 already_AddRefed<PerformanceStorageWorker> PerformanceStorageWorker::Create(
70 WorkerPrivate* aWorkerPrivate) {
71 MOZ_ASSERT(aWorkerPrivate);
72 aWorkerPrivate->AssertIsOnWorkerThread();
74 RefPtr<PerformanceStorageWorker> storage = new PerformanceStorageWorker();
76 MutexAutoLock lock(storage->mMutex); // for thread-safety analysis
77 storage->mWorkerRef = WeakWorkerRef::Create(
78 aWorkerPrivate, [storage]() { storage->ShutdownOnWorker(); });
80 // PerformanceStorageWorker is created at the creation time of the worker.
81 MOZ_ASSERT(storage->mWorkerRef);
83 return storage.forget();
86 PerformanceStorageWorker::PerformanceStorageWorker()
87 : mMutex("PerformanceStorageWorker::mMutex") {}
89 PerformanceStorageWorker::~PerformanceStorageWorker() = default;
91 void PerformanceStorageWorker::AddEntry(nsIHttpChannel* aChannel,
92 nsITimedChannel* aTimedChannel) {
93 MOZ_ASSERT(NS_IsMainThread());
95 MutexAutoLock lock(mMutex);
97 if (!mWorkerRef) {
98 return;
101 // If we have mWorkerRef, we haven't received the WorkerRef notification and
102 // we haven't yet call ShutdownOnWorker, which uses the mutex.
103 WorkerPrivate* workerPrivate = mWorkerRef->GetUnsafePrivate();
104 MOZ_ASSERT(workerPrivate);
106 nsAutoString initiatorType;
107 nsAutoString entryName;
109 UniquePtr<PerformanceTimingData> performanceTimingData(
110 PerformanceTimingData::Create(aTimedChannel, aChannel, 0, initiatorType,
111 entryName));
112 if (!performanceTimingData) {
113 return;
116 UniquePtr<PerformanceProxyData> data(new PerformanceProxyData(
117 std::move(performanceTimingData), initiatorType, entryName));
119 RefPtr<PerformanceEntryAdder> r =
120 new PerformanceEntryAdder(workerPrivate, this, std::move(data));
121 Unused << NS_WARN_IF(!r->Dispatch());
124 void PerformanceStorageWorker::AddEntry(
125 const nsString& aEntryName, const nsString& aInitiatorType,
126 UniquePtr<PerformanceTimingData>&& aData) {
127 MOZ_ASSERT(!NS_IsMainThread());
128 if (!aData) {
129 return;
132 UniquePtr<PerformanceProxyData> data = MakeUnique<PerformanceProxyData>(
133 std::move(aData), aInitiatorType, aEntryName);
135 AddEntryOnWorker(std::move(data));
138 void PerformanceStorageWorker::ShutdownOnWorker() {
139 MutexAutoLock lock(mMutex);
141 if (!mWorkerRef) {
142 return;
145 MOZ_ASSERT(!NS_IsMainThread());
147 mWorkerRef = nullptr;
150 void PerformanceStorageWorker::AddEntryOnWorker(
151 UniquePtr<PerformanceProxyData>&& aData) {
152 RefPtr<Performance> performance;
153 UniquePtr<PerformanceProxyData> data = std::move(aData);
156 MutexAutoLock lock(mMutex);
158 if (!mWorkerRef) {
159 return;
162 // We must have the workerPrivate because it is available until a
163 // notification is received by WorkerRef and we use mutex to make the code
164 // protected.
165 WorkerPrivate* workerPrivate = mWorkerRef->GetPrivate();
166 MOZ_ASSERT(workerPrivate);
168 WorkerGlobalScope* scope = workerPrivate->GlobalScope();
169 performance = scope->GetPerformance();
172 if (NS_WARN_IF(!performance)) {
173 return;
176 RefPtr<PerformanceResourceTiming> performanceEntry =
177 new PerformanceResourceTiming(std::move(data->mData), performance,
178 data->mEntryName);
179 performanceEntry->SetInitiatorType(data->mInitiatorType);
181 performance->InsertResourceEntry(performanceEntry);
184 } // namespace mozilla::dom