Bug 1892041 - Part 1: Update test262 features. r=spidermonkey-reviewers,dminor
[gecko.git] / dom / performance / PerformanceStorageWorker.cpp
blob4fb4815121344b3a546f8f4d4afe18800cde9cac
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, "PerformanceEntryAdder",
43 WorkerThread),
44 mStorage(aStorage),
45 mData(std::move(aData)) {}
47 bool WorkerRun(JSContext* aCx, WorkerPrivate* aWorkerPrivate) override {
48 mStorage->AddEntryOnWorker(std::move(mData));
49 return true;
52 nsresult Cancel() override {
53 mStorage->ShutdownOnWorker();
54 return NS_OK;
57 bool PreDispatch(WorkerPrivate* aWorkerPrivate) override { return true; }
59 void PostDispatch(WorkerPrivate* aWorkerPrivate,
60 bool aDispatchResult) override {}
62 private:
63 RefPtr<PerformanceStorageWorker> mStorage;
64 UniquePtr<PerformanceProxyData> mData;
67 } // namespace
69 /* static */
70 already_AddRefed<PerformanceStorageWorker> PerformanceStorageWorker::Create(
71 WorkerPrivate* aWorkerPrivate) {
72 MOZ_ASSERT(aWorkerPrivate);
73 aWorkerPrivate->AssertIsOnWorkerThread();
75 RefPtr<PerformanceStorageWorker> storage = new PerformanceStorageWorker();
77 MutexAutoLock lock(storage->mMutex); // for thread-safety analysis
78 storage->mWorkerRef = WeakWorkerRef::Create(
79 aWorkerPrivate, [storage]() { storage->ShutdownOnWorker(); });
81 // PerformanceStorageWorker is created at the creation time of the worker.
82 MOZ_ASSERT(storage->mWorkerRef);
84 return storage.forget();
87 PerformanceStorageWorker::PerformanceStorageWorker()
88 : mMutex("PerformanceStorageWorker::mMutex") {}
90 PerformanceStorageWorker::~PerformanceStorageWorker() = default;
92 void PerformanceStorageWorker::AddEntry(nsIHttpChannel* aChannel,
93 nsITimedChannel* aTimedChannel) {
94 MOZ_ASSERT(NS_IsMainThread());
96 MutexAutoLock lock(mMutex);
98 if (!mWorkerRef) {
99 return;
102 // If we have mWorkerRef, we haven't received the WorkerRef notification and
103 // we haven't yet call ShutdownOnWorker, which uses the mutex.
104 WorkerPrivate* workerPrivate = mWorkerRef->GetUnsafePrivate();
105 MOZ_ASSERT(workerPrivate);
107 nsAutoString initiatorType;
108 nsAutoString entryName;
110 UniquePtr<PerformanceTimingData> performanceTimingData(
111 PerformanceTimingData::Create(aTimedChannel, aChannel, 0, initiatorType,
112 entryName));
113 if (!performanceTimingData) {
114 return;
117 UniquePtr<PerformanceProxyData> data(new PerformanceProxyData(
118 std::move(performanceTimingData), initiatorType, entryName));
120 RefPtr<PerformanceEntryAdder> r =
121 new PerformanceEntryAdder(workerPrivate, this, std::move(data));
122 Unused << NS_WARN_IF(!r->Dispatch());
125 void PerformanceStorageWorker::AddEntry(
126 const nsString& aEntryName, const nsString& aInitiatorType,
127 UniquePtr<PerformanceTimingData>&& aData) {
128 MOZ_ASSERT(!NS_IsMainThread());
129 if (!aData) {
130 return;
133 UniquePtr<PerformanceProxyData> data = MakeUnique<PerformanceProxyData>(
134 std::move(aData), aInitiatorType, aEntryName);
136 AddEntryOnWorker(std::move(data));
139 void PerformanceStorageWorker::ShutdownOnWorker() {
140 MutexAutoLock lock(mMutex);
142 if (!mWorkerRef) {
143 return;
146 MOZ_ASSERT(!NS_IsMainThread());
148 mWorkerRef = nullptr;
151 void PerformanceStorageWorker::AddEntryOnWorker(
152 UniquePtr<PerformanceProxyData>&& aData) {
153 RefPtr<Performance> performance;
154 UniquePtr<PerformanceProxyData> data = std::move(aData);
157 MutexAutoLock lock(mMutex);
159 if (!mWorkerRef) {
160 return;
163 // We must have the workerPrivate because it is available until a
164 // notification is received by WorkerRef and we use mutex to make the code
165 // protected.
166 WorkerPrivate* workerPrivate = mWorkerRef->GetPrivate();
167 MOZ_ASSERT(workerPrivate);
169 WorkerGlobalScope* scope = workerPrivate->GlobalScope();
170 performance = scope->GetPerformance();
173 if (NS_WARN_IF(!performance)) {
174 return;
177 RefPtr<PerformanceResourceTiming> performanceEntry =
178 new PerformanceResourceTiming(std::move(data->mData), performance,
179 data->mEntryName);
180 performanceEntry->SetInitiatorType(data->mInitiatorType);
182 performance->InsertResourceEntry(performanceEntry);
185 } // namespace mozilla::dom