Bug 1835710 - Cancel off-thread JIT compilation before changing nursery allocation...
[gecko.git] / dom / workers / WorkerNavigator.cpp
blobfc16071f74815460b167cb3cbda06e0277d4ae46
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 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);
109 return;
112 if (!mProperties.mAppNameOverridden.IsEmpty()) {
113 aAppName = mProperties.mAppNameOverridden;
114 return;
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);
132 return;
135 if (!mProperties.mAppVersionOverridden.IsEmpty()) {
136 aAppVersion = mProperties.mAppVersionOverridden;
137 return;
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);
154 return;
157 if (!mProperties.mPlatformOverridden.IsEmpty()) {
158 aPlatform = mProperties.mPlatformOverridden;
159 return;
163 aPlatform = mProperties.mPlatform;
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();
190 nsCOMPtr<nsPIDOMWindowInner> window = mWorkerPrivate->GetWindow();
192 nsresult rv =
193 dom::Navigator::GetUserAgent(window, mWorkerPrivate->GetDocument(),
194 Some(mShouldResistFingerprinting), mUA);
195 if (NS_FAILED(rv)) {
196 NS_WARNING("Failed to retrieve user-agent from the worker thread.");
199 return true;
203 } // namespace
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();
220 MOZ_ASSERT(rts);
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();
235 MOZ_ASSERT(global);
237 mStorageManager = new StorageManager(global);
240 return mStorageManager;
243 network::Connection* WorkerNavigator::GetConnection(ErrorResult& aRv) {
244 if (!mConnection) {
245 WorkerPrivate* workerPrivate = GetCurrentThreadWorkerPrivate();
246 MOZ_ASSERT(workerPrivate);
248 mConnection = network::Connection::CreateForWorker(workerPrivate, aRv);
251 return mConnection;
254 dom::MediaCapabilities* WorkerNavigator::MediaCapabilities() {
255 if (!mMediaCapabilities) {
256 WorkerPrivate* workerPrivate = GetCurrentThreadWorkerPrivate();
257 MOZ_ASSERT(workerPrivate);
259 nsIGlobalObject* global = workerPrivate->GlobalScope();
260 MOZ_ASSERT(global);
262 mMediaCapabilities = new dom::MediaCapabilities(global);
264 return mMediaCapabilities;
267 webgpu::Instance* WorkerNavigator::Gpu() {
268 if (!mWebGpu) {
269 WorkerPrivate* workerPrivate = GetCurrentThreadWorkerPrivate();
270 MOZ_ASSERT(workerPrivate);
272 nsIGlobalObject* global = workerPrivate->GlobalScope();
273 MOZ_ASSERT(global);
275 mWebGpu = webgpu::Instance::Create(global);
277 return mWebGpu;
280 dom::LockManager* WorkerNavigator::Locks() {
281 if (!mLocks) {
282 WorkerPrivate* workerPrivate = GetCurrentThreadWorkerPrivate();
283 MOZ_ASSERT(workerPrivate);
285 nsIGlobalObject* global = workerPrivate->GlobalScope();
286 MOZ_ASSERT(global);
288 mLocks = new dom::LockManager(global);
290 return mLocks;
293 } // namespace mozilla::dom