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 bool WorkerNavigator::GlobalPrivacyControl() const {
95 bool gpcStatus
= StaticPrefs::privacy_globalprivacycontrol_enabled();
97 JSObject
* jso
= GetWrapper();
98 if (const nsCOMPtr
<nsIGlobalObject
> global
= xpc::NativeGlobal(jso
)) {
99 if (const nsCOMPtr
<nsIPrincipal
> principal
= global
->PrincipalOrNull()) {
100 gpcStatus
= principal
->GetPrivateBrowsingId() > 0 &&
101 StaticPrefs::privacy_globalprivacycontrol_pbmode_enabled();
105 return StaticPrefs::privacy_globalprivacycontrol_functionality_enabled() &&
109 void WorkerNavigator::SetLanguages(const nsTArray
<nsString
>& aLanguages
) {
110 WorkerNavigator_Binding::ClearCachedLanguagesValue(this);
111 mProperties
.mLanguages
= aLanguages
.Clone();
114 void WorkerNavigator::GetAppVersion(nsString
& aAppVersion
,
115 CallerType aCallerType
,
116 ErrorResult
& aRv
) const {
117 WorkerPrivate
* workerPrivate
= GetCurrentThreadWorkerPrivate();
118 MOZ_ASSERT(workerPrivate
);
120 if (aCallerType
!= CallerType::System
) {
121 if (workerPrivate
->ShouldResistFingerprinting(
122 RFPTarget::NavigatorAppVersion
)) {
123 // See nsRFPService.h for spoofed value.
124 aAppVersion
.AssignLiteral(SPOOFED_APPVERSION
);
128 if (!mProperties
.mAppVersionOverridden
.IsEmpty()) {
129 aAppVersion
= mProperties
.mAppVersionOverridden
;
134 aAppVersion
= mProperties
.mAppVersion
;
137 void WorkerNavigator::GetPlatform(nsString
& aPlatform
, CallerType aCallerType
,
138 ErrorResult
& aRv
) const {
139 WorkerPrivate
* workerPrivate
= GetCurrentThreadWorkerPrivate();
140 MOZ_ASSERT(workerPrivate
);
142 if (aCallerType
!= CallerType::System
) {
143 if (workerPrivate
->ShouldResistFingerprinting(
144 RFPTarget::NavigatorPlatform
)) {
145 // See nsRFPService.h for spoofed value.
146 aPlatform
.AssignLiteral(SPOOFED_PLATFORM
);
150 if (!mProperties
.mPlatformOverridden
.IsEmpty()) {
151 aPlatform
= mProperties
.mPlatformOverridden
;
156 aPlatform
= mProperties
.mPlatform
;
162 * This Worker Runnable needs to check RFP; but our standard way of doing so
163 * relies on accessing GlobalScope() - which can only be accessed on the worker
164 * thread. So we need to pass it in.
166 class GetUserAgentRunnable final
: public WorkerMainThreadRunnable
{
168 bool mShouldResistFingerprinting
;
171 GetUserAgentRunnable(WorkerPrivate
* aWorkerPrivate
, nsString
& aUA
,
172 bool aShouldResistFingerprinting
)
173 : WorkerMainThreadRunnable(aWorkerPrivate
, "UserAgent getter"_ns
),
175 mShouldResistFingerprinting(aShouldResistFingerprinting
) {
176 MOZ_ASSERT(aWorkerPrivate
);
177 aWorkerPrivate
->AssertIsOnWorkerThread();
180 virtual bool MainThreadRun() override
{
181 AssertIsOnMainThread();
183 nsCOMPtr
<nsPIDOMWindowInner
> window
= mWorkerPrivate
->GetWindow();
186 dom::Navigator::GetUserAgent(window
, mWorkerPrivate
->GetDocument(),
187 Some(mShouldResistFingerprinting
), mUA
);
189 NS_WARNING("Failed to retrieve user-agent from the worker thread.");
198 void WorkerNavigator::GetUserAgent(nsString
& aUserAgent
, CallerType aCallerType
,
199 ErrorResult
& aRv
) const {
200 WorkerPrivate
* workerPrivate
= GetCurrentThreadWorkerPrivate();
201 MOZ_ASSERT(workerPrivate
);
203 RefPtr
<GetUserAgentRunnable
> runnable
= new GetUserAgentRunnable(
204 workerPrivate
, aUserAgent
,
205 workerPrivate
->ShouldResistFingerprinting(RFPTarget::NavigatorUserAgent
));
207 runnable
->Dispatch(Canceling
, aRv
);
210 uint64_t WorkerNavigator::HardwareConcurrency() const {
211 RuntimeService
* rts
= RuntimeService::GetService();
214 WorkerPrivate
* aWorkerPrivate
= GetCurrentThreadWorkerPrivate();
215 bool rfp
= aWorkerPrivate
->ShouldResistFingerprinting(
216 RFPTarget::NavigatorHWConcurrency
);
218 return rts
->ClampedHardwareConcurrency(rfp
);
221 StorageManager
* WorkerNavigator::Storage() {
222 if (!mStorageManager
) {
223 WorkerPrivate
* workerPrivate
= GetCurrentThreadWorkerPrivate();
224 MOZ_ASSERT(workerPrivate
);
226 RefPtr
<nsIGlobalObject
> global
= workerPrivate
->GlobalScope();
229 mStorageManager
= new StorageManager(global
);
232 return mStorageManager
;
235 network::Connection
* WorkerNavigator::GetConnection(ErrorResult
& aRv
) {
237 WorkerPrivate
* workerPrivate
= GetCurrentThreadWorkerPrivate();
238 MOZ_ASSERT(workerPrivate
);
240 mConnection
= network::Connection::CreateForWorker(workerPrivate
, aRv
);
246 dom::MediaCapabilities
* WorkerNavigator::MediaCapabilities() {
247 if (!mMediaCapabilities
) {
248 WorkerPrivate
* workerPrivate
= GetCurrentThreadWorkerPrivate();
249 MOZ_ASSERT(workerPrivate
);
251 nsIGlobalObject
* global
= workerPrivate
->GlobalScope();
254 mMediaCapabilities
= new dom::MediaCapabilities(global
);
256 return mMediaCapabilities
;
259 webgpu::Instance
* WorkerNavigator::Gpu() {
261 WorkerPrivate
* workerPrivate
= GetCurrentThreadWorkerPrivate();
262 MOZ_ASSERT(workerPrivate
);
264 nsIGlobalObject
* global
= workerPrivate
->GlobalScope();
267 mWebGpu
= webgpu::Instance::Create(global
);
272 dom::LockManager
* WorkerNavigator::Locks() {
274 WorkerPrivate
* workerPrivate
= GetCurrentThreadWorkerPrivate();
275 MOZ_ASSERT(workerPrivate
);
277 nsIGlobalObject
* global
= workerPrivate
->GlobalScope();
280 mLocks
= dom::LockManager::Create(*global
);
285 } // namespace mozilla::dom