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
{
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
;
35 // Here we use control runnable because this code must be executed also when in
37 class PerformanceEntryAdder final
: public WorkerControlRunnable
{
39 PerformanceEntryAdder(WorkerPrivate
* aWorkerPrivate
,
40 PerformanceStorageWorker
* aStorage
,
41 UniquePtr
<PerformanceProxyData
>&& aData
)
42 : WorkerControlRunnable(aWorkerPrivate
, "PerformanceEntryAdder",
45 mData(std::move(aData
)) {}
47 bool WorkerRun(JSContext
* aCx
, WorkerPrivate
* aWorkerPrivate
) override
{
48 mStorage
->AddEntryOnWorker(std::move(mData
));
52 nsresult
Cancel() override
{
53 mStorage
->ShutdownOnWorker();
57 bool PreDispatch(WorkerPrivate
* aWorkerPrivate
) override
{ return true; }
59 void PostDispatch(WorkerPrivate
* aWorkerPrivate
,
60 bool aDispatchResult
) override
{}
63 RefPtr
<PerformanceStorageWorker
> mStorage
;
64 UniquePtr
<PerformanceProxyData
> mData
;
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
);
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
,
113 if (!performanceTimingData
) {
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());
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
);
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
);
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
166 WorkerPrivate
* workerPrivate
= mWorkerRef
->GetPrivate();
167 MOZ_ASSERT(workerPrivate
);
169 WorkerGlobalScope
* scope
= workerPrivate
->GlobalScope();
170 performance
= scope
->GetPerformance();
173 if (NS_WARN_IF(!performance
)) {
177 RefPtr
<PerformanceResourceTiming
> performanceEntry
=
178 new PerformanceResourceTiming(std::move(data
->mData
), performance
,
180 performanceEntry
->SetInitiatorType(data
->mInitiatorType
);
182 performance
->InsertResourceEntry(performanceEntry
);
185 } // namespace mozilla::dom