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/. */
8 #include "base/basictypes.h"
10 #include "Navigator.h"
11 #include "nsIXULAppInfo.h"
12 #include "nsPluginArray.h"
13 #include "nsMimeTypeArray.h"
14 #include "mozilla/Components.h"
15 #include "mozilla/ContentBlockingNotifier.h"
16 #include "mozilla/MemoryReporting.h"
17 #include "mozilla/dom/BodyExtractor.h"
18 #include "mozilla/dom/FetchBinding.h"
19 #include "mozilla/dom/File.h"
20 #include "Geolocation.h"
21 #include "nsIClassOfService.h"
22 #include "nsIHttpProtocolHandler.h"
23 #include "nsIContentPolicy.h"
24 #include "nsContentPolicyUtils.h"
25 #include "nsISupportsPriority.h"
26 #include "nsIWebProtocolHandlerRegistrar.h"
27 #include "nsCharSeparatedTokenizer.h"
28 #include "nsContentUtils.h"
29 #include "nsUnicharUtils.h"
30 #include "mozilla/Preferences.h"
31 #include "mozilla/StaticPrefs_dom.h"
33 # include "mozilla/StaticPrefs_fuzzing.h"
35 #include "mozilla/StaticPrefs_media.h"
36 #include "mozilla/StaticPrefs_network.h"
37 #include "mozilla/StaticPrefs_pdfjs.h"
38 #include "mozilla/StaticPrefs_privacy.h"
39 #include "mozilla/StorageAccess.h"
40 #include "mozilla/Telemetry.h"
41 #include "BatteryManager.h"
42 #include "mozilla/dom/CredentialsContainer.h"
43 #include "mozilla/dom/Clipboard.h"
44 #include "mozilla/dom/FeaturePolicyUtils.h"
45 #include "mozilla/dom/GamepadServiceTest.h"
46 #include "mozilla/dom/MediaCapabilities.h"
47 #include "mozilla/dom/MediaSession.h"
48 #include "mozilla/dom/power/PowerManagerService.h"
49 #include "mozilla/dom/LockManager.h"
50 #include "mozilla/dom/MIDIAccessManager.h"
51 #include "mozilla/dom/MIDIOptionsBinding.h"
52 #include "mozilla/dom/Permissions.h"
53 #include "mozilla/dom/ServiceWorkerContainer.h"
54 #include "mozilla/dom/StorageManager.h"
55 #include "mozilla/dom/TCPSocket.h"
56 #include "mozilla/dom/URLSearchParams.h"
57 #include "mozilla/dom/UserActivation.h"
58 #include "mozilla/dom/VRDisplay.h"
59 #include "mozilla/dom/VRDisplayEvent.h"
60 #include "mozilla/dom/VRServiceTest.h"
61 #include "mozilla/dom/XRSystem.h"
62 #include "mozilla/dom/workerinternals/RuntimeService.h"
63 #include "mozilla/dom/WakeLockJS.h"
64 #include "mozilla/Hal.h"
65 #include "mozilla/ClearOnShutdown.h"
66 #include "mozilla/StaticPtr.h"
67 #include "Connection.h"
68 #include "mozilla/dom/Event.h" // for Event
69 #include "nsGlobalWindowInner.h"
70 #include "nsIPermissionManager.h"
71 #include "nsMimeTypes.h"
72 #include "nsNetUtil.h"
73 #include "nsRFPService.h"
74 #include "nsStringStream.h"
75 #include "nsComponentManagerUtils.h"
76 #include "nsICookieManager.h"
77 #include "nsICookieService.h"
78 #include "nsIHttpChannel.h"
79 #ifdef ENABLE_WEBDRIVER
80 # include "nsIMarionette.h"
81 # include "nsIRemoteAgent.h"
83 #include "nsStreamUtils.h"
84 #include "WidgetUtils.h"
85 #include "nsIScriptError.h"
86 #include "ReferrerInfo.h"
87 #include "mozilla/PermissionDelegateHandler.h"
89 #include "nsIExternalProtocolHandler.h"
90 #include "BrowserChild.h"
91 #include "mozilla/ipc/URIUtils.h"
93 #include "mozilla/dom/MediaDevices.h"
94 #include "MediaManager.h"
96 #include "nsJSUtils.h"
98 #include "mozilla/dom/Promise.h"
100 #include "nsIUploadChannel2.h"
101 #include "mozilla/dom/FormData.h"
102 #include "nsIDocShell.h"
104 #include "mozilla/dom/WorkerPrivate.h"
105 #include "mozilla/dom/WorkerRunnable.h"
108 # include "mozilla/WindowsVersion.h"
111 #include "mozilla/EMEUtils.h"
112 #include "mozilla/DetailedPromise.h"
113 #include "mozilla/Unused.h"
115 #include "mozilla/webgpu/Instance.h"
116 #include "mozilla/dom/WindowGlobalChild.h"
118 #include "mozilla/intl/LocaleService.h"
119 #include "mozilla/dom/AudioContext.h"
120 #include "mozilla/dom/HTMLMediaElement.h"
121 #include "AutoplayPolicy.h"
123 namespace mozilla::dom
{
125 static const nsLiteralCString kVibrationPermissionType
= "vibration"_ns
;
127 Navigator::Navigator(nsPIDOMWindowInner
* aWindow
) : mWindow(aWindow
) {}
129 Navigator::~Navigator() { Invalidate(); }
131 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(Navigator
)
132 NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
133 NS_INTERFACE_MAP_ENTRY(nsISupports
)
136 NS_IMPL_CYCLE_COLLECTING_ADDREF(Navigator
)
137 NS_IMPL_CYCLE_COLLECTING_RELEASE(Navigator
)
139 NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_CLASS(Navigator
)
141 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(Navigator
)
143 NS_IMPL_CYCLE_COLLECTION_UNLINK(mWindow
)
144 NS_IMPL_CYCLE_COLLECTION_UNLINK(mSharePromise
)
145 NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
146 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
148 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(Navigator
)
149 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPlugins
)
150 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPermissions
)
151 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mGeolocation
)
152 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mBatteryManager
)
153 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mBatteryPromise
)
154 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mConnection
)
155 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mStorageManager
)
156 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mCredentials
)
157 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mMediaDevices
)
158 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mServiceWorkerContainer
)
159 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mMediaCapabilities
)
160 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mMediaSession
)
161 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mAddonManager
)
162 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mWebGpu
)
163 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mLocks
)
164 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mUserActivation
)
165 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mWakeLock
)
167 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mWindow
)
168 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mMediaKeySystemAccessManager
)
169 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mGamepadServiceTest
)
170 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mVRGetDisplaysPromises
)
171 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mVRServiceTest
)
172 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mSharePromise
)
173 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mXRSystem
)
174 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mClipboard
)
175 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
177 void Navigator::Invalidate() {
178 // Don't clear mWindow here so we know we've got a non-null mWindow
179 // until we're unlinked.
183 mPermissions
= nullptr;
185 if (mStorageManager
) {
186 mStorageManager
->Shutdown();
187 mStorageManager
= nullptr;
190 // If there is a page transition, make sure delete the geolocation object.
192 mGeolocation
->Shutdown();
193 mGeolocation
= nullptr;
196 if (mBatteryManager
) {
197 mBatteryManager
->Shutdown();
198 mBatteryManager
= nullptr;
201 mBatteryPromise
= nullptr;
204 mConnection
->Shutdown();
205 mConnection
= nullptr;
208 mMediaDevices
= nullptr;
210 mServiceWorkerContainer
= nullptr;
212 if (mMediaKeySystemAccessManager
) {
213 mMediaKeySystemAccessManager
->Shutdown();
214 mMediaKeySystemAccessManager
= nullptr;
217 if (mGamepadServiceTest
) {
218 mGamepadServiceTest
->Shutdown();
219 mGamepadServiceTest
= nullptr;
222 mVRGetDisplaysPromises
.Clear();
224 if (mVRServiceTest
) {
225 mVRServiceTest
->Shutdown();
226 mVRServiceTest
= nullptr;
230 mXRSystem
->Shutdown();
234 mMediaCapabilities
= nullptr;
237 mMediaSession
->Shutdown();
238 mMediaSession
= nullptr;
241 mAddonManager
= nullptr;
246 // Unloading a page does not immediately destruct the lock manager actor,
247 // but we want to abort the lock requests as soon as possible. Explicitly
248 // call Shutdown() to do that.
253 mUserActivation
= nullptr;
255 mSharePromise
= nullptr;
259 mClipboard
= nullptr;
262 void Navigator::GetUserAgent(nsAString
& aUserAgent
, CallerType aCallerType
,
263 ErrorResult
& aRv
) const {
264 nsCOMPtr
<nsPIDOMWindowInner
> window
;
268 nsIDocShell
* docshell
= window
->GetDocShell();
269 nsString customUserAgent
;
271 docshell
->GetBrowsingContext()->GetCustomUserAgent(customUserAgent
);
273 if (!customUserAgent
.IsEmpty()) {
274 aUserAgent
= customUserAgent
;
280 nsCOMPtr
<Document
> doc
= mWindow
->GetExtantDoc();
281 nsresult rv
= GetUserAgent(
282 mWindow
, doc
, aCallerType
== CallerType::System
? Some(false) : Nothing(),
284 if (NS_WARN_IF(NS_FAILED(rv
))) {
289 void Navigator::GetAppCodeName(nsAString
& aAppCodeName
, ErrorResult
& aRv
) {
292 nsCOMPtr
<nsIHttpProtocolHandler
> service(
293 do_GetService(NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX
"http", &rv
));
294 if (NS_WARN_IF(NS_FAILED(rv
))) {
299 nsAutoCString appName
;
300 rv
= service
->GetAppName(appName
);
301 if (NS_WARN_IF(NS_FAILED(rv
))) {
306 CopyASCIItoUTF16(appName
, aAppCodeName
);
309 void Navigator::GetAppVersion(nsAString
& aAppVersion
, CallerType aCallerType
,
310 ErrorResult
& aRv
) const {
311 nsCOMPtr
<Document
> doc
= mWindow
->GetExtantDoc();
313 nsresult rv
= GetAppVersion(
315 /* aUsePrefOverriddenValue = */ aCallerType
!= CallerType::System
);
316 if (NS_WARN_IF(NS_FAILED(rv
))) {
321 void Navigator::GetAppName(nsAString
& aAppName
) const {
322 aAppName
.AssignLiteral("Netscape");
326 * Returns the value of Accept-Languages (HTTP header) as a nsTArray of
327 * languages. The value is set in the preference by the user ("Content
330 * "en", "en-US" and "i-cherokee" and "" are valid languages tokens.
332 * If there is no valid language, the value of getWebExposedLocales is
333 * used to ensure that locale spoofing is honored and to reduce
336 * See RFC 7231, Section 9.7 "Browser Fingerprinting" and
337 * RFC 2616, Section 15.1.4 "Privacy Issues Connected to Accept Headers"
341 void Navigator::GetAcceptLanguages(nsTArray
<nsString
>& aLanguages
) {
342 MOZ_ASSERT(NS_IsMainThread());
346 // E.g. "de-de, en-us,en".
347 nsAutoString acceptLang
;
348 Preferences::GetLocalizedString("intl.accept_languages", acceptLang
);
350 // Split values on commas.
351 for (nsDependentSubstring lang
:
352 nsCharSeparatedTokenizer(acceptLang
, ',').ToRange()) {
353 // Replace "_" with "-" to avoid POSIX/Windows "en_US" notation.
354 // NOTE: we should probably rely on the pref being set correctly.
355 if (lang
.Length() > 2 && lang
[2] == char16_t('_')) {
356 lang
.Replace(2, 1, char16_t('-'));
359 // Use uppercase for country part, e.g. "en-US", not "en-us", see BCP47
360 // only uppercase 2-letter country codes, not "zh-Hant", "de-DE-x-goethe".
361 // NOTE: we should probably rely on the pref being set correctly.
362 if (lang
.Length() > 2) {
365 for (const nsAString
& code
:
366 nsCharSeparatedTokenizer(lang
, '-').ToRange()) {
367 if (code
.Length() == 2 && !first
) {
368 nsAutoString
upper(code
);
370 lang
.Replace(pos
, code
.Length(), upper
);
373 pos
+= code
.Length() + 1; // 1 is the separator
378 aLanguages
.AppendElement(lang
);
380 if (aLanguages
.Length() == 0) {
381 nsTArray
<nsCString
> locales
;
382 mozilla::intl::LocaleService::GetInstance()->GetWebExposedLocales(locales
);
383 aLanguages
.AppendElement(NS_ConvertUTF8toUTF16(locales
[0]));
388 * Returns the first language from GetAcceptLanguages.
390 * Full details above in GetAcceptLanguages.
392 void Navigator::GetLanguage(nsAString
& aLanguage
) {
393 nsTArray
<nsString
> languages
;
394 GetLanguages(languages
);
395 MOZ_ASSERT(languages
.Length() >= 1);
396 aLanguage
.Assign(languages
[0]);
399 void Navigator::GetLanguages(nsTArray
<nsString
>& aLanguages
) {
400 GetAcceptLanguages(aLanguages
);
402 // The returned value is cached by the binding code. The window listens to the
403 // accept languages change and will clear the cache when needed. It has to
404 // take care of dispatching the DOM event already and the invalidation and the
405 // event has to be timed correctly.
408 void Navigator::GetPlatform(nsAString
& aPlatform
, CallerType aCallerType
,
409 ErrorResult
& aRv
) const {
411 BrowsingContext
* bc
= mWindow
->GetBrowsingContext();
412 nsString customPlatform
;
414 bc
->GetCustomPlatform(customPlatform
);
416 if (!customPlatform
.IsEmpty()) {
417 aPlatform
= customPlatform
;
423 nsCOMPtr
<Document
> doc
= mWindow
->GetExtantDoc();
425 nsresult rv
= GetPlatform(
427 /* aUsePrefOverriddenValue = */ aCallerType
!= CallerType::System
);
428 if (NS_WARN_IF(NS_FAILED(rv
))) {
433 void Navigator::GetOscpu(nsAString
& aOSCPU
, CallerType aCallerType
,
434 ErrorResult
& aRv
) const {
435 if (aCallerType
!= CallerType::System
) {
436 // If fingerprinting resistance is on, we will spoof this value. See
437 // nsRFPService.h for details about spoofed values.
438 if (nsContentUtils::ShouldResistFingerprinting(GetDocShell(),
439 RFPTarget::NavigatorOscpu
)) {
440 aOSCPU
.AssignLiteral(SPOOFED_OSCPU
);
444 nsAutoString override
;
445 nsresult rv
= Preferences::GetString("general.oscpu.override", override
);
446 if (NS_SUCCEEDED(rv
)) {
453 nsCOMPtr
<nsIHttpProtocolHandler
> service(
454 do_GetService(NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX
"http", &rv
));
455 if (NS_WARN_IF(NS_FAILED(rv
))) {
461 rv
= service
->GetOscpu(oscpu
);
462 if (NS_WARN_IF(NS_FAILED(rv
))) {
467 CopyASCIItoUTF16(oscpu
, aOSCPU
);
470 void Navigator::GetVendor(nsAString
& aVendor
) { aVendor
.Truncate(); }
472 void Navigator::GetVendorSub(nsAString
& aVendorSub
) { aVendorSub
.Truncate(); }
474 void Navigator::GetProduct(nsAString
& aProduct
) {
475 aProduct
.AssignLiteral("Gecko");
478 void Navigator::GetProductSub(nsAString
& aProductSub
) {
479 // Legacy build date hardcoded for backward compatibility (bug 776376)
480 aProductSub
.AssignLiteral(LEGACY_UA_GECKO_TRAIL
);
483 nsMimeTypeArray
* Navigator::GetMimeTypes(ErrorResult
& aRv
) {
484 auto* plugins
= GetPlugins(aRv
);
489 return plugins
->MimeTypeArray();
492 nsPluginArray
* Navigator::GetPlugins(ErrorResult
& aRv
) {
495 aRv
.Throw(NS_ERROR_UNEXPECTED
);
498 mPlugins
= MakeRefPtr
<nsPluginArray
>(mWindow
);
504 bool Navigator::PdfViewerEnabled() { return !StaticPrefs::pdfjs_disabled(); }
506 Permissions
* Navigator::GetPermissions(ErrorResult
& aRv
) {
508 aRv
.Throw(NS_ERROR_UNEXPECTED
);
513 mPermissions
= new Permissions(mWindow
);
519 StorageManager
* Navigator::Storage() {
522 if (!mStorageManager
) {
523 mStorageManager
= new StorageManager(mWindow
->AsGlobal());
526 return mStorageManager
;
529 bool Navigator::CookieEnabled() {
530 // Check whether an exception overrides the global cookie behavior
531 // Note that the code for getting the URI here matches that in
532 // nsHTMLDocument::SetCookie.
533 if (!mWindow
|| !mWindow
->GetDocShell()) {
534 return nsICookieManager::GetCookieBehavior(false) !=
535 nsICookieService::BEHAVIOR_REJECT
;
538 nsCOMPtr
<nsILoadContext
> loadContext
= do_GetInterface(mWindow
);
539 uint32_t cookieBehavior
= loadContext
540 ? nsICookieManager::GetCookieBehavior(
541 loadContext
->UsePrivateBrowsing())
542 : nsICookieManager::GetCookieBehavior(false);
543 bool cookieEnabled
= cookieBehavior
!= nsICookieService::BEHAVIOR_REJECT
;
545 nsCOMPtr
<Document
> doc
= mWindow
->GetExtantDoc();
547 return cookieEnabled
;
550 uint32_t rejectedReason
= 0;
551 bool granted
= false;
552 nsresult rv
= doc
->NodePrincipal()->HasFirstpartyStorageAccess(
553 mWindow
, &rejectedReason
, &granted
);
555 // Not a content, so technically can't set cookies, but let's
556 // just return the default value.
557 return cookieEnabled
;
560 // We should return true if the cookie is partitioned because the cookie is
561 // still available in this case.
563 StoragePartitioningEnabled(rejectedReason
, doc
->CookieJarSettings())) {
567 ContentBlockingNotifier::OnDecision(
569 granted
? ContentBlockingNotifier::BlockingDecision::eAllow
570 : ContentBlockingNotifier::BlockingDecision::eBlock
,
575 bool Navigator::OnLine() {
577 // Check if this tab is set to be offline.
578 BrowsingContext
* bc
= mWindow
->GetBrowsingContext();
579 if (bc
&& bc
->Top()->GetForceOffline()) {
583 // Return the default browser value
584 return !NS_IsOffline();
587 void Navigator::GetBuildID(nsAString
& aBuildID
, CallerType aCallerType
,
588 ErrorResult
& aRv
) const {
589 if (aCallerType
!= CallerType::System
) {
590 // If fingerprinting resistance is on, we will spoof this value. See
591 // nsRFPService.h for details about spoofed values.
592 if (nsContentUtils::ShouldResistFingerprinting(
593 GetDocShell(), RFPTarget::NavigatorBuildID
)) {
594 aBuildID
.AssignLiteral(LEGACY_BUILD_ID
);
598 nsAutoString override
;
599 nsresult rv
= Preferences::GetString("general.buildID.override", override
);
600 if (NS_SUCCEEDED(rv
)) {
606 bool isHTTPS
= false;
608 nsCOMPtr
<Document
> doc
= mWindow
->GetDoc();
610 nsIURI
* uri
= doc
->GetDocumentURI();
612 isHTTPS
= uri
->SchemeIs("https");
614 MOZ_ALWAYS_SUCCEEDS(uri
->GetHost(host
));
620 // Spoof the buildID on pages not loaded from "https://*.mozilla.org".
621 if (!isHTTPS
|| !StringEndsWith(host
, ".mozilla.org"_ns
)) {
622 aBuildID
.AssignLiteral(LEGACY_BUILD_ID
);
627 nsCOMPtr
<nsIXULAppInfo
> appInfo
=
628 do_GetService("@mozilla.org/xre/app-info;1");
630 aRv
.Throw(NS_ERROR_NOT_IMPLEMENTED
);
634 nsAutoCString buildID
;
635 nsresult rv
= appInfo
->GetAppBuildID(buildID
);
636 if (NS_WARN_IF(NS_FAILED(rv
))) {
642 AppendASCIItoUTF16(buildID
, aBuildID
);
645 void Navigator::GetDoNotTrack(nsAString
& aResult
) {
646 bool doNotTrack
= StaticPrefs::privacy_donottrackheader_enabled();
648 nsCOMPtr
<nsILoadContext
> loadContext
= do_GetInterface(mWindow
);
649 doNotTrack
= loadContext
&& loadContext
->UseTrackingProtection();
653 aResult
.AssignLiteral("1");
655 aResult
.AssignLiteral("unspecified");
659 bool Navigator::GlobalPrivacyControl() {
660 bool gpcStatus
= StaticPrefs::privacy_globalprivacycontrol_enabled();
662 nsCOMPtr
<nsILoadContext
> loadContext
= do_GetInterface(mWindow
);
663 gpcStatus
= loadContext
&& loadContext
->UsePrivateBrowsing() &&
664 StaticPrefs::privacy_globalprivacycontrol_pbmode_enabled();
666 return StaticPrefs::privacy_globalprivacycontrol_functionality_enabled() &&
670 uint64_t Navigator::HardwareConcurrency() {
671 workerinternals::RuntimeService
* rts
=
672 workerinternals::RuntimeService::GetOrCreateService();
677 return rts
->ClampedHardwareConcurrency(
678 nsGlobalWindowInner::Cast(mWindow
)->ShouldResistFingerprinting(
679 RFPTarget::NavigatorHWConcurrency
));
684 class VibrateWindowListener
: public nsIDOMEventListener
{
686 VibrateWindowListener(nsPIDOMWindowInner
* aWindow
, Document
* aDocument
)
687 : mWindow(do_GetWeakReference(aWindow
)), mDocument(aDocument
) {
688 constexpr auto visibilitychange
= u
"visibilitychange"_ns
;
689 aDocument
->AddSystemEventListener(visibilitychange
, this, /* listener */
690 true, /* use capture */
691 false /* wants untrusted */);
694 void RemoveListener();
697 NS_DECL_NSIDOMEVENTLISTENER
700 virtual ~VibrateWindowListener() = default;
703 WeakPtr
<Document
> mDocument
;
706 NS_IMPL_ISUPPORTS(VibrateWindowListener
, nsIDOMEventListener
)
708 StaticRefPtr
<VibrateWindowListener
> gVibrateWindowListener
;
710 static bool MayVibrate(Document
* doc
) {
711 // Hidden documents cannot start or stop a vibration.
712 return (doc
&& !doc
->Hidden());
716 VibrateWindowListener::HandleEvent(Event
* aEvent
) {
717 nsCOMPtr
<Document
> doc
= do_QueryInterface(aEvent
->GetTarget());
719 if (!MayVibrate(doc
)) {
720 // It's important that we call CancelVibrate(), not Vibrate() with an
721 // empty list, because Vibrate() will fail if we're no longer focused, but
722 // CancelVibrate() will succeed, so long as nobody else has started a new
723 // vibration pattern.
724 nsCOMPtr
<nsPIDOMWindowInner
> window
= do_QueryReferent(mWindow
);
725 hal::CancelVibrate(window
);
727 gVibrateWindowListener
= nullptr;
728 // Careful: The line above might have deleted |this|!
734 void VibrateWindowListener::RemoveListener() {
735 nsCOMPtr
<Document
> target(mDocument
);
739 constexpr auto visibilitychange
= u
"visibilitychange"_ns
;
740 target
->RemoveSystemEventListener(visibilitychange
, this,
741 true /* use capture */);
746 void Navigator::SetVibrationPermission(bool aPermitted
, bool aPersistent
) {
747 MOZ_ASSERT(NS_IsMainThread());
749 nsTArray
<uint32_t> pattern
= std::move(mRequestedVibrationPattern
);
755 nsCOMPtr
<Document
> doc
= mWindow
->GetExtantDoc();
757 if (!MayVibrate(doc
)) {
762 // Add a listener to cancel the vibration if the document becomes hidden,
763 // and remove the old visibility listener, if there was one.
764 if (!gVibrateWindowListener
) {
765 // If gVibrateWindowListener is null, this is the first time we've
766 // vibrated, and we need to register a listener to clear
767 // gVibrateWindowListener on shutdown.
768 ClearOnShutdown(&gVibrateWindowListener
);
770 gVibrateWindowListener
->RemoveListener();
772 gVibrateWindowListener
= new VibrateWindowListener(mWindow
, doc
);
773 hal::Vibrate(pattern
, mWindow
);
777 nsCOMPtr
<nsIPermissionManager
> permMgr
=
778 components::PermissionManager::Service();
782 permMgr
->AddFromPrincipal(doc
->NodePrincipal(), kVibrationPermissionType
,
783 aPermitted
? nsIPermissionManager::ALLOW_ACTION
784 : nsIPermissionManager::DENY_ACTION
,
785 nsIPermissionManager::EXPIRE_SESSION
, 0);
789 bool Navigator::Vibrate(uint32_t aDuration
) {
790 AutoTArray
<uint32_t, 1> pattern
;
791 pattern
.AppendElement(aDuration
);
792 return Vibrate(pattern
);
795 nsTArray
<uint32_t> SanitizeVibratePattern(const nsTArray
<uint32_t>& aPattern
) {
796 nsTArray
<uint32_t> pattern(aPattern
.Clone());
798 if (pattern
.Length() > StaticPrefs::dom_vibrator_max_vibrate_list_len()) {
799 pattern
.SetLength(StaticPrefs::dom_vibrator_max_vibrate_list_len());
802 for (size_t i
= 0; i
< pattern
.Length(); ++i
) {
804 std::min(StaticPrefs::dom_vibrator_max_vibrate_ms(), pattern
[i
]);
810 bool Navigator::Vibrate(const nsTArray
<uint32_t>& aPattern
) {
811 MOZ_ASSERT(NS_IsMainThread());
817 nsCOMPtr
<Document
> doc
= mWindow
->GetExtantDoc();
819 if (!MayVibrate(doc
)) {
823 nsTArray
<uint32_t> pattern
= SanitizeVibratePattern(aPattern
);
825 // The spec says we check dom.vibrator.enabled after we've done the sanity
826 // checking on the pattern.
827 if (!StaticPrefs::dom_vibrator_enabled()) {
831 mRequestedVibrationPattern
= std::move(pattern
);
833 PermissionDelegateHandler
* permissionHandler
=
834 doc
->GetPermissionDelegateHandler();
835 if (NS_WARN_IF(!permissionHandler
)) {
839 uint32_t permission
= nsIPermissionManager::UNKNOWN_ACTION
;
841 permissionHandler
->GetPermission(kVibrationPermissionType
, &permission
,
844 if (permission
== nsIPermissionManager::DENY_ACTION
) {
845 // Abort without observer service or on denied session permission.
846 SetVibrationPermission(false /* permitted */, false /* persistent */);
850 if (permission
== nsIPermissionManager::ALLOW_ACTION
||
851 mRequestedVibrationPattern
.IsEmpty() ||
852 (mRequestedVibrationPattern
.Length() == 1 &&
853 mRequestedVibrationPattern
[0] == 0)) {
854 // Always allow cancelling vibration and respect session permissions.
855 SetVibrationPermission(true /* permitted */, false /* persistent */);
859 // Request user permission.
860 nsCOMPtr
<nsIObserverService
> obs
= services::GetObserverService();
865 obs
->NotifyObservers(ToSupports(this), "Vibration:Request", nullptr);
870 //*****************************************************************************
871 // Pointer Events interface
872 //*****************************************************************************
874 uint32_t Navigator::MaxTouchPoints(CallerType aCallerType
) {
875 nsIDocShell
* docshell
= GetDocShell();
876 BrowsingContext
* bc
= docshell
? docshell
->GetBrowsingContext() : nullptr;
878 // Responsive Design Mode overrides the maxTouchPoints property when
879 // touch simulation is enabled.
880 if (bc
&& bc
->InRDMPane()) {
881 return bc
->GetMaxTouchPointsOverride();
884 // The maxTouchPoints is going to reveal the detail of users' hardware. So,
885 // we will spoof it into 0 if fingerprinting resistance is on.
886 if (aCallerType
!= CallerType::System
&&
887 nsContentUtils::ShouldResistFingerprinting(GetDocShell(),
888 RFPTarget::PointerEvents
)) {
892 nsCOMPtr
<nsIWidget
> widget
=
893 widget::WidgetUtils::DOMWindowToWidget(mWindow
->GetOuterWindow());
895 NS_ENSURE_TRUE(widget
, 0);
896 return widget
->GetMaxTouchPoints();
899 //*****************************************************************************
900 // Navigator::nsIDOMClientInformation
901 //*****************************************************************************
903 // This list should be kept up-to-date with the spec:
904 // https://html.spec.whatwg.org/multipage/system-state.html#custom-handlers
905 // If you change this list, please also update the copy in E10SUtils.sys.mjs.
906 static const char* const kSafeSchemes
[] = {
935 void Navigator::CheckProtocolHandlerAllowed(const nsAString
& aScheme
,
937 nsIURI
* aDocumentURI
,
939 auto raisePermissionDeniedHandler
= [&] {
941 aHandlerURI
->GetSpec(spec
);
942 nsPrintfCString
message("Permission denied to add %s as a protocol handler",
944 aRv
.ThrowSecurityError(message
);
947 auto raisePermissionDeniedScheme
= [&] {
948 nsPrintfCString
message(
949 "Permission denied to add a protocol handler for %s",
950 NS_ConvertUTF16toUTF8(aScheme
).get());
951 aRv
.ThrowSecurityError(message
);
954 if (!aDocumentURI
|| !aHandlerURI
) {
955 aRv
.Throw(NS_ERROR_DOM_SYNTAX_ERR
);
960 aHandlerURI
->GetSpec(spec
);
961 // If the uri doesn't contain '%s', it won't be a good handler - the %s
962 // gets replaced with the handled URI.
963 if (!FindInReadable("%s"_ns
, spec
)) {
964 aRv
.ThrowSyntaxError("Handler URI does not contain \"%s\".");
968 // For security reasons we reject non-http(s) urls (see bug 354316),
969 nsAutoCString docScheme
;
970 nsAutoCString handlerScheme
;
971 aDocumentURI
->GetScheme(docScheme
);
972 aHandlerURI
->GetScheme(handlerScheme
);
973 if ((!docScheme
.EqualsLiteral("https") && !docScheme
.EqualsLiteral("http")) ||
974 (!handlerScheme
.EqualsLiteral("https") &&
975 !handlerScheme
.EqualsLiteral("http"))) {
976 raisePermissionDeniedHandler();
980 // Should be same-origin:
981 nsAutoCString handlerHost
;
982 aHandlerURI
->GetHostPort(handlerHost
);
983 nsAutoCString documentHost
;
984 aDocumentURI
->GetHostPort(documentHost
);
985 if (!handlerHost
.Equals(documentHost
) || !handlerScheme
.Equals(docScheme
)) {
986 raisePermissionDeniedHandler();
990 // Having checked the handler URI, check the scheme:
991 nsAutoCString scheme
;
992 ToLowerCase(NS_ConvertUTF16toUTF8(aScheme
), scheme
);
993 if (StringBeginsWith(scheme
, "web+"_ns
)) {
994 // Check for non-ascii
995 nsReadingIterator
<char> iter
;
996 nsReadingIterator
<char> iterEnd
;
997 auto remainingScheme
= Substring(scheme
, 4 /* web+ */);
998 remainingScheme
.BeginReading(iter
);
999 remainingScheme
.EndReading(iterEnd
);
1000 // Scheme suffix must be non-empty
1001 if (iter
== iterEnd
) {
1002 raisePermissionDeniedScheme();
1005 for (; iter
!= iterEnd
; iter
++) {
1006 if (*iter
< 'a' || *iter
> 'z') {
1007 raisePermissionDeniedScheme();
1012 bool matches
= false;
1013 for (const char* safeScheme
: kSafeSchemes
) {
1014 if (scheme
.Equals(safeScheme
)) {
1020 raisePermissionDeniedScheme();
1025 nsCOMPtr
<nsIProtocolHandler
> handler
;
1026 nsCOMPtr
<nsIIOService
> io
= components::IO::Service();
1028 io
->GetProtocolHandler(scheme
.get(), getter_AddRefs(handler
)))) {
1029 raisePermissionDeniedScheme();
1033 // check if we have prefs set saying not to add this.
1034 bool defaultExternal
=
1035 Preferences::GetBool("network.protocol-handler.external-default");
1036 nsPrintfCString
specificPref("network.protocol-handler.external.%s",
1038 if (!Preferences::GetBool(specificPref
.get(), defaultExternal
)) {
1039 raisePermissionDeniedScheme();
1043 // Check to make sure this isn't already handled internally (we don't
1044 // want to let them take over, say "chrome"). In theory, the checks above
1045 // should have already taken care of this.
1046 nsCOMPtr
<nsIExternalProtocolHandler
> externalHandler
=
1047 do_QueryInterface(handler
);
1050 "We should never allow overriding a builtin protocol handler");
1053 void Navigator::RegisterProtocolHandler(const nsAString
& aScheme
,
1054 const nsAString
& aURI
,
1056 if (!mWindow
|| !mWindow
->GetOuterWindow() || !mWindow
->GetDocShell() ||
1057 !mWindow
->GetDoc()) {
1060 nsCOMPtr
<nsILoadContext
> loadContext
= do_GetInterface(mWindow
);
1061 if (loadContext
->UsePrivateBrowsing()) {
1062 // If we're a private window, don't alert the user or webpage. We log to the
1063 // console so that web developers have some way to tell what's going wrong.
1064 nsContentUtils::ReportToConsole(
1065 nsIScriptError::warningFlag
, "DOM"_ns
, mWindow
->GetDoc(),
1066 nsContentUtils::eDOM_PROPERTIES
,
1067 "RegisterProtocolHandlerPrivateBrowsingWarning");
1071 nsCOMPtr
<Document
> doc
= mWindow
->GetDoc();
1073 // Determine if doc is allowed to assign this handler
1074 nsIURI
* docURI
= doc
->GetDocumentURIObject();
1075 nsCOMPtr
<nsIURI
> handlerURI
;
1076 NS_NewURI(getter_AddRefs(handlerURI
), NS_ConvertUTF16toUTF8(aURI
),
1077 doc
->GetDocumentCharacterSet(), docURI
);
1078 CheckProtocolHandlerAllowed(aScheme
, handlerURI
, docURI
, aRv
);
1083 // Determine a title from the document URI.
1084 nsAutoCString docDisplayHostPort
;
1085 docURI
->GetDisplayHostPort(docDisplayHostPort
);
1086 NS_ConvertASCIItoUTF16
title(docDisplayHostPort
);
1088 if (XRE_IsContentProcess()) {
1089 nsAutoString
scheme(aScheme
);
1090 RefPtr
<BrowserChild
> browserChild
= BrowserChild::GetFrom(mWindow
);
1091 browserChild
->SendRegisterProtocolHandler(scheme
, handlerURI
, title
,
1096 nsCOMPtr
<nsIWebProtocolHandlerRegistrar
> registrar
=
1097 do_GetService(NS_WEBPROTOCOLHANDLERREGISTRAR_CONTRACTID
);
1099 aRv
= registrar
->RegisterProtocolHandler(aScheme
, handlerURI
, title
, docURI
,
1100 mWindow
->GetOuterWindow());
1104 Geolocation
* Navigator::GetGeolocation(ErrorResult
& aRv
) {
1106 return mGeolocation
;
1109 if (!mWindow
|| !mWindow
->GetOuterWindow() || !mWindow
->GetDocShell()) {
1110 aRv
.Throw(NS_ERROR_FAILURE
);
1114 mGeolocation
= new Geolocation();
1115 if (NS_FAILED(mGeolocation
->Init(mWindow
))) {
1116 mGeolocation
= nullptr;
1117 aRv
.Throw(NS_ERROR_FAILURE
);
1121 return mGeolocation
;
1124 class BeaconStreamListener final
: public nsIStreamListener
{
1125 ~BeaconStreamListener() = default;
1128 BeaconStreamListener() : mLoadGroup(nullptr) {}
1130 void SetLoadGroup(nsILoadGroup
* aLoadGroup
) { mLoadGroup
= aLoadGroup
; }
1133 NS_DECL_NSISTREAMLISTENER
1134 NS_DECL_NSIREQUESTOBSERVER
1137 nsCOMPtr
<nsILoadGroup
> mLoadGroup
;
1140 NS_IMPL_ISUPPORTS(BeaconStreamListener
, nsIStreamListener
, nsIRequestObserver
)
1143 BeaconStreamListener::OnStartRequest(nsIRequest
* aRequest
) {
1144 // release the loadgroup first
1145 mLoadGroup
= nullptr;
1147 return NS_ERROR_ABORT
;
1151 BeaconStreamListener::OnStopRequest(nsIRequest
* aRequest
, nsresult aStatus
) {
1156 BeaconStreamListener::OnDataAvailable(nsIRequest
* aRequest
,
1157 nsIInputStream
* inStr
,
1158 uint64_t sourceOffset
, uint32_t count
) {
1163 bool Navigator::SendBeacon(const nsAString
& aUrl
,
1164 const Nullable
<fetch::BodyInit
>& aData
,
1166 if (aData
.IsNull()) {
1167 return SendBeaconInternal(aUrl
, nullptr, eBeaconTypeOther
, aRv
);
1170 if (aData
.Value().IsArrayBuffer()) {
1171 BodyExtractor
<const ArrayBuffer
> body(&aData
.Value().GetAsArrayBuffer());
1172 return SendBeaconInternal(aUrl
, &body
, eBeaconTypeArrayBuffer
, aRv
);
1175 if (aData
.Value().IsArrayBufferView()) {
1176 BodyExtractor
<const ArrayBufferView
> body(
1177 &aData
.Value().GetAsArrayBufferView());
1178 return SendBeaconInternal(aUrl
, &body
, eBeaconTypeArrayBuffer
, aRv
);
1181 if (aData
.Value().IsBlob()) {
1182 BodyExtractor
<const Blob
> body(&aData
.Value().GetAsBlob());
1183 return SendBeaconInternal(aUrl
, &body
, eBeaconTypeBlob
, aRv
);
1186 if (aData
.Value().IsFormData()) {
1187 BodyExtractor
<const FormData
> body(&aData
.Value().GetAsFormData());
1188 return SendBeaconInternal(aUrl
, &body
, eBeaconTypeOther
, aRv
);
1191 if (aData
.Value().IsUSVString()) {
1192 BodyExtractor
<const nsAString
> body(&aData
.Value().GetAsUSVString());
1193 return SendBeaconInternal(aUrl
, &body
, eBeaconTypeOther
, aRv
);
1196 if (aData
.Value().IsURLSearchParams()) {
1197 BodyExtractor
<const URLSearchParams
> body(
1198 &aData
.Value().GetAsURLSearchParams());
1199 return SendBeaconInternal(aUrl
, &body
, eBeaconTypeOther
, aRv
);
1202 MOZ_CRASH("Invalid data type.");
1206 bool Navigator::SendBeaconInternal(const nsAString
& aUrl
,
1207 BodyExtractorBase
* aBody
, BeaconType aType
,
1210 aRv
.Throw(NS_ERROR_DOM_INVALID_STATE_ERR
);
1214 nsCOMPtr
<Document
> doc
= mWindow
->GetDoc();
1216 aRv
.Throw(NS_ERROR_DOM_INVALID_STATE_ERR
);
1220 nsIURI
* documentURI
= doc
->GetDocumentURI();
1222 aRv
.Throw(NS_ERROR_DOM_INVALID_STATE_ERR
);
1226 nsCOMPtr
<nsIURI
> uri
;
1227 nsresult rv
= nsContentUtils::NewURIWithDocumentCharset(
1228 getter_AddRefs(uri
), aUrl
, doc
, doc
->GetDocBaseURI());
1229 if (NS_FAILED(rv
)) {
1230 aRv
.ThrowTypeError
<MSG_INVALID_URL
>(NS_ConvertUTF16toUTF8(aUrl
));
1234 // Spec disallows any schemes save for HTTP/HTTPs
1235 if (!uri
->SchemeIs("http") && !uri
->SchemeIs("https")) {
1236 aRv
.ThrowTypeError
<MSG_INVALID_URL_SCHEME
>("Beacon",
1237 uri
->GetSpecOrDefault());
1241 nsCOMPtr
<nsIInputStream
> in
;
1242 nsAutoCString contentTypeWithCharset
;
1243 nsAutoCString charset
;
1244 uint64_t length
= 0;
1246 aRv
= aBody
->GetAsStream(getter_AddRefs(in
), &length
,
1247 contentTypeWithCharset
, charset
);
1248 if (NS_WARN_IF(aRv
.Failed())) {
1253 nsSecurityFlags securityFlags
= nsILoadInfo::SEC_COOKIES_INCLUDE
;
1254 // Ensure that only streams with content types that are safelisted ignore CORS
1256 if (aBody
&& !contentTypeWithCharset
.IsVoid() &&
1257 !nsContentUtils::IsCORSSafelistedRequestHeader("content-type"_ns
,
1258 contentTypeWithCharset
)) {
1259 securityFlags
|= nsILoadInfo::SEC_REQUIRE_CORS_INHERITS_SEC_CONTEXT
;
1261 securityFlags
|= nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_INHERITS_SEC_CONTEXT
;
1264 nsCOMPtr
<nsIChannel
> channel
;
1265 rv
= NS_NewChannel(getter_AddRefs(channel
), uri
, doc
, securityFlags
,
1266 nsIContentPolicy::TYPE_BEACON
);
1268 if (NS_FAILED(rv
)) {
1273 nsCOMPtr
<nsIHttpChannel
> httpChannel
= do_QueryInterface(channel
);
1275 // Beacon spec only supports HTTP requests at this time
1276 aRv
.Throw(NS_ERROR_DOM_BAD_URI
);
1280 auto referrerInfo
= MakeRefPtr
<ReferrerInfo
>(*doc
);
1281 rv
= httpChannel
->SetReferrerInfoWithoutClone(referrerInfo
);
1282 MOZ_ASSERT(NS_SUCCEEDED(rv
));
1285 nsCOMPtr
<nsIUploadChannel2
> uploadChannel
= do_QueryInterface(channel
);
1286 if (!uploadChannel
) {
1287 aRv
.Throw(NS_ERROR_FAILURE
);
1291 uploadChannel
->ExplicitSetUploadStream(in
, contentTypeWithCharset
, length
,
1294 rv
= httpChannel
->SetRequestMethod("POST"_ns
);
1295 MOZ_ASSERT(NS_SUCCEEDED(rv
));
1298 nsCOMPtr
<nsISupportsPriority
> p
= do_QueryInterface(channel
);
1300 p
->SetPriority(nsISupportsPriority::PRIORITY_LOWEST
);
1303 nsCOMPtr
<nsIClassOfService
> cos(do_QueryInterface(channel
));
1305 cos
->AddClassFlags(nsIClassOfService::Background
);
1308 // The channel needs to have a loadgroup associated with it, so that we can
1309 // cancel the channel and any redirected channels it may create.
1310 nsCOMPtr
<nsILoadGroup
> loadGroup
= do_CreateInstance(NS_LOADGROUP_CONTRACTID
);
1311 nsCOMPtr
<nsIInterfaceRequestor
> callbacks
=
1312 do_QueryInterface(mWindow
->GetDocShell());
1313 loadGroup
->SetNotificationCallbacks(callbacks
);
1314 channel
->SetLoadGroup(loadGroup
);
1316 RefPtr
<BeaconStreamListener
> beaconListener
= new BeaconStreamListener();
1317 rv
= channel
->AsyncOpen(beaconListener
);
1318 // do not throw if security checks fail within asyncOpen
1319 NS_ENSURE_SUCCESS(rv
, false);
1321 // make the beaconListener hold a strong reference to the loadgroup
1322 // which is released in ::OnStartRequest
1323 beaconListener
->SetLoadGroup(loadGroup
);
1328 MediaDevices
* Navigator::GetMediaDevices(ErrorResult
& aRv
) {
1329 if (!mMediaDevices
) {
1330 if (!mWindow
|| !mWindow
->GetOuterWindow() ||
1331 mWindow
->GetOuterWindow()->GetCurrentInnerWindow() != mWindow
) {
1332 aRv
.Throw(NS_ERROR_NOT_AVAILABLE
);
1335 mMediaDevices
= new MediaDevices(mWindow
);
1337 return mMediaDevices
;
1340 void Navigator::MozGetUserMedia(const MediaStreamConstraints
& aConstraints
,
1341 NavigatorUserMediaSuccessCallback
& aOnSuccess
,
1342 NavigatorUserMediaErrorCallback
& aOnError
,
1343 CallerType aCallerType
, ErrorResult
& aRv
) {
1344 MOZ_ASSERT(NS_IsMainThread());
1345 if (!mWindow
|| !mWindow
->IsFullyActive()) {
1346 aRv
.ThrowInvalidStateError("The document is not fully active.");
1349 GetMediaDevices(aRv
);
1353 MOZ_ASSERT(mMediaDevices
);
1354 if (Document
* doc
= mWindow
->GetExtantDoc()) {
1355 if (!mWindow
->IsSecureContext()) {
1356 doc
->SetUseCounter(eUseCounter_custom_MozGetUserMediaInsec
);
1359 RefPtr
<MediaManager::StreamPromise
> sp
;
1360 if (!MediaManager::IsOn(aConstraints
.mVideo
) &&
1361 !MediaManager::IsOn(aConstraints
.mAudio
)) {
1362 sp
= MediaManager::StreamPromise::CreateAndReject(
1363 MakeRefPtr
<MediaMgrError
>(MediaMgrError::Name::TypeError
,
1364 "audio and/or video is required"),
1367 sp
= mMediaDevices
->GetUserMedia(mWindow
, aConstraints
, aCallerType
);
1369 RefPtr
<NavigatorUserMediaSuccessCallback
> onsuccess(&aOnSuccess
);
1370 RefPtr
<NavigatorUserMediaErrorCallback
> onerror(&aOnError
);
1372 nsWeakPtr weakWindow
= nsWeakPtr(do_GetWeakReference(mWindow
));
1374 GetMainThreadSerialEventTarget(), __func__
,
1375 [weakWindow
, onsuccess
= std::move(onsuccess
)](
1376 const RefPtr
<DOMMediaStream
>& aStream
) MOZ_CAN_RUN_SCRIPT
{
1377 nsCOMPtr
<nsPIDOMWindowInner
> window
= do_QueryReferent(weakWindow
);
1378 if (!window
|| !window
->GetOuterWindow() ||
1379 window
->GetOuterWindow()->GetCurrentInnerWindow() != window
) {
1380 return; // Leave Promise pending after navigation by design.
1382 MediaManager::CallOnSuccess(*onsuccess
, *aStream
);
1384 [weakWindow
, onerror
= std::move(onerror
)](
1385 const RefPtr
<MediaMgrError
>& aError
) MOZ_CAN_RUN_SCRIPT
{
1386 nsCOMPtr
<nsPIDOMWindowInner
> window
= do_QueryReferent(weakWindow
);
1387 if (!window
|| !window
->GetOuterWindow() ||
1388 window
->GetOuterWindow()->GetCurrentInnerWindow() != window
) {
1389 return; // Leave Promise pending after navigation by design.
1391 auto error
= MakeRefPtr
<MediaStreamError
>(window
, *aError
);
1392 MediaManager::CallOnError(*onerror
, *error
);
1396 //*****************************************************************************
1397 // Navigator::nsINavigatorBattery
1398 //*****************************************************************************
1400 Promise
* Navigator::GetBattery(ErrorResult
& aRv
) {
1401 if (mBatteryPromise
) {
1402 return mBatteryPromise
;
1405 if (!mWindow
|| !mWindow
->GetDocShell()) {
1406 aRv
.Throw(NS_ERROR_UNEXPECTED
);
1410 RefPtr
<Promise
> batteryPromise
= Promise::Create(mWindow
->AsGlobal(), aRv
);
1411 if (NS_WARN_IF(aRv
.Failed())) {
1414 mBatteryPromise
= batteryPromise
;
1416 if (!mBatteryManager
) {
1417 mBatteryManager
= new battery::BatteryManager(mWindow
);
1418 mBatteryManager
->Init();
1421 mBatteryPromise
->MaybeResolve(mBatteryManager
);
1423 return mBatteryPromise
;
1426 //*****************************************************************************
1427 // Navigator::Share() - Web Share API
1428 //*****************************************************************************
1430 already_AddRefed
<Promise
> Navigator::Share(const ShareData
& aData
,
1432 if (!mWindow
|| !mWindow
->IsFullyActive()) {
1433 aRv
.ThrowInvalidStateError("The document is not fully active.");
1437 if (NS_WARN_IF(!mWindow
->GetDocShell() || !mWindow
->GetExtantDoc())) {
1438 aRv
.Throw(NS_ERROR_UNEXPECTED
);
1442 if (!FeaturePolicyUtils::IsFeatureAllowed(mWindow
->GetExtantDoc(),
1444 aRv
.ThrowNotAllowedError(
1445 "Document's Permissions Policy does not allow calling "
1446 "share() from this context.");
1450 if (mSharePromise
) {
1451 NS_WARNING("Only one share picker at a time per navigator instance");
1452 aRv
.Throw(NS_ERROR_DOM_INVALID_STATE_ERR
);
1456 // null checked above
1457 Document
* doc
= mWindow
->GetExtantDoc();
1459 if (StaticPrefs::dom_webshare_requireinteraction() &&
1460 !doc
->ConsumeTransientUserGestureActivation()) {
1461 aRv
.ThrowNotAllowedError(
1462 "User activation was already consumed "
1463 "or share() was not activated by a user gesture.");
1467 ValidateShareData(aData
, aRv
);
1473 // TODO: Process file member, which we don't currently support.
1475 // If data's url member is present, try to resolve it...
1476 nsCOMPtr
<nsIURI
> url
;
1477 if (aData
.mUrl
.WasPassed()) {
1478 auto result
= doc
->ResolveWithBaseURI(aData
.mUrl
.Value());
1479 url
= result
.unwrap();
1483 // Process the title member...
1485 if (aData
.mTitle
.WasPassed()) {
1486 title
.Assign(NS_ConvertUTF16toUTF8(aData
.mTitle
.Value()));
1488 title
.SetIsVoid(true);
1491 // Process the text member...
1493 if (aData
.mText
.WasPassed()) {
1494 text
.Assign(NS_ConvertUTF16toUTF8(aData
.mText
.Value()));
1496 text
.SetIsVoid(true);
1499 // Let mSharePromise be a new promise.
1500 mSharePromise
= Promise::Create(mWindow
->AsGlobal(), aRv
);
1505 IPCWebShareData
data(title
, text
, url
);
1506 auto wgc
= mWindow
->GetWindowGlobalChild();
1508 aRv
.Throw(NS_ERROR_FAILURE
);
1513 wgc
->SendShare(data
)->Then(
1514 GetCurrentSerialEventTarget(), __func__
,
1515 [self
= RefPtr
{this}](
1516 PWindowGlobalChild::SharePromise::ResolveOrRejectValue
&& aResult
) {
1517 if (aResult
.IsResolve()) {
1518 if (NS_SUCCEEDED(aResult
.ResolveValue())) {
1519 self
->mSharePromise
->MaybeResolveWithUndefined();
1521 self
->mSharePromise
->MaybeReject(aResult
.ResolveValue());
1523 } else if (self
->mSharePromise
) {
1525 self
->mSharePromise
->MaybeReject(NS_BINDING_ABORTED
);
1527 self
->mSharePromise
= nullptr;
1529 return do_AddRef(mSharePromise
);
1532 //*****************************************************************************
1533 // Navigator::CanShare() - Web Share API
1534 //*****************************************************************************
1535 bool Navigator::CanShare(const ShareData
& aData
) {
1536 if (!mWindow
|| !mWindow
->IsFullyActive()) {
1540 if (!FeaturePolicyUtils::IsFeatureAllowed(mWindow
->GetExtantDoc(),
1545 IgnoredErrorResult rv
;
1546 ValidateShareData(aData
, rv
);
1547 return !rv
.Failed();
1550 void Navigator::ValidateShareData(const ShareData
& aData
, ErrorResult
& aRv
) {
1551 // TODO: remove this check when we support files share.
1552 if (aData
.mFiles
.WasPassed() && !aData
.mFiles
.Value().IsEmpty()) {
1553 aRv
.ThrowTypeError("Passing files is currently not supported.");
1557 bool titleTextOrUrlPassed
= aData
.mTitle
.WasPassed() ||
1558 aData
.mText
.WasPassed() || aData
.mUrl
.WasPassed();
1560 // At least one member must be present.
1561 if (!titleTextOrUrlPassed
) {
1563 "Must have a title, text, or url member in the ShareData dictionary");
1567 // If data's url member is present, try to resolve it...
1568 nsCOMPtr
<nsIURI
> url
;
1569 if (aData
.mUrl
.WasPassed()) {
1570 Document
* doc
= mWindow
->GetExtantDoc();
1571 Result
<OwningNonNull
<nsIURI
>, nsresult
> result
=
1572 doc
->ResolveWithBaseURI(aData
.mUrl
.Value());
1573 if (NS_WARN_IF(result
.isErr())) {
1574 aRv
.ThrowTypeError
<MSG_INVALID_URL
>(
1575 NS_ConvertUTF16toUTF8(aData
.mUrl
.Value()));
1578 url
= result
.unwrap();
1579 // Check that we only share loadable URLs (e.g., http/https).
1580 // we also exclude blobs, as it doesn't make sense to share those outside
1581 // the context of the browser.
1582 const uint32_t flags
=
1583 nsIScriptSecurityManager::DISALLOW_INHERIT_PRINCIPAL
|
1584 nsIScriptSecurityManager::DISALLOW_SCRIPT
;
1586 nsContentUtils::GetSecurityManager()->CheckLoadURIWithPrincipal(
1587 doc
->NodePrincipal(), url
, flags
, doc
->InnerWindowID())) ||
1588 url
->SchemeIs("blob")) {
1589 aRv
.ThrowTypeError
<MSG_INVALID_URL_SCHEME
>("Share",
1590 url
->GetSpecOrDefault());
1596 static bool ShouldResistFingerprinting(const Document
* aDoc
,
1597 RFPTarget aTarget
) {
1598 return aDoc
? aDoc
->ShouldResistFingerprinting(aTarget
)
1599 : nsContentUtils::ShouldResistFingerprinting("Fallback", aTarget
);
1602 already_AddRefed
<LegacyMozTCPSocket
> Navigator::MozTCPSocket() {
1603 RefPtr
<LegacyMozTCPSocket
> socket
= new LegacyMozTCPSocket(GetWindow());
1604 return socket
.forget();
1607 void Navigator::GetGamepads(nsTArray
<RefPtr
<Gamepad
>>& aGamepads
,
1609 if (!mWindow
|| !mWindow
->IsFullyActive()) {
1612 NS_ENSURE_TRUE_VOID(mWindow
->GetDocShell());
1613 nsGlobalWindowInner
* win
= nsGlobalWindowInner::Cast(mWindow
);
1615 if (!FeaturePolicyUtils::IsFeatureAllowed(win
->GetExtantDoc(),
1617 aRv
.ThrowSecurityError(
1618 "Document's Permission Policy does not allow calling "
1619 "getGamepads() from this context.");
1623 win
->SetHasGamepadEventListener(true);
1624 win
->GetGamepads(aGamepads
);
1627 GamepadServiceTest
* Navigator::RequestGamepadServiceTest(ErrorResult
& aRv
) {
1629 if (!StaticPrefs::fuzzing_enabled()) {
1630 aRv
.Throw(NS_ERROR_UNEXPECTED
);
1634 if (!xpc::IsInAutomation()) {
1635 aRv
.Throw(NS_ERROR_UNEXPECTED
);
1640 if (!mGamepadServiceTest
) {
1641 mGamepadServiceTest
= GamepadServiceTest::CreateTestService(mWindow
);
1643 return mGamepadServiceTest
;
1646 already_AddRefed
<Promise
> Navigator::GetVRDisplays(ErrorResult
& aRv
) {
1647 if (!mWindow
|| !mWindow
->GetDocShell() || !mWindow
->GetExtantDoc()) {
1648 aRv
.Throw(NS_ERROR_UNEXPECTED
);
1652 if (!FeaturePolicyUtils::IsFeatureAllowed(mWindow
->GetExtantDoc(),
1654 aRv
.Throw(NS_ERROR_DOM_SECURITY_ERR
);
1658 RefPtr
<Promise
> p
= Promise::Create(mWindow
->AsGlobal(), aRv
);
1663 RefPtr
<BrowserChild
> browser(BrowserChild::GetFrom(mWindow
));
1665 MOZ_ASSERT(XRE_IsParentProcess());
1666 FinishGetVRDisplays(true, p
);
1668 RefPtr
<Navigator
> self(this);
1669 int browserID
= browser
->ChromeOuterWindowID();
1671 browser
->SendIsWindowSupportingWebVR(browserID
)->Then(
1672 GetCurrentSerialEventTarget(), __func__
,
1673 [self
, p
](bool isSupported
) {
1674 self
->FinishGetVRDisplays(isSupported
, p
);
1676 [p
](const mozilla::ipc::ResponseRejectReason
) {
1677 p
->MaybeRejectWithTypeError("Unable to start display enumeration");
1684 void Navigator::FinishGetVRDisplays(bool isWebVRSupportedInwindow
, Promise
* p
) {
1685 if (!isWebVRSupportedInwindow
) {
1686 // WebVR in this window is not supported, so resolve the promise
1687 // with no displays available
1688 nsTArray
<RefPtr
<VRDisplay
>> vrDisplaysEmpty
;
1689 p
->MaybeResolve(vrDisplaysEmpty
);
1693 // Since FinishGetVRDisplays can be called asynchronously after an IPC
1694 // response, it's possible that the Window can be torn down before this
1695 // call. In that case, the Window's cyclic references to VR objects are
1696 // also torn down and should not be recreated via
1697 // NotifyHasXRSession.
1698 nsGlobalWindowInner
* win
= nsGlobalWindowInner::Cast(mWindow
);
1699 if (win
->IsDying()) {
1700 // The Window has been torn down, so there is no further work that can
1702 p
->MaybeRejectWithTypeError(
1703 "Unable to return VRDisplays for a closed window.");
1707 mVRGetDisplaysPromises
.AppendElement(p
);
1708 win
->RequestXRPermission();
1711 void Navigator::OnXRPermissionRequestAllow() {
1712 // The permission request that results in this callback could have
1713 // been instantiated by WebVR, WebXR, or both.
1714 nsGlobalWindowInner
* win
= nsGlobalWindowInner::Cast(mWindow
);
1715 bool usingWebXR
= false;
1718 usingWebXR
= mXRSystem
->OnXRPermissionRequestAllow();
1721 bool rejectWebVR
= true;
1722 // If WebVR and WebXR both requested permission, only grant it to
1723 // WebXR, which takes priority.
1725 // We pass mWindow's id to RefreshVRDisplays, so NotifyVRDisplaysUpdated
1726 // will be called asynchronously, resolving the promises in
1727 // mVRGetDisplaysPromises.
1728 rejectWebVR
= !VRDisplay::RefreshVRDisplays(win
->WindowID());
1730 // Even if WebXR took priority, reject requests for WebVR in case they were
1731 // made simultaneously and coelesced into a single permission prompt.
1733 for (auto& p
: mVRGetDisplaysPromises
) {
1734 // Failed to refresh, reject the promise now
1735 p
->MaybeRejectWithTypeError("Failed to find attached VR displays.");
1737 mVRGetDisplaysPromises
.Clear();
1741 void Navigator::OnXRPermissionRequestCancel() {
1743 mXRSystem
->OnXRPermissionRequestCancel();
1746 nsTArray
<RefPtr
<VRDisplay
>> vrDisplays
;
1747 for (auto& p
: mVRGetDisplaysPromises
) {
1748 // Resolve the promise with no vr displays when
1749 // the user blocks access.
1750 p
->MaybeResolve(vrDisplays
);
1752 mVRGetDisplaysPromises
.Clear();
1755 void Navigator::GetActiveVRDisplays(
1756 nsTArray
<RefPtr
<VRDisplay
>>& aDisplays
) const {
1758 * Get only the active VR displays.
1759 * GetActiveVRDisplays should only enumerate displays that
1760 * are already active without causing any other hardware to be
1762 * We must not call nsGlobalWindowInner::NotifyHasXRSession here,
1763 * as that would cause enumeration and activation of other VR hardware.
1764 * Activating VR hardware is intrusive to the end user, as it may
1765 * involve physically powering on devices that the user did not
1768 if (!mWindow
|| !mWindow
->GetDocShell()) {
1771 nsGlobalWindowInner
* win
= nsGlobalWindowInner::Cast(mWindow
);
1772 nsTArray
<RefPtr
<VRDisplay
>> displays
;
1773 if (win
->UpdateVRDisplays(displays
)) {
1774 for (auto display
: displays
) {
1775 if (display
->IsPresenting()) {
1776 aDisplays
.AppendElement(display
);
1782 void Navigator::NotifyVRDisplaysUpdated() {
1783 // Synchronize the VR devices and resolve the promises in
1784 // mVRGetDisplaysPromises
1785 nsGlobalWindowInner
* win
= nsGlobalWindowInner::Cast(mWindow
);
1787 nsTArray
<RefPtr
<VRDisplay
>> vrDisplays
;
1788 if (win
->UpdateVRDisplays(vrDisplays
)) {
1789 for (auto p
: mVRGetDisplaysPromises
) {
1790 p
->MaybeResolve(vrDisplays
);
1793 for (auto p
: mVRGetDisplaysPromises
) {
1794 p
->MaybeReject(NS_ERROR_FAILURE
);
1797 mVRGetDisplaysPromises
.Clear();
1800 void Navigator::NotifyActiveVRDisplaysChanged() {
1801 Navigator_Binding::ClearCachedActiveVRDisplaysValue(this);
1804 VRServiceTest
* Navigator::RequestVRServiceTest(ErrorResult
& aRv
) {
1805 if (!xpc::IsInAutomation()) {
1806 aRv
.Throw(NS_ERROR_UNEXPECTED
);
1810 // Ensure that the Mock VR devices are not released prematurely
1811 nsGlobalWindowInner
* win
= nsGlobalWindowInner::Cast(mWindow
);
1812 win
->NotifyHasXRSession();
1814 if (!mVRServiceTest
) {
1815 mVRServiceTest
= VRServiceTest::CreateTestService(mWindow
);
1817 return mVRServiceTest
;
1820 XRSystem
* Navigator::GetXr(ErrorResult
& aRv
) {
1822 aRv
.Throw(NS_ERROR_UNEXPECTED
);
1826 mXRSystem
= XRSystem::Create(mWindow
);
1831 bool Navigator::IsWebVRContentDetected() const {
1832 nsGlobalWindowInner
* win
= nsGlobalWindowInner::Cast(mWindow
);
1833 return win
->IsVRContentDetected();
1836 bool Navigator::IsWebVRContentPresenting() const {
1837 nsGlobalWindowInner
* win
= nsGlobalWindowInner::Cast(mWindow
);
1838 return win
->IsVRContentPresenting();
1841 void Navigator::RequestVRPresentation(VRDisplay
& aDisplay
) {
1842 nsGlobalWindowInner
* win
= nsGlobalWindowInner::Cast(mWindow
);
1843 win
->DispatchVRDisplayActivate(aDisplay
.DisplayId(),
1844 VRDisplayEventReason::Requested
);
1847 already_AddRefed
<Promise
> Navigator::RequestMIDIAccess(
1848 const MIDIOptions
& aOptions
, ErrorResult
& aRv
) {
1850 aRv
.Throw(NS_ERROR_UNEXPECTED
);
1853 MIDIAccessManager
* accessMgr
= MIDIAccessManager::Get();
1854 return accessMgr
->RequestMIDIAccess(mWindow
, aOptions
, aRv
);
1857 network::Connection
* Navigator::GetConnection(ErrorResult
& aRv
) {
1860 aRv
.Throw(NS_ERROR_UNEXPECTED
);
1863 mConnection
= network::Connection::CreateForWindow(
1864 mWindow
, nsGlobalWindowInner::Cast(mWindow
)->ShouldResistFingerprinting(
1865 RFPTarget::NavigatorConnection
));
1871 already_AddRefed
<ServiceWorkerContainer
> Navigator::ServiceWorker() {
1872 MOZ_ASSERT(mWindow
);
1874 if (!mServiceWorkerContainer
) {
1875 mServiceWorkerContainer
=
1876 ServiceWorkerContainer::Create(mWindow
->AsGlobal());
1879 RefPtr
<ServiceWorkerContainer
> ref
= mServiceWorkerContainer
;
1880 return ref
.forget();
1883 already_AddRefed
<ServiceWorkerContainer
> Navigator::ServiceWorkerJS() {
1884 if (mWindow
->AsGlobal()->GetStorageAccess() ==
1885 StorageAccess::ePrivateBrowsing
) {
1886 SetUseCounter(mWindow
->AsGlobal()->GetGlobalJSObject(),
1887 eUseCounter_custom_PrivateBrowsingNavigatorServiceWorker
);
1890 return ServiceWorker();
1893 size_t Navigator::SizeOfIncludingThis(
1894 mozilla::MallocSizeOf aMallocSizeOf
) const {
1895 size_t n
= aMallocSizeOf(this);
1897 // TODO: add SizeOfIncludingThis() to nsMimeTypeArray, bug 674113.
1898 // TODO: add SizeOfIncludingThis() to nsPluginArray, bug 674114.
1899 // TODO: add SizeOfIncludingThis() to Geolocation, bug 674115.
1900 // TODO: add SizeOfIncludingThis() to DesktopNotificationCenter, bug 674116.
1905 void Navigator::OnNavigation() {
1910 // If MediaManager is open let it inform any live streams or pending callbacks
1911 MediaManager
* manager
= MediaManager::GetIfExists();
1913 manager
->OnNavigation(mWindow
->WindowID());
1917 JSObject
* Navigator::WrapObject(JSContext
* cx
,
1918 JS::Handle
<JSObject
*> aGivenProto
) {
1919 return Navigator_Binding::Wrap(cx
, this, aGivenProto
);
1923 bool Navigator::HasUserMediaSupport(JSContext
* cx
, JSObject
* obj
) {
1924 // Make enabling peerconnection enable getUserMedia() as well.
1925 // Emulate [SecureContext] unless media.devices.insecure.enabled=true
1926 return (StaticPrefs::media_navigator_enabled() ||
1927 StaticPrefs::media_peerconnection_enabled()) &&
1928 (IsSecureContextOrObjectIsFromSecureContext(cx
, obj
) ||
1929 StaticPrefs::media_devices_insecure_enabled());
1933 bool Navigator::HasShareSupport(JSContext
* cx
, JSObject
* obj
) {
1934 if (!StaticPrefs::dom_webshare_enabled()) {
1937 #if defined(XP_WIN) && !defined(__MINGW32__)
1938 // The first public build that supports ShareCanceled API
1939 return IsWindows10BuildOrLater(18956);
1946 bool Navigator::HasMidiSupport(JSContext
* cx
, JSObject
* obj
) {
1947 nsIPrincipal
* principal
= nsContentUtils::SubjectPrincipal(cx
);
1949 // Enable on secure contexts but exclude file schemes.
1950 return StaticPrefs::dom_webmidi_enabled() &&
1951 IsSecureContextOrObjectIsFromSecureContext(cx
, obj
) &&
1952 !principal
->SchemeIs("file");
1956 already_AddRefed
<nsPIDOMWindowInner
> Navigator::GetWindowFromGlobal(
1957 JSObject
* aGlobal
) {
1958 nsCOMPtr
<nsPIDOMWindowInner
> win
= xpc::WindowOrNull(aGlobal
);
1959 return win
.forget();
1962 void Navigator::ClearPlatformCache() {
1963 Navigator_Binding::ClearCachedPlatformValue(this);
1966 nsresult
Navigator::GetPlatform(nsAString
& aPlatform
, Document
* aCallerDoc
,
1967 bool aUsePrefOverriddenValue
) {
1968 MOZ_ASSERT(NS_IsMainThread());
1970 if (aUsePrefOverriddenValue
) {
1971 // If fingerprinting resistance is on, we will spoof this value. See
1972 // nsRFPService.h for details about spoofed values.
1973 if (ShouldResistFingerprinting(aCallerDoc
, RFPTarget::NavigatorPlatform
)) {
1974 aPlatform
.AssignLiteral(SPOOFED_PLATFORM
);
1977 nsAutoString override
;
1979 mozilla::Preferences::GetString("general.platform.override", override
);
1981 if (NS_SUCCEEDED(rv
)) {
1982 aPlatform
= override
;
1988 aPlatform
.AssignLiteral("Win32");
1989 #elif defined(XP_MACOSX)
1990 // Always return "MacIntel", even on ARM64 macOS like Safari does.
1991 aPlatform
.AssignLiteral("MacIntel");
1994 nsCOMPtr
<nsIHttpProtocolHandler
> service(
1995 do_GetService(NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX
"http", &rv
));
1996 NS_ENSURE_SUCCESS(rv
, rv
);
1999 rv
= service
->GetOscpu(plat
);
2000 NS_ENSURE_SUCCESS(rv
, rv
);
2002 CopyASCIItoUTF16(plat
, aPlatform
);
2009 nsresult
Navigator::GetAppVersion(nsAString
& aAppVersion
, Document
* aCallerDoc
,
2010 bool aUsePrefOverriddenValue
) {
2011 MOZ_ASSERT(NS_IsMainThread());
2013 if (aUsePrefOverriddenValue
) {
2014 // If fingerprinting resistance is on, we will spoof this value. See
2015 // nsRFPService.h for details about spoofed values.
2016 if (ShouldResistFingerprinting(aCallerDoc
,
2017 RFPTarget::NavigatorAppVersion
)) {
2018 aAppVersion
.AssignLiteral(SPOOFED_APPVERSION
);
2021 nsAutoString override
;
2022 nsresult rv
= mozilla::Preferences::GetString("general.appversion.override",
2025 if (NS_SUCCEEDED(rv
)) {
2026 aAppVersion
= override
;
2033 nsCOMPtr
<nsIHttpProtocolHandler
> service(
2034 do_GetService(NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX
"http", &rv
));
2035 NS_ENSURE_SUCCESS(rv
, rv
);
2038 rv
= service
->GetAppVersion(str
);
2039 CopyASCIItoUTF16(str
, aAppVersion
);
2040 NS_ENSURE_SUCCESS(rv
, rv
);
2042 aAppVersion
.AppendLiteral(" (");
2044 rv
= service
->GetPlatform(str
);
2045 NS_ENSURE_SUCCESS(rv
, rv
);
2047 AppendASCIItoUTF16(str
, aAppVersion
);
2048 aAppVersion
.Append(char16_t(')'));
2053 void Navigator::ClearUserAgentCache() {
2054 Navigator_Binding::ClearCachedUserAgentValue(this);
2057 nsresult
Navigator::GetUserAgent(nsPIDOMWindowInner
* aWindow
,
2058 Document
* aCallerDoc
,
2059 Maybe
<bool> aShouldResistFingerprinting
,
2060 nsAString
& aUserAgent
) {
2061 MOZ_ASSERT(NS_IsMainThread());
2064 ResistFingerprinting is migrating to fine-grained control based off
2065 either a channel or Principal+OriginAttributes
2067 This function can be called from Workers, Main Thread, and at least one
2068 other (unusual) case.
2070 For Main Thread, we will generally have a window and an associated
2071 Document, for Workers we will not.
2073 If aShouldResistFingerprinting is provided, we should respect it.
2074 If it is not provided, we will use aCallerDoc to determine our behavior.
2077 bool shouldResistFingerprinting
=
2078 aShouldResistFingerprinting
.isSome()
2079 ? aShouldResistFingerprinting
.value()
2080 : ShouldResistFingerprinting(aCallerDoc
,
2081 RFPTarget::NavigatorUserAgent
);
2083 // We will skip the override and pass to httpHandler to get spoofed userAgent
2084 // when 'privacy.resistFingerprinting' is true.
2085 if (!shouldResistFingerprinting
) {
2086 nsAutoString override
;
2088 mozilla::Preferences::GetString("general.useragent.override", override
);
2090 if (NS_SUCCEEDED(rv
)) {
2091 aUserAgent
= override
;
2096 // When the caller is content and 'privacy.resistFingerprinting' is true,
2097 // return a spoofed userAgent which reveals the platform but not the
2098 // specific OS version, etc.
2099 if (shouldResistFingerprinting
) {
2100 nsAutoCString spoofedUA
;
2101 nsRFPService::GetSpoofedUserAgent(spoofedUA
, false);
2102 CopyASCIItoUTF16(spoofedUA
, aUserAgent
);
2107 nsCOMPtr
<nsIHttpProtocolHandler
> service(
2108 do_GetService(NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX
"http", &rv
));
2109 if (NS_WARN_IF(NS_FAILED(rv
))) {
2114 rv
= service
->GetUserAgent(ua
);
2115 if (NS_WARN_IF(NS_FAILED(rv
))) {
2119 CopyASCIItoUTF16(ua
, aUserAgent
);
2125 // Copy the User-Agent header from the document channel which has already been
2126 // subject to UA overrides.
2127 nsCOMPtr
<Document
> doc
= aWindow
->GetExtantDoc();
2131 nsCOMPtr
<nsIHttpChannel
> httpChannel
= do_QueryInterface(doc
->GetChannel());
2133 nsAutoCString userAgent
;
2134 rv
= httpChannel
->GetRequestHeader("User-Agent"_ns
, userAgent
);
2135 if (NS_WARN_IF(NS_FAILED(rv
))) {
2138 CopyASCIItoUTF16(userAgent
, aUserAgent
);
2143 static nsCString
RequestKeySystemAccessLogString(
2144 const nsAString
& aKeySystem
,
2145 const Sequence
<MediaKeySystemConfiguration
>& aConfigs
,
2146 bool aIsSecureContext
) {
2149 "Navigator::RequestMediaKeySystemAccess(keySystem='%s' options=",
2150 NS_ConvertUTF16toUTF8(aKeySystem
).get());
2151 str
.Append(MediaKeySystemAccess::ToCString(aConfigs
));
2152 str
.AppendLiteral(") secureContext=");
2153 str
.AppendInt(aIsSecureContext
);
2157 already_AddRefed
<Promise
> Navigator::RequestMediaKeySystemAccess(
2158 const nsAString
& aKeySystem
,
2159 const Sequence
<MediaKeySystemConfiguration
>& aConfigs
, ErrorResult
& aRv
) {
2160 EME_LOG("%s", RequestKeySystemAccessLogString(aKeySystem
, aConfigs
,
2161 mWindow
->IsSecureContext())
2164 if (!mWindow
->IsSecureContext()) {
2165 Document
* doc
= mWindow
->GetExtantDoc();
2166 AutoTArray
<nsString
, 1> params
;
2167 nsString
* uri
= params
.AppendElement();
2169 Unused
<< doc
->GetDocumentURI(*uri
);
2171 nsContentUtils::ReportToConsole(nsIScriptError::warningFlag
, "Media"_ns
,
2172 doc
, nsContentUtils::eDOM_PROPERTIES
,
2173 "MediaEMEInsecureContextDeprecatedWarning",
2177 Document
* doc
= mWindow
->GetExtantDoc();
2179 !FeaturePolicyUtils::IsFeatureAllowed(doc
, u
"encrypted-media"_ns
)) {
2180 aRv
.Throw(NS_ERROR_DOM_SECURITY_ERR
);
2184 RefPtr
<DetailedPromise
> promise
= DetailedPromise::Create(
2185 mWindow
->AsGlobal(), aRv
, "navigator.requestMediaKeySystemAccess"_ns
);
2190 if (!mMediaKeySystemAccessManager
) {
2191 mMediaKeySystemAccessManager
= new MediaKeySystemAccessManager(mWindow
);
2194 mMediaKeySystemAccessManager
->Request(promise
, aKeySystem
, aConfigs
);
2195 return promise
.forget();
2198 CredentialsContainer
* Navigator::Credentials() {
2199 if (!mCredentials
) {
2200 mCredentials
= new CredentialsContainer(GetWindow());
2202 return mCredentials
;
2205 dom::MediaCapabilities
* Navigator::MediaCapabilities() {
2206 if (!mMediaCapabilities
) {
2207 mMediaCapabilities
= new dom::MediaCapabilities(GetWindow()->AsGlobal());
2209 return mMediaCapabilities
;
2212 dom::MediaSession
* Navigator::MediaSession() {
2213 if (!mMediaSession
) {
2214 mMediaSession
= new dom::MediaSession(GetWindow());
2216 return mMediaSession
;
2219 bool Navigator::HasCreatedMediaSession() const {
2220 return mMediaSession
!= nullptr;
2223 Clipboard
* Navigator::Clipboard() {
2225 mClipboard
= new dom::Clipboard(GetWindow());
2230 AddonManager
* Navigator::GetMozAddonManager(ErrorResult
& aRv
) {
2231 if (!mAddonManager
) {
2232 nsPIDOMWindowInner
* win
= GetWindow();
2234 aRv
.Throw(NS_ERROR_UNEXPECTED
);
2238 mAddonManager
= ConstructJSImplementation
<AddonManager
>(
2239 "@mozilla.org/addon-web-api/manager;1", win
->AsGlobal(), aRv
);
2245 return mAddonManager
;
2248 webgpu::Instance
* Navigator::Gpu() {
2250 mWebGpu
= webgpu::Instance::Create(GetWindow()->AsGlobal());
2255 dom::LockManager
* Navigator::Locks() {
2257 mLocks
= dom::LockManager::Create(*GetWindow()->AsGlobal());
2263 bool Navigator::Webdriver() {
2264 #ifdef ENABLE_WEBDRIVER
2265 nsCOMPtr
<nsIMarionette
> marionette
= do_GetService(NS_MARIONETTE_CONTRACTID
);
2267 bool marionetteRunning
= false;
2268 marionette
->GetRunning(&marionetteRunning
);
2269 if (marionetteRunning
) {
2274 nsCOMPtr
<nsIRemoteAgent
> agent
= do_GetService(NS_REMOTEAGENT_CONTRACTID
);
2276 bool remoteAgentRunning
= false;
2277 agent
->GetRunning(&remoteAgentRunning
);
2278 if (remoteAgentRunning
) {
2287 AutoplayPolicy
Navigator::GetAutoplayPolicy(AutoplayPolicyMediaType aType
) {
2289 return AutoplayPolicy::Disallowed
;
2291 nsCOMPtr
<Document
> doc
= mWindow
->GetExtantDoc();
2293 return AutoplayPolicy::Disallowed
;
2295 return media::AutoplayPolicy::GetAutoplayPolicy(aType
, *doc
);
2298 AutoplayPolicy
Navigator::GetAutoplayPolicy(HTMLMediaElement
& aElement
) {
2299 return media::AutoplayPolicy::GetAutoplayPolicy(aElement
);
2302 AutoplayPolicy
Navigator::GetAutoplayPolicy(AudioContext
& aContext
) {
2303 return media::AutoplayPolicy::GetAutoplayPolicy(aContext
);
2306 already_AddRefed
<dom::UserActivation
> Navigator::UserActivation() {
2307 if (!mUserActivation
) {
2308 mUserActivation
= new dom::UserActivation(GetWindow());
2310 return do_AddRef(mUserActivation
);
2313 dom::WakeLockJS
* Navigator::WakeLock() {
2315 mWakeLock
= new WakeLockJS(mWindow
);
2320 } // namespace mozilla::dom