Backed out changeset e95ff11012c5 (bug 1910360) as requested for causing Android...
[gecko.git] / dom / workers / WorkerNavigator.cpp
blob4f9988bd17a187c0bc06ffb4aa460924d73a121f
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"
9 #include <utility>
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"
25 #include "nsCOMPtr.h"
26 #include "nsDebug.h"
27 #include "nsError.h"
28 #include "nsIGlobalObject.h"
29 #include "nsLiteralString.h"
30 #include "nsPIDOMWindow.h"
31 #include "nsRFPService.h"
32 #include "nsString.h"
34 class JSObject;
35 struct JSContext;
37 namespace mozilla::dom {
39 using namespace workerinternals;
41 NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_CLASS(WorkerNavigator)
42 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(WorkerNavigator)
43 tmp->Invalidate();
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,
56 bool aOnline)
57 : mProperties(aProperties), mOnline(aOnline) {}
59 WorkerNavigator::~WorkerNavigator() { Invalidate(); }
61 /* static */
62 already_AddRefed<WorkerNavigator> WorkerNavigator::Create(bool aOnLine) {
63 RuntimeService* rts = RuntimeService::GetService();
64 MOZ_ASSERT(rts);
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;
84 mWebGpu = nullptr;
86 mLocks = 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();
96 if (!gpcStatus) {
97 JSObject* jso = GetWrapper();
98 if (const nsCOMPtr<nsIGlobalObject> global = xpc::NativeGlobal(jso)) {
99 if (const nsCOMPtr<nsIPrincipal> principal = global->PrincipalOrNull()) {
100 gpcStatus = principal->GetIsInPrivateBrowsing() &&
101 StaticPrefs::privacy_globalprivacycontrol_pbmode_enabled();
105 return StaticPrefs::privacy_globalprivacycontrol_functionality_enabled() &&
106 gpcStatus;
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);
125 return;
128 if (!mProperties.mAppVersionOverridden.IsEmpty()) {
129 aAppVersion = mProperties.mAppVersionOverridden;
130 return;
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);
147 return;
150 if (!mProperties.mPlatformOverridden.IsEmpty()) {
151 aPlatform = mProperties.mPlatformOverridden;
152 return;
156 aPlatform = mProperties.mPlatform;
159 namespace {
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 {
167 nsString& mUA;
168 bool mShouldResistFingerprinting;
170 public:
171 GetUserAgentRunnable(WorkerPrivate* aWorkerPrivate, nsString& aUA,
172 bool aShouldResistFingerprinting)
173 : WorkerMainThreadRunnable(aWorkerPrivate, "UserAgent getter"_ns),
174 mUA(aUA),
175 mShouldResistFingerprinting(aShouldResistFingerprinting) {
176 MOZ_ASSERT(aWorkerPrivate);
177 aWorkerPrivate->AssertIsOnWorkerThread();
180 virtual bool MainThreadRun() override {
181 AssertIsOnMainThread();
182 MOZ_ASSERT(mWorkerRef);
184 WorkerPrivate* workerPrivate = mWorkerRef->Private();
186 nsCOMPtr<nsPIDOMWindowInner> window = workerPrivate->GetWindow();
188 nsresult rv =
189 dom::Navigator::GetUserAgent(window, workerPrivate->GetDocument(),
190 Some(mShouldResistFingerprinting), mUA);
191 if (NS_FAILED(rv)) {
192 NS_WARNING("Failed to retrieve user-agent from the worker thread.");
195 return true;
199 } // namespace
201 void WorkerNavigator::GetUserAgent(nsString& aUserAgent, CallerType aCallerType,
202 ErrorResult& aRv) const {
203 WorkerPrivate* workerPrivate = GetCurrentThreadWorkerPrivate();
204 MOZ_ASSERT(workerPrivate);
206 RefPtr<GetUserAgentRunnable> runnable = new GetUserAgentRunnable(
207 workerPrivate, aUserAgent,
208 workerPrivate->ShouldResistFingerprinting(RFPTarget::NavigatorUserAgent));
210 runnable->Dispatch(workerPrivate, Canceling, aRv);
213 uint64_t WorkerNavigator::HardwareConcurrency() const {
214 RuntimeService* rts = RuntimeService::GetService();
215 MOZ_ASSERT(rts);
217 WorkerPrivate* aWorkerPrivate = GetCurrentThreadWorkerPrivate();
218 bool rfp = aWorkerPrivate->ShouldResistFingerprinting(
219 RFPTarget::NavigatorHWConcurrency);
221 return rts->ClampedHardwareConcurrency(rfp);
224 StorageManager* WorkerNavigator::Storage() {
225 if (!mStorageManager) {
226 WorkerPrivate* workerPrivate = GetCurrentThreadWorkerPrivate();
227 MOZ_ASSERT(workerPrivate);
229 RefPtr<nsIGlobalObject> global = workerPrivate->GlobalScope();
230 MOZ_ASSERT(global);
232 mStorageManager = new StorageManager(global);
234 workerPrivate->NotifyStorageKeyUsed();
237 return mStorageManager;
240 network::Connection* WorkerNavigator::GetConnection(ErrorResult& aRv) {
241 if (!mConnection) {
242 WorkerPrivate* workerPrivate = GetCurrentThreadWorkerPrivate();
243 MOZ_ASSERT(workerPrivate);
245 mConnection = network::Connection::CreateForWorker(workerPrivate, aRv);
248 return mConnection;
251 dom::MediaCapabilities* WorkerNavigator::MediaCapabilities() {
252 if (!mMediaCapabilities) {
253 WorkerPrivate* workerPrivate = GetCurrentThreadWorkerPrivate();
254 MOZ_ASSERT(workerPrivate);
256 nsIGlobalObject* global = workerPrivate->GlobalScope();
257 MOZ_ASSERT(global);
259 mMediaCapabilities = new dom::MediaCapabilities(global);
261 return mMediaCapabilities;
264 webgpu::Instance* WorkerNavigator::Gpu() {
265 if (!mWebGpu) {
266 WorkerPrivate* workerPrivate = GetCurrentThreadWorkerPrivate();
267 MOZ_ASSERT(workerPrivate);
269 nsIGlobalObject* global = workerPrivate->GlobalScope();
270 MOZ_ASSERT(global);
272 mWebGpu = webgpu::Instance::Create(global);
274 return mWebGpu;
277 dom::LockManager* WorkerNavigator::Locks() {
278 if (!mLocks) {
279 WorkerPrivate* workerPrivate = GetCurrentThreadWorkerPrivate();
280 MOZ_ASSERT(workerPrivate);
282 nsIGlobalObject* global = workerPrivate->GlobalScope();
283 MOZ_ASSERT(global);
285 mLocks = dom::LockManager::Create(*global);
287 return mLocks;
290 } // namespace mozilla::dom