Bug 1892041 - Part 1: Update test262 features. r=spidermonkey-reviewers,dminor
[gecko.git] / dom / workers / WorkerNavigator.cpp
blob1be36bc7d4ff812a964231770e3b988acc93b026
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->GetPrivateBrowsingId() > 0 &&
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();
183 nsCOMPtr<nsPIDOMWindowInner> window = mWorkerPrivate->GetWindow();
185 nsresult rv =
186 dom::Navigator::GetUserAgent(window, mWorkerPrivate->GetDocument(),
187 Some(mShouldResistFingerprinting), mUA);
188 if (NS_FAILED(rv)) {
189 NS_WARNING("Failed to retrieve user-agent from the worker thread.");
192 return true;
196 } // namespace
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();
212 MOZ_ASSERT(rts);
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();
227 MOZ_ASSERT(global);
229 mStorageManager = new StorageManager(global);
232 return mStorageManager;
235 network::Connection* WorkerNavigator::GetConnection(ErrorResult& aRv) {
236 if (!mConnection) {
237 WorkerPrivate* workerPrivate = GetCurrentThreadWorkerPrivate();
238 MOZ_ASSERT(workerPrivate);
240 mConnection = network::Connection::CreateForWorker(workerPrivate, aRv);
243 return mConnection;
246 dom::MediaCapabilities* WorkerNavigator::MediaCapabilities() {
247 if (!mMediaCapabilities) {
248 WorkerPrivate* workerPrivate = GetCurrentThreadWorkerPrivate();
249 MOZ_ASSERT(workerPrivate);
251 nsIGlobalObject* global = workerPrivate->GlobalScope();
252 MOZ_ASSERT(global);
254 mMediaCapabilities = new dom::MediaCapabilities(global);
256 return mMediaCapabilities;
259 webgpu::Instance* WorkerNavigator::Gpu() {
260 if (!mWebGpu) {
261 WorkerPrivate* workerPrivate = GetCurrentThreadWorkerPrivate();
262 MOZ_ASSERT(workerPrivate);
264 nsIGlobalObject* global = workerPrivate->GlobalScope();
265 MOZ_ASSERT(global);
267 mWebGpu = webgpu::Instance::Create(global);
269 return mWebGpu;
272 dom::LockManager* WorkerNavigator::Locks() {
273 if (!mLocks) {
274 WorkerPrivate* workerPrivate = GetCurrentThreadWorkerPrivate();
275 MOZ_ASSERT(workerPrivate);
277 nsIGlobalObject* global = workerPrivate->GlobalScope();
278 MOZ_ASSERT(global);
280 mLocks = dom::LockManager::Create(*global);
282 return mLocks;
285 } // namespace mozilla::dom