Backed out changeset 9d8b4c0b99ed (bug 1945683) for causing btime failures. CLOSED...
[gecko.git] / dom / workers / WorkerNavigator.cpp
blob1563d6ce19fc26523cdbe55aa3cb024feef2a3e6
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/Permissions.h"
20 #include "mozilla/dom/ServiceWorkerContainer.h"
21 #include "mozilla/dom/StorageManager.h"
22 #include "mozilla/dom/WorkerCommon.h"
23 #include "mozilla/dom/WorkerNavigatorBinding.h"
24 #include "mozilla/dom/WorkerStatus.h"
25 #include "mozilla/dom/network/Connection.h"
26 #include "mozilla/webgpu/Instance.h"
27 #include "nsCOMPtr.h"
28 #include "nsDebug.h"
29 #include "nsError.h"
30 #include "nsIGlobalObject.h"
31 #include "nsLiteralString.h"
32 #include "nsPIDOMWindow.h"
33 #include "nsRFPService.h"
34 #include "nsString.h"
36 class JSObject;
37 struct JSContext;
39 namespace mozilla::dom {
41 using namespace workerinternals;
43 NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_CLASS(WorkerNavigator)
44 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(WorkerNavigator)
45 tmp->Invalidate();
46 NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
47 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
49 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(WorkerNavigator)
50 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mStorageManager)
51 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mConnection)
52 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mMediaCapabilities)
53 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mWebGpu)
54 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mLocks)
55 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPermissions)
56 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mServiceWorkerContainer)
57 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
59 WorkerNavigator::WorkerNavigator(const NavigatorProperties& aProperties,
60 bool aOnline)
61 : mProperties(aProperties), mOnline(aOnline) {}
63 WorkerNavigator::~WorkerNavigator() { Invalidate(); }
65 /* static */
66 already_AddRefed<WorkerNavigator> WorkerNavigator::Create(bool aOnLine) {
67 RuntimeService* rts = RuntimeService::GetService();
68 MOZ_ASSERT(rts);
70 const RuntimeService::NavigatorProperties& properties =
71 rts->GetNavigatorProperties();
73 RefPtr<WorkerNavigator> navigator = new WorkerNavigator(properties, aOnLine);
75 return navigator.forget();
78 void WorkerNavigator::Invalidate() {
79 if (mStorageManager) {
80 mStorageManager->Shutdown();
81 mStorageManager = nullptr;
84 mConnection = nullptr;
86 mMediaCapabilities = nullptr;
88 mWebGpu = nullptr;
90 if (mLocks) {
91 mLocks->Shutdown();
92 mLocks = nullptr;
95 mPermissions = nullptr;
97 mServiceWorkerContainer = nullptr;
100 JSObject* WorkerNavigator::WrapObject(JSContext* aCx,
101 JS::Handle<JSObject*> aGivenProto) {
102 return WorkerNavigator_Binding::Wrap(aCx, this, aGivenProto);
105 bool WorkerNavigator::GlobalPrivacyControl() const {
106 bool gpcStatus = StaticPrefs::privacy_globalprivacycontrol_enabled();
107 if (!gpcStatus) {
108 JSObject* jso = GetWrapper();
109 if (const nsCOMPtr<nsIGlobalObject> global = xpc::NativeGlobal(jso)) {
110 if (const nsCOMPtr<nsIPrincipal> principal = global->PrincipalOrNull()) {
111 gpcStatus = principal->GetIsInPrivateBrowsing() &&
112 StaticPrefs::privacy_globalprivacycontrol_pbmode_enabled();
116 return StaticPrefs::privacy_globalprivacycontrol_functionality_enabled() &&
117 gpcStatus;
120 void WorkerNavigator::SetLanguages(const nsTArray<nsString>& aLanguages) {
121 WorkerNavigator_Binding::ClearCachedLanguagesValue(this);
122 mProperties.mLanguages = aLanguages.Clone();
125 void WorkerNavigator::GetAppVersion(nsString& aAppVersion,
126 CallerType aCallerType,
127 ErrorResult& aRv) const {
128 WorkerPrivate* workerPrivate = GetCurrentThreadWorkerPrivate();
129 MOZ_ASSERT(workerPrivate);
131 if (aCallerType != CallerType::System) {
132 if (workerPrivate->ShouldResistFingerprinting(
133 RFPTarget::NavigatorAppVersion)) {
134 // See nsRFPService.h for spoofed value.
135 aAppVersion.AssignLiteral(SPOOFED_APPVERSION);
136 return;
139 if (!mProperties.mAppVersionOverridden.IsEmpty()) {
140 aAppVersion = mProperties.mAppVersionOverridden;
141 return;
145 aAppVersion = mProperties.mAppVersion;
148 void WorkerNavigator::GetPlatform(nsString& aPlatform, CallerType aCallerType,
149 ErrorResult& aRv) const {
150 WorkerPrivate* workerPrivate = GetCurrentThreadWorkerPrivate();
151 MOZ_ASSERT(workerPrivate);
153 // navigator.platform is the same for default and spoofed values. The
154 // "general.platform.override" pref should override the default platform,
155 // but the spoofed platform should override the pref.
156 if (aCallerType == CallerType::System ||
157 workerPrivate->ShouldResistFingerprinting(RFPTarget::NavigatorPlatform) ||
158 mProperties.mPlatformOverridden.IsEmpty()) {
159 aPlatform = mProperties.mPlatform;
160 } else {
161 // from "general.platform.override" pref.
162 aPlatform = mProperties.mPlatformOverridden;
166 namespace {
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 {
174 nsString& mUA;
175 bool mShouldResistFingerprinting;
177 public:
178 GetUserAgentRunnable(WorkerPrivate* aWorkerPrivate, nsString& aUA,
179 bool aShouldResistFingerprinting)
180 : WorkerMainThreadRunnable(aWorkerPrivate, "UserAgent getter"_ns),
181 mUA(aUA),
182 mShouldResistFingerprinting(aShouldResistFingerprinting) {
183 MOZ_ASSERT(aWorkerPrivate);
184 aWorkerPrivate->AssertIsOnWorkerThread();
187 virtual bool MainThreadRun() override {
188 AssertIsOnMainThread();
189 MOZ_ASSERT(mWorkerRef);
191 WorkerPrivate* workerPrivate = mWorkerRef->Private();
193 nsCOMPtr<nsPIDOMWindowInner> window = workerPrivate->GetWindow();
195 nsresult rv =
196 dom::Navigator::GetUserAgent(window, workerPrivate->GetDocument(),
197 Some(mShouldResistFingerprinting), mUA);
198 if (NS_FAILED(rv)) {
199 NS_WARNING("Failed to retrieve user-agent from the worker thread.");
202 return true;
206 } // namespace
208 void WorkerNavigator::GetUserAgent(nsString& aUserAgent, CallerType aCallerType,
209 ErrorResult& aRv) const {
210 WorkerPrivate* workerPrivate = GetCurrentThreadWorkerPrivate();
211 MOZ_ASSERT(workerPrivate);
213 RefPtr<GetUserAgentRunnable> runnable = new GetUserAgentRunnable(
214 workerPrivate, aUserAgent,
215 workerPrivate->ShouldResistFingerprinting(RFPTarget::NavigatorUserAgent));
217 runnable->Dispatch(workerPrivate, Canceling, aRv);
220 uint64_t WorkerNavigator::HardwareConcurrency() const {
221 RuntimeService* rts = RuntimeService::GetService();
222 MOZ_ASSERT(rts);
224 WorkerPrivate* aWorkerPrivate = GetCurrentThreadWorkerPrivate();
225 bool rfp = aWorkerPrivate->ShouldResistFingerprinting(
226 RFPTarget::NavigatorHWConcurrency);
228 return rts->ClampedHardwareConcurrency(rfp);
231 StorageManager* WorkerNavigator::Storage() {
232 if (!mStorageManager) {
233 WorkerPrivate* workerPrivate = GetCurrentThreadWorkerPrivate();
234 MOZ_ASSERT(workerPrivate);
236 RefPtr<nsIGlobalObject> global = workerPrivate->GlobalScope();
237 MOZ_ASSERT(global);
239 mStorageManager = new StorageManager(global);
241 workerPrivate->NotifyStorageKeyUsed();
244 return mStorageManager;
247 network::Connection* WorkerNavigator::GetConnection(ErrorResult& aRv) {
248 if (!mConnection) {
249 WorkerPrivate* workerPrivate = GetCurrentThreadWorkerPrivate();
250 MOZ_ASSERT(workerPrivate);
252 mConnection = network::Connection::CreateForWorker(workerPrivate, aRv);
255 return mConnection;
258 dom::MediaCapabilities* WorkerNavigator::MediaCapabilities() {
259 if (!mMediaCapabilities) {
260 WorkerPrivate* workerPrivate = GetCurrentThreadWorkerPrivate();
261 MOZ_ASSERT(workerPrivate);
263 nsIGlobalObject* global = workerPrivate->GlobalScope();
264 MOZ_ASSERT(global);
266 mMediaCapabilities = new dom::MediaCapabilities(global);
268 return mMediaCapabilities;
271 webgpu::Instance* WorkerNavigator::Gpu() {
272 if (!mWebGpu) {
273 WorkerPrivate* workerPrivate = GetCurrentThreadWorkerPrivate();
274 MOZ_ASSERT(workerPrivate);
276 nsIGlobalObject* global = workerPrivate->GlobalScope();
277 MOZ_ASSERT(global);
279 mWebGpu = webgpu::Instance::Create(global);
281 return mWebGpu;
284 dom::LockManager* WorkerNavigator::Locks() {
285 if (!mLocks) {
286 WorkerPrivate* workerPrivate = GetCurrentThreadWorkerPrivate();
287 MOZ_ASSERT(workerPrivate);
289 nsIGlobalObject* global = workerPrivate->GlobalScope();
290 MOZ_ASSERT(global);
292 mLocks = dom::LockManager::Create(*global);
294 return mLocks;
297 dom::Permissions* WorkerNavigator::Permissions() {
298 if (!mPermissions) {
299 WorkerPrivate* workerPrivate = GetCurrentThreadWorkerPrivate();
300 MOZ_ASSERT(workerPrivate);
302 nsIGlobalObject* global = workerPrivate->GlobalScope();
303 MOZ_ASSERT(global);
304 mPermissions = new dom::Permissions(global);
307 return mPermissions;
310 already_AddRefed<ServiceWorkerContainer> WorkerNavigator::ServiceWorker() {
311 if (!mServiceWorkerContainer) {
312 WorkerPrivate* workerPrivate = GetCurrentThreadWorkerPrivate();
313 MOZ_ASSERT(workerPrivate);
315 nsIGlobalObject* global = workerPrivate->GlobalScope();
316 MOZ_ASSERT(global);
318 mServiceWorkerContainer = ServiceWorkerContainer::Create(global);
321 RefPtr<ServiceWorkerContainer> ref = mServiceWorkerContainer;
322 return ref.forget();
325 } // namespace mozilla::dom