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 "mozilla/dom/WorkerNavigator.h"
11 #include "ErrorList.h"
12 #include "MainThreadUtils.h"
13 #include "RuntimeService.h"
14 #include "WorkerRunnable.h"
15 #include "WorkerScope.h"
16 #include "mozilla/dom/LockManager.h"
17 #include "mozilla/dom/MediaCapabilities.h"
18 #include "mozilla/dom/Navigator.h"
19 #include "mozilla/dom/StorageManager.h"
20 #include "mozilla/dom/WorkerCommon.h"
21 #include "mozilla/dom/WorkerNavigatorBinding.h"
22 #include "mozilla/dom/WorkerStatus.h"
23 #include "mozilla/dom/network/Connection.h"
24 #include "mozilla/webgpu/Instance.h"
28 #include "nsIGlobalObject.h"
29 #include "nsLiteralString.h"
30 #include "nsPIDOMWindow.h"
31 #include "nsRFPService.h"
37 namespace mozilla::dom
{
39 using namespace workerinternals
;
41 NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_CLASS(WorkerNavigator
)
42 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(WorkerNavigator
)
44 NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
45 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
47 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(WorkerNavigator
)
48 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mStorageManager
)
49 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mConnection
)
50 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mMediaCapabilities
)
51 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mWebGpu
)
52 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mLocks
)
53 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
55 WorkerNavigator::WorkerNavigator(const NavigatorProperties
& aProperties
,
57 : mProperties(aProperties
), mOnline(aOnline
) {}
59 WorkerNavigator::~WorkerNavigator() { Invalidate(); }
62 already_AddRefed
<WorkerNavigator
> WorkerNavigator::Create(bool aOnLine
) {
63 RuntimeService
* rts
= RuntimeService::GetService();
66 const RuntimeService::NavigatorProperties
& properties
=
67 rts
->GetNavigatorProperties();
69 RefPtr
<WorkerNavigator
> navigator
= new WorkerNavigator(properties
, aOnLine
);
71 return navigator
.forget();
74 void WorkerNavigator::Invalidate() {
75 if (mStorageManager
) {
76 mStorageManager
->Shutdown();
77 mStorageManager
= nullptr;
80 mConnection
= nullptr;
82 mMediaCapabilities
= nullptr;
89 JSObject
* WorkerNavigator::WrapObject(JSContext
* aCx
,
90 JS::Handle
<JSObject
*> aGivenProto
) {
91 return WorkerNavigator_Binding::Wrap(aCx
, this, aGivenProto
);
94 void WorkerNavigator::SetLanguages(const nsTArray
<nsString
>& aLanguages
) {
95 WorkerNavigator_Binding::ClearCachedLanguagesValue(this);
96 mProperties
.mLanguages
= aLanguages
.Clone();
99 void WorkerNavigator::GetAppName(nsString
& aAppName
,
100 CallerType aCallerType
) const {
101 WorkerPrivate
* workerPrivate
= GetCurrentThreadWorkerPrivate();
102 MOZ_ASSERT(workerPrivate
);
104 if (aCallerType
!= CallerType::System
) {
105 if (workerPrivate
->GlobalScope()->ShouldResistFingerprinting(
106 RFPTarget::NavigatorAppName
)) {
107 // See nsRFPService.h for spoofed value.
108 aAppName
.AssignLiteral(SPOOFED_APPNAME
);
112 if (!mProperties
.mAppNameOverridden
.IsEmpty()) {
113 aAppName
= mProperties
.mAppNameOverridden
;
118 aAppName
= mProperties
.mAppName
;
121 void WorkerNavigator::GetAppVersion(nsString
& aAppVersion
,
122 CallerType aCallerType
,
123 ErrorResult
& aRv
) const {
124 WorkerPrivate
* workerPrivate
= GetCurrentThreadWorkerPrivate();
125 MOZ_ASSERT(workerPrivate
);
127 if (aCallerType
!= CallerType::System
) {
128 if (workerPrivate
->GlobalScope()->ShouldResistFingerprinting(
129 RFPTarget::NavigatorAppVersion
)) {
130 // See nsRFPService.h for spoofed value.
131 aAppVersion
.AssignLiteral(SPOOFED_APPVERSION
);
135 if (!mProperties
.mAppVersionOverridden
.IsEmpty()) {
136 aAppVersion
= mProperties
.mAppVersionOverridden
;
141 aAppVersion
= mProperties
.mAppVersion
;
144 void WorkerNavigator::GetPlatform(nsString
& aPlatform
, CallerType aCallerType
,
145 ErrorResult
& aRv
) const {
146 WorkerPrivate
* workerPrivate
= GetCurrentThreadWorkerPrivate();
147 MOZ_ASSERT(workerPrivate
);
149 if (aCallerType
!= CallerType::System
) {
150 if (workerPrivate
->GlobalScope()->ShouldResistFingerprinting(
151 RFPTarget::NavigatorPlatform
)) {
152 // See nsRFPService.h for spoofed value.
153 aPlatform
.AssignLiteral(SPOOFED_PLATFORM
);
157 if (!mProperties
.mPlatformOverridden
.IsEmpty()) {
158 aPlatform
= mProperties
.mPlatformOverridden
;
163 aPlatform
= mProperties
.mPlatform
;
169 * This Worker Runnable needs to check RFP; but our standard way of doing so
170 * relies on accessing GlobalScope() - which can only be accessed on the worker
171 * thread. So we need to pass it in.
173 class GetUserAgentRunnable final
: public WorkerMainThreadRunnable
{
175 bool mShouldResistFingerprinting
;
178 GetUserAgentRunnable(WorkerPrivate
* aWorkerPrivate
, nsString
& aUA
,
179 bool aShouldResistFingerprinting
)
180 : WorkerMainThreadRunnable(aWorkerPrivate
, "UserAgent getter"_ns
),
182 mShouldResistFingerprinting(aShouldResistFingerprinting
) {
183 MOZ_ASSERT(aWorkerPrivate
);
184 aWorkerPrivate
->AssertIsOnWorkerThread();
187 virtual bool MainThreadRun() override
{
188 AssertIsOnMainThread();
190 nsCOMPtr
<nsPIDOMWindowInner
> window
= mWorkerPrivate
->GetWindow();
193 dom::Navigator::GetUserAgent(window
, mWorkerPrivate
->GetDocument(),
194 Some(mShouldResistFingerprinting
), mUA
);
196 NS_WARNING("Failed to retrieve user-agent from the worker thread.");
205 void WorkerNavigator::GetUserAgent(nsString
& aUserAgent
, CallerType aCallerType
,
206 ErrorResult
& aRv
) const {
207 WorkerPrivate
* workerPrivate
= GetCurrentThreadWorkerPrivate();
208 MOZ_ASSERT(workerPrivate
);
210 RefPtr
<GetUserAgentRunnable
> runnable
= new GetUserAgentRunnable(
211 workerPrivate
, aUserAgent
,
212 workerPrivate
->GlobalScope()->ShouldResistFingerprinting(
213 RFPTarget::NavigatorUserAgent
));
215 runnable
->Dispatch(Canceling
, aRv
);
218 uint64_t WorkerNavigator::HardwareConcurrency() const {
219 RuntimeService
* rts
= RuntimeService::GetService();
222 WorkerPrivate
* aWorkerPrivate
= GetCurrentThreadWorkerPrivate();
223 bool rfp
= aWorkerPrivate
->GlobalScope()->ShouldResistFingerprinting(
224 RFPTarget::NavigatorHWConcurrency
);
226 return rts
->ClampedHardwareConcurrency(rfp
);
229 StorageManager
* WorkerNavigator::Storage() {
230 if (!mStorageManager
) {
231 WorkerPrivate
* workerPrivate
= GetCurrentThreadWorkerPrivate();
232 MOZ_ASSERT(workerPrivate
);
234 RefPtr
<nsIGlobalObject
> global
= workerPrivate
->GlobalScope();
237 mStorageManager
= new StorageManager(global
);
240 return mStorageManager
;
243 network::Connection
* WorkerNavigator::GetConnection(ErrorResult
& aRv
) {
245 WorkerPrivate
* workerPrivate
= GetCurrentThreadWorkerPrivate();
246 MOZ_ASSERT(workerPrivate
);
248 mConnection
= network::Connection::CreateForWorker(workerPrivate
, aRv
);
254 dom::MediaCapabilities
* WorkerNavigator::MediaCapabilities() {
255 if (!mMediaCapabilities
) {
256 WorkerPrivate
* workerPrivate
= GetCurrentThreadWorkerPrivate();
257 MOZ_ASSERT(workerPrivate
);
259 nsIGlobalObject
* global
= workerPrivate
->GlobalScope();
262 mMediaCapabilities
= new dom::MediaCapabilities(global
);
264 return mMediaCapabilities
;
267 webgpu::Instance
* WorkerNavigator::Gpu() {
269 WorkerPrivate
* workerPrivate
= GetCurrentThreadWorkerPrivate();
270 MOZ_ASSERT(workerPrivate
);
272 nsIGlobalObject
* global
= workerPrivate
->GlobalScope();
275 mWebGpu
= webgpu::Instance::Create(global
);
280 dom::LockManager
* WorkerNavigator::Locks() {
282 WorkerPrivate
* workerPrivate
= GetCurrentThreadWorkerPrivate();
283 MOZ_ASSERT(workerPrivate
);
285 nsIGlobalObject
* global
= workerPrivate
->GlobalScope();
288 mLocks
= new dom::LockManager(global
);
293 } // namespace mozilla::dom