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/Hal.h"
64 #include "mozilla/ClearOnShutdown.h"
65 #include "mozilla/StaticPtr.h"
66 #include "Connection.h"
67 #include "mozilla/dom/Event.h" // for Event
68 #include "nsGlobalWindowInner.h"
69 #include "nsIPermissionManager.h"
70 #include "nsMimeTypes.h"
71 #include "nsNetUtil.h"
72 #include "nsRFPService.h"
73 #include "nsStringStream.h"
74 #include "nsComponentManagerUtils.h"
75 #include "nsICookieManager.h"
76 #include "nsICookieService.h"
77 #include "nsIHttpChannel.h"
78 #ifdef ENABLE_WEBDRIVER
79 # include "nsIMarionette.h"
80 # include "nsIRemoteAgent.h"
82 #include "nsStreamUtils.h"
83 #include "WidgetUtils.h"
84 #include "nsIScriptError.h"
85 #include "ReferrerInfo.h"
86 #include "mozilla/PermissionDelegateHandler.h"
88 #include "nsIExternalProtocolHandler.h"
89 #include "BrowserChild.h"
90 #include "mozilla/ipc/URIUtils.h"
92 #include "mozilla/dom/MediaDevices.h"
93 #include "MediaManager.h"
95 #include "nsJSUtils.h"
97 #include "mozilla/dom/Promise.h"
99 #include "nsIUploadChannel2.h"
100 #include "mozilla/dom/FormData.h"
101 #include "nsIDocShell.h"
103 #include "mozilla/dom/WorkerPrivate.h"
104 #include "mozilla/dom/WorkerRunnable.h"
107 # include "mozilla/WindowsVersion.h"
110 #include "mozilla/EMEUtils.h"
111 #include "mozilla/DetailedPromise.h"
112 #include "mozilla/Unused.h"
114 #include "mozilla/webgpu/Instance.h"
115 #include "mozilla/dom/WindowGlobalChild.h"
117 #include "mozilla/intl/LocaleService.h"
118 #include "mozilla/dom/AudioContext.h"
119 #include "mozilla/dom/HTMLMediaElement.h"
120 #include "AutoplayPolicy.h"
122 namespace mozilla::dom
{
124 static const nsLiteralCString kVibrationPermissionType
= "vibration"_ns
;
126 Navigator::Navigator(nsPIDOMWindowInner
* aWindow
) : mWindow(aWindow
) {}
128 Navigator::~Navigator() { Invalidate(); }
130 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(Navigator
)
131 NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
132 NS_INTERFACE_MAP_ENTRY(nsISupports
)
135 NS_IMPL_CYCLE_COLLECTING_ADDREF(Navigator
)
136 NS_IMPL_CYCLE_COLLECTING_RELEASE(Navigator
)
138 NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_CLASS(Navigator
)
140 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(Navigator
)
142 NS_IMPL_CYCLE_COLLECTION_UNLINK(mWindow
)
143 NS_IMPL_CYCLE_COLLECTION_UNLINK(mSharePromise
)
144 NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
145 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
147 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(Navigator
)
148 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPlugins
)
149 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPermissions
)
150 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mGeolocation
)
151 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mBatteryManager
)
152 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mBatteryPromise
)
153 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mConnection
)
154 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mStorageManager
)
155 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mCredentials
)
156 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mMediaDevices
)
157 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mServiceWorkerContainer
)
158 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mMediaCapabilities
)
159 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mMediaSession
)
160 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mAddonManager
)
161 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mWebGpu
)
162 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mLocks
)
163 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mUserActivation
)
165 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mWindow
)
166 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mMediaKeySystemAccessManager
)
167 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mGamepadServiceTest
)
168 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mVRGetDisplaysPromises
)
169 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mVRServiceTest
)
170 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mSharePromise
)
171 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mXRSystem
)
172 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
174 void Navigator::Invalidate() {
175 // Don't clear mWindow here so we know we've got a non-null mWindow
176 // until we're unlinked.
180 mPermissions
= nullptr;
182 if (mStorageManager
) {
183 mStorageManager
->Shutdown();
184 mStorageManager
= nullptr;
187 // If there is a page transition, make sure delete the geolocation object.
189 mGeolocation
->Shutdown();
190 mGeolocation
= nullptr;
193 if (mBatteryManager
) {
194 mBatteryManager
->Shutdown();
195 mBatteryManager
= nullptr;
198 mBatteryPromise
= nullptr;
201 mConnection
->Shutdown();
202 mConnection
= nullptr;
205 mMediaDevices
= nullptr;
207 mServiceWorkerContainer
= nullptr;
209 if (mMediaKeySystemAccessManager
) {
210 mMediaKeySystemAccessManager
->Shutdown();
211 mMediaKeySystemAccessManager
= nullptr;
214 if (mGamepadServiceTest
) {
215 mGamepadServiceTest
->Shutdown();
216 mGamepadServiceTest
= nullptr;
219 mVRGetDisplaysPromises
.Clear();
221 if (mVRServiceTest
) {
222 mVRServiceTest
->Shutdown();
223 mVRServiceTest
= nullptr;
227 mXRSystem
->Shutdown();
231 mMediaCapabilities
= nullptr;
234 mMediaSession
->Shutdown();
235 mMediaSession
= nullptr;
238 mAddonManager
= nullptr;
243 // Unloading a page does not immediately destruct the lock manager actor,
244 // but we want to abort the lock requests as soon as possible. Explicitly
245 // call Shutdown() to do that.
250 mUserActivation
= nullptr;
252 mSharePromise
= nullptr;
255 void Navigator::GetUserAgent(nsAString
& aUserAgent
, CallerType aCallerType
,
256 ErrorResult
& aRv
) const {
257 nsCOMPtr
<nsPIDOMWindowInner
> window
;
261 nsIDocShell
* docshell
= window
->GetDocShell();
262 nsString customUserAgent
;
264 docshell
->GetBrowsingContext()->GetCustomUserAgent(customUserAgent
);
266 if (!customUserAgent
.IsEmpty()) {
267 aUserAgent
= customUserAgent
;
273 nsCOMPtr
<Document
> doc
= mWindow
->GetExtantDoc();
274 nsresult rv
= GetUserAgent(
275 mWindow
, doc
, aCallerType
== CallerType::System
? Some(false) : Nothing(),
277 if (NS_WARN_IF(NS_FAILED(rv
))) {
282 void Navigator::GetAppCodeName(nsAString
& aAppCodeName
, ErrorResult
& aRv
) {
285 nsCOMPtr
<nsIHttpProtocolHandler
> service(
286 do_GetService(NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX
"http", &rv
));
287 if (NS_WARN_IF(NS_FAILED(rv
))) {
292 nsAutoCString appName
;
293 rv
= service
->GetAppName(appName
);
294 if (NS_WARN_IF(NS_FAILED(rv
))) {
299 CopyASCIItoUTF16(appName
, aAppCodeName
);
302 void Navigator::GetAppVersion(nsAString
& aAppVersion
, CallerType aCallerType
,
303 ErrorResult
& aRv
) const {
304 nsCOMPtr
<Document
> doc
= mWindow
->GetExtantDoc();
306 nsresult rv
= GetAppVersion(
308 /* aUsePrefOverriddenValue = */ aCallerType
!= CallerType::System
);
309 if (NS_WARN_IF(NS_FAILED(rv
))) {
314 void Navigator::GetAppName(nsAString
& aAppName
) const {
315 aAppName
.AssignLiteral("Netscape");
319 * Returns the value of Accept-Languages (HTTP header) as a nsTArray of
320 * languages. The value is set in the preference by the user ("Content
323 * "en", "en-US" and "i-cherokee" and "" are valid languages tokens.
325 * If there is no valid language, the value of getWebExposedLocales is
326 * used to ensure that locale spoofing is honored and to reduce
329 * See RFC 7231, Section 9.7 "Browser Fingerprinting" and
330 * RFC 2616, Section 15.1.4 "Privacy Issues Connected to Accept Headers"
334 void Navigator::GetAcceptLanguages(nsTArray
<nsString
>& aLanguages
) {
335 MOZ_ASSERT(NS_IsMainThread());
339 // E.g. "de-de, en-us,en".
340 nsAutoString acceptLang
;
341 Preferences::GetLocalizedString("intl.accept_languages", acceptLang
);
343 // Split values on commas.
344 for (nsDependentSubstring lang
:
345 nsCharSeparatedTokenizer(acceptLang
, ',').ToRange()) {
346 // Replace "_" with "-" to avoid POSIX/Windows "en_US" notation.
347 // NOTE: we should probably rely on the pref being set correctly.
348 if (lang
.Length() > 2 && lang
[2] == char16_t('_')) {
349 lang
.Replace(2, 1, char16_t('-'));
352 // Use uppercase for country part, e.g. "en-US", not "en-us", see BCP47
353 // only uppercase 2-letter country codes, not "zh-Hant", "de-DE-x-goethe".
354 // NOTE: we should probably rely on the pref being set correctly.
355 if (lang
.Length() > 2) {
358 for (const nsAString
& code
:
359 nsCharSeparatedTokenizer(lang
, '-').ToRange()) {
360 if (code
.Length() == 2 && !first
) {
361 nsAutoString
upper(code
);
363 lang
.Replace(pos
, code
.Length(), upper
);
366 pos
+= code
.Length() + 1; // 1 is the separator
371 aLanguages
.AppendElement(lang
);
373 if (aLanguages
.Length() == 0) {
374 nsTArray
<nsCString
> locales
;
375 mozilla::intl::LocaleService::GetInstance()->GetWebExposedLocales(locales
);
376 aLanguages
.AppendElement(NS_ConvertUTF8toUTF16(locales
[0]));
381 * Returns the first language from GetAcceptLanguages.
383 * Full details above in GetAcceptLanguages.
385 void Navigator::GetLanguage(nsAString
& aLanguage
) {
386 nsTArray
<nsString
> languages
;
387 GetLanguages(languages
);
388 MOZ_ASSERT(languages
.Length() >= 1);
389 aLanguage
.Assign(languages
[0]);
392 void Navigator::GetLanguages(nsTArray
<nsString
>& aLanguages
) {
393 GetAcceptLanguages(aLanguages
);
395 // The returned value is cached by the binding code. The window listens to the
396 // accept languages change and will clear the cache when needed. It has to
397 // take care of dispatching the DOM event already and the invalidation and the
398 // event has to be timed correctly.
401 void Navigator::GetPlatform(nsAString
& aPlatform
, CallerType aCallerType
,
402 ErrorResult
& aRv
) const {
404 BrowsingContext
* bc
= mWindow
->GetBrowsingContext();
405 nsString customPlatform
;
407 bc
->GetCustomPlatform(customPlatform
);
409 if (!customPlatform
.IsEmpty()) {
410 aPlatform
= customPlatform
;
416 nsCOMPtr
<Document
> doc
= mWindow
->GetExtantDoc();
418 nsresult rv
= GetPlatform(
420 /* aUsePrefOverriddenValue = */ aCallerType
!= CallerType::System
);
421 if (NS_WARN_IF(NS_FAILED(rv
))) {
426 void Navigator::GetOscpu(nsAString
& aOSCPU
, CallerType aCallerType
,
427 ErrorResult
& aRv
) const {
428 if (aCallerType
!= CallerType::System
) {
429 // If fingerprinting resistance is on, we will spoof this value. See
430 // nsRFPService.h for details about spoofed values.
431 if (nsContentUtils::ShouldResistFingerprinting(GetDocShell(),
432 RFPTarget::NavigatorOscpu
)) {
433 aOSCPU
.AssignLiteral(SPOOFED_OSCPU
);
437 nsAutoString override
;
438 nsresult rv
= Preferences::GetString("general.oscpu.override", override
);
439 if (NS_SUCCEEDED(rv
)) {
446 nsCOMPtr
<nsIHttpProtocolHandler
> service(
447 do_GetService(NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX
"http", &rv
));
448 if (NS_WARN_IF(NS_FAILED(rv
))) {
454 rv
= service
->GetOscpu(oscpu
);
455 if (NS_WARN_IF(NS_FAILED(rv
))) {
460 CopyASCIItoUTF16(oscpu
, aOSCPU
);
463 void Navigator::GetVendor(nsAString
& aVendor
) { aVendor
.Truncate(); }
465 void Navigator::GetVendorSub(nsAString
& aVendorSub
) { aVendorSub
.Truncate(); }
467 void Navigator::GetProduct(nsAString
& aProduct
) {
468 aProduct
.AssignLiteral("Gecko");
471 void Navigator::GetProductSub(nsAString
& aProductSub
) {
472 // Legacy build date hardcoded for backward compatibility (bug 776376)
473 aProductSub
.AssignLiteral(LEGACY_UA_GECKO_TRAIL
);
476 nsMimeTypeArray
* Navigator::GetMimeTypes(ErrorResult
& aRv
) {
477 auto* plugins
= GetPlugins(aRv
);
482 return plugins
->MimeTypeArray();
485 nsPluginArray
* Navigator::GetPlugins(ErrorResult
& aRv
) {
488 aRv
.Throw(NS_ERROR_UNEXPECTED
);
491 mPlugins
= MakeRefPtr
<nsPluginArray
>(mWindow
);
497 bool Navigator::PdfViewerEnabled() { return !StaticPrefs::pdfjs_disabled(); }
499 Permissions
* Navigator::GetPermissions(ErrorResult
& aRv
) {
501 aRv
.Throw(NS_ERROR_UNEXPECTED
);
506 mPermissions
= new Permissions(mWindow
);
512 StorageManager
* Navigator::Storage() {
515 if (!mStorageManager
) {
516 mStorageManager
= new StorageManager(mWindow
->AsGlobal());
519 return mStorageManager
;
522 bool Navigator::CookieEnabled() {
523 // Check whether an exception overrides the global cookie behavior
524 // Note that the code for getting the URI here matches that in
525 // nsHTMLDocument::SetCookie.
526 if (!mWindow
|| !mWindow
->GetDocShell()) {
527 return nsICookieManager::GetCookieBehavior(false) !=
528 nsICookieService::BEHAVIOR_REJECT
;
531 nsCOMPtr
<nsILoadContext
> loadContext
= do_GetInterface(mWindow
);
532 uint32_t cookieBehavior
= loadContext
533 ? nsICookieManager::GetCookieBehavior(
534 loadContext
->UsePrivateBrowsing())
535 : nsICookieManager::GetCookieBehavior(false);
536 bool cookieEnabled
= cookieBehavior
!= nsICookieService::BEHAVIOR_REJECT
;
538 nsCOMPtr
<Document
> doc
= mWindow
->GetExtantDoc();
540 return cookieEnabled
;
543 uint32_t rejectedReason
= 0;
544 bool granted
= false;
545 nsresult rv
= doc
->NodePrincipal()->HasFirstpartyStorageAccess(
546 mWindow
, &rejectedReason
, &granted
);
548 // Not a content, so technically can't set cookies, but let's
549 // just return the default value.
550 return cookieEnabled
;
553 // We should return true if the cookie is partitioned because the cookie is
554 // still available in this case.
556 StoragePartitioningEnabled(rejectedReason
, doc
->CookieJarSettings())) {
560 ContentBlockingNotifier::OnDecision(
562 granted
? ContentBlockingNotifier::BlockingDecision::eAllow
563 : ContentBlockingNotifier::BlockingDecision::eBlock
,
568 bool Navigator::OnLine() {
570 // Check if this tab is set to be offline.
571 BrowsingContext
* bc
= mWindow
->GetBrowsingContext();
572 if (bc
&& bc
->Top()->GetForceOffline()) {
576 // Return the default browser value
577 return !NS_IsOffline();
580 void Navigator::GetBuildID(nsAString
& aBuildID
, CallerType aCallerType
,
581 ErrorResult
& aRv
) const {
582 if (aCallerType
!= CallerType::System
) {
583 // If fingerprinting resistance is on, we will spoof this value. See
584 // nsRFPService.h for details about spoofed values.
585 if (nsContentUtils::ShouldResistFingerprinting(
586 GetDocShell(), RFPTarget::NavigatorBuildID
)) {
587 aBuildID
.AssignLiteral(LEGACY_BUILD_ID
);
591 nsAutoString override
;
592 nsresult rv
= Preferences::GetString("general.buildID.override", override
);
593 if (NS_SUCCEEDED(rv
)) {
599 bool isHTTPS
= false;
601 nsCOMPtr
<Document
> doc
= mWindow
->GetDoc();
603 nsIURI
* uri
= doc
->GetDocumentURI();
605 isHTTPS
= uri
->SchemeIs("https");
607 MOZ_ALWAYS_SUCCEEDS(uri
->GetHost(host
));
613 // Spoof the buildID on pages not loaded from "https://*.mozilla.org".
614 if (!isHTTPS
|| !StringEndsWith(host
, ".mozilla.org"_ns
)) {
615 aBuildID
.AssignLiteral(LEGACY_BUILD_ID
);
620 nsCOMPtr
<nsIXULAppInfo
> appInfo
=
621 do_GetService("@mozilla.org/xre/app-info;1");
623 aRv
.Throw(NS_ERROR_NOT_IMPLEMENTED
);
627 nsAutoCString buildID
;
628 nsresult rv
= appInfo
->GetAppBuildID(buildID
);
629 if (NS_WARN_IF(NS_FAILED(rv
))) {
635 AppendASCIItoUTF16(buildID
, aBuildID
);
638 void Navigator::GetDoNotTrack(nsAString
& aResult
) {
639 bool doNotTrack
= StaticPrefs::privacy_donottrackheader_enabled();
641 nsCOMPtr
<nsILoadContext
> loadContext
= do_GetInterface(mWindow
);
642 doNotTrack
= loadContext
&& loadContext
->UseTrackingProtection();
646 aResult
.AssignLiteral("1");
648 aResult
.AssignLiteral("unspecified");
652 bool Navigator::GlobalPrivacyControl() {
653 return StaticPrefs::privacy_globalprivacycontrol_enabled() &&
654 StaticPrefs::privacy_globalprivacycontrol_functionality_enabled();
657 uint64_t Navigator::HardwareConcurrency() {
658 workerinternals::RuntimeService
* rts
=
659 workerinternals::RuntimeService::GetOrCreateService();
664 return rts
->ClampedHardwareConcurrency(
665 nsGlobalWindowInner::Cast(mWindow
)->ShouldResistFingerprinting(
666 RFPTarget::NavigatorHWConcurrency
));
671 class VibrateWindowListener
: public nsIDOMEventListener
{
673 VibrateWindowListener(nsPIDOMWindowInner
* aWindow
, Document
* aDocument
) {
674 mWindow
= do_GetWeakReference(aWindow
);
675 mDocument
= do_GetWeakReference(aDocument
);
677 constexpr auto visibilitychange
= u
"visibilitychange"_ns
;
678 aDocument
->AddSystemEventListener(visibilitychange
, this, /* listener */
679 true, /* use capture */
680 false /* wants untrusted */);
683 void RemoveListener();
686 NS_DECL_NSIDOMEVENTLISTENER
689 virtual ~VibrateWindowListener() = default;
695 NS_IMPL_ISUPPORTS(VibrateWindowListener
, nsIDOMEventListener
)
697 StaticRefPtr
<VibrateWindowListener
> gVibrateWindowListener
;
699 static bool MayVibrate(Document
* doc
) {
700 // Hidden documents cannot start or stop a vibration.
701 return (doc
&& !doc
->Hidden());
705 VibrateWindowListener::HandleEvent(Event
* aEvent
) {
706 nsCOMPtr
<Document
> doc
= do_QueryInterface(aEvent
->GetTarget());
708 if (!MayVibrate(doc
)) {
709 // It's important that we call CancelVibrate(), not Vibrate() with an
710 // empty list, because Vibrate() will fail if we're no longer focused, but
711 // CancelVibrate() will succeed, so long as nobody else has started a new
712 // vibration pattern.
713 nsCOMPtr
<nsPIDOMWindowInner
> window
= do_QueryReferent(mWindow
);
714 hal::CancelVibrate(window
);
716 gVibrateWindowListener
= nullptr;
717 // Careful: The line above might have deleted |this|!
723 void VibrateWindowListener::RemoveListener() {
724 nsCOMPtr
<EventTarget
> target
= do_QueryReferent(mDocument
);
728 constexpr auto visibilitychange
= u
"visibilitychange"_ns
;
729 target
->RemoveSystemEventListener(visibilitychange
, this,
730 true /* use capture */);
735 void Navigator::SetVibrationPermission(bool aPermitted
, bool aPersistent
) {
736 MOZ_ASSERT(NS_IsMainThread());
738 nsTArray
<uint32_t> pattern
= std::move(mRequestedVibrationPattern
);
744 nsCOMPtr
<Document
> doc
= mWindow
->GetExtantDoc();
746 if (!MayVibrate(doc
)) {
751 // Add a listener to cancel the vibration if the document becomes hidden,
752 // and remove the old visibility listener, if there was one.
753 if (!gVibrateWindowListener
) {
754 // If gVibrateWindowListener is null, this is the first time we've
755 // vibrated, and we need to register a listener to clear
756 // gVibrateWindowListener on shutdown.
757 ClearOnShutdown(&gVibrateWindowListener
);
759 gVibrateWindowListener
->RemoveListener();
761 gVibrateWindowListener
= new VibrateWindowListener(mWindow
, doc
);
762 hal::Vibrate(pattern
, mWindow
);
766 nsCOMPtr
<nsIPermissionManager
> permMgr
=
767 components::PermissionManager::Service();
771 permMgr
->AddFromPrincipal(doc
->NodePrincipal(), kVibrationPermissionType
,
772 aPermitted
? nsIPermissionManager::ALLOW_ACTION
773 : nsIPermissionManager::DENY_ACTION
,
774 nsIPermissionManager::EXPIRE_SESSION
, 0);
778 bool Navigator::Vibrate(uint32_t aDuration
) {
779 AutoTArray
<uint32_t, 1> pattern
;
780 pattern
.AppendElement(aDuration
);
781 return Vibrate(pattern
);
784 nsTArray
<uint32_t> SanitizeVibratePattern(const nsTArray
<uint32_t>& aPattern
) {
785 nsTArray
<uint32_t> pattern(aPattern
.Clone());
787 if (pattern
.Length() > StaticPrefs::dom_vibrator_max_vibrate_list_len()) {
788 pattern
.SetLength(StaticPrefs::dom_vibrator_max_vibrate_list_len());
791 for (size_t i
= 0; i
< pattern
.Length(); ++i
) {
793 std::min(StaticPrefs::dom_vibrator_max_vibrate_ms(), pattern
[i
]);
799 bool Navigator::Vibrate(const nsTArray
<uint32_t>& aPattern
) {
800 MOZ_ASSERT(NS_IsMainThread());
806 nsCOMPtr
<Document
> doc
= mWindow
->GetExtantDoc();
808 if (!MayVibrate(doc
)) {
812 nsTArray
<uint32_t> pattern
= SanitizeVibratePattern(aPattern
);
814 // The spec says we check dom.vibrator.enabled after we've done the sanity
815 // checking on the pattern.
816 if (!StaticPrefs::dom_vibrator_enabled()) {
820 mRequestedVibrationPattern
= std::move(pattern
);
822 PermissionDelegateHandler
* permissionHandler
=
823 doc
->GetPermissionDelegateHandler();
824 if (NS_WARN_IF(!permissionHandler
)) {
828 uint32_t permission
= nsIPermissionManager::UNKNOWN_ACTION
;
830 permissionHandler
->GetPermission(kVibrationPermissionType
, &permission
,
833 if (permission
== nsIPermissionManager::DENY_ACTION
) {
834 // Abort without observer service or on denied session permission.
835 SetVibrationPermission(false /* permitted */, false /* persistent */);
839 if (permission
== nsIPermissionManager::ALLOW_ACTION
||
840 mRequestedVibrationPattern
.IsEmpty() ||
841 (mRequestedVibrationPattern
.Length() == 1 &&
842 mRequestedVibrationPattern
[0] == 0)) {
843 // Always allow cancelling vibration and respect session permissions.
844 SetVibrationPermission(true /* permitted */, false /* persistent */);
848 // Request user permission.
849 nsCOMPtr
<nsIObserverService
> obs
= services::GetObserverService();
854 obs
->NotifyObservers(ToSupports(this), "Vibration:Request", nullptr);
859 //*****************************************************************************
860 // Pointer Events interface
861 //*****************************************************************************
863 uint32_t Navigator::MaxTouchPoints(CallerType aCallerType
) {
864 nsIDocShell
* docshell
= GetDocShell();
865 BrowsingContext
* bc
= docshell
? docshell
->GetBrowsingContext() : nullptr;
867 // Responsive Design Mode overrides the maxTouchPoints property when
868 // touch simulation is enabled.
869 if (bc
&& bc
->InRDMPane()) {
870 return bc
->GetMaxTouchPointsOverride();
873 // The maxTouchPoints is going to reveal the detail of users' hardware. So,
874 // we will spoof it into 0 if fingerprinting resistance is on.
875 if (aCallerType
!= CallerType::System
&&
876 nsContentUtils::ShouldResistFingerprinting(GetDocShell(),
877 RFPTarget::PointerEvents
)) {
881 nsCOMPtr
<nsIWidget
> widget
=
882 widget::WidgetUtils::DOMWindowToWidget(mWindow
->GetOuterWindow());
884 NS_ENSURE_TRUE(widget
, 0);
885 return widget
->GetMaxTouchPoints();
888 //*****************************************************************************
889 // Navigator::nsIDOMClientInformation
890 //*****************************************************************************
892 // This list should be kept up-to-date with the spec:
893 // https://html.spec.whatwg.org/multipage/system-state.html#custom-handlers
894 // If you change this list, please also update the copy in E10SUtils.sys.mjs.
895 static const char* const kSafeSchemes
[] = {
924 void Navigator::CheckProtocolHandlerAllowed(const nsAString
& aScheme
,
926 nsIURI
* aDocumentURI
,
928 auto raisePermissionDeniedHandler
= [&] {
930 aHandlerURI
->GetSpec(spec
);
931 nsPrintfCString
message("Permission denied to add %s as a protocol handler",
933 aRv
.ThrowSecurityError(message
);
936 auto raisePermissionDeniedScheme
= [&] {
937 nsPrintfCString
message(
938 "Permission denied to add a protocol handler for %s",
939 NS_ConvertUTF16toUTF8(aScheme
).get());
940 aRv
.ThrowSecurityError(message
);
943 if (!aDocumentURI
|| !aHandlerURI
) {
944 aRv
.Throw(NS_ERROR_DOM_SYNTAX_ERR
);
949 aHandlerURI
->GetSpec(spec
);
950 // If the uri doesn't contain '%s', it won't be a good handler - the %s
951 // gets replaced with the handled URI.
952 if (!FindInReadable("%s"_ns
, spec
)) {
953 aRv
.ThrowSyntaxError("Handler URI does not contain \"%s\".");
957 // For security reasons we reject non-http(s) urls (see bug 354316),
958 nsAutoCString docScheme
;
959 nsAutoCString handlerScheme
;
960 aDocumentURI
->GetScheme(docScheme
);
961 aHandlerURI
->GetScheme(handlerScheme
);
962 if ((!docScheme
.EqualsLiteral("https") && !docScheme
.EqualsLiteral("http")) ||
963 (!handlerScheme
.EqualsLiteral("https") &&
964 !handlerScheme
.EqualsLiteral("http"))) {
965 raisePermissionDeniedHandler();
969 // Should be same-origin:
970 nsAutoCString handlerHost
;
971 aHandlerURI
->GetHostPort(handlerHost
);
972 nsAutoCString documentHost
;
973 aDocumentURI
->GetHostPort(documentHost
);
974 if (!handlerHost
.Equals(documentHost
) || !handlerScheme
.Equals(docScheme
)) {
975 raisePermissionDeniedHandler();
979 // Having checked the handler URI, check the scheme:
980 nsAutoCString scheme
;
981 ToLowerCase(NS_ConvertUTF16toUTF8(aScheme
), scheme
);
982 if (StringBeginsWith(scheme
, "web+"_ns
)) {
983 // Check for non-ascii
984 nsReadingIterator
<char> iter
;
985 nsReadingIterator
<char> iterEnd
;
986 auto remainingScheme
= Substring(scheme
, 4 /* web+ */);
987 remainingScheme
.BeginReading(iter
);
988 remainingScheme
.EndReading(iterEnd
);
989 // Scheme suffix must be non-empty
990 if (iter
== iterEnd
) {
991 raisePermissionDeniedScheme();
994 for (; iter
!= iterEnd
; iter
++) {
995 if (*iter
< 'a' || *iter
> 'z') {
996 raisePermissionDeniedScheme();
1001 bool matches
= false;
1002 for (const char* safeScheme
: kSafeSchemes
) {
1003 if (scheme
.Equals(safeScheme
)) {
1009 raisePermissionDeniedScheme();
1014 nsCOMPtr
<nsIProtocolHandler
> handler
;
1015 nsCOMPtr
<nsIIOService
> io
= components::IO::Service();
1017 io
->GetProtocolHandler(scheme
.get(), getter_AddRefs(handler
)))) {
1018 raisePermissionDeniedScheme();
1022 // check if we have prefs set saying not to add this.
1023 bool defaultExternal
=
1024 Preferences::GetBool("network.protocol-handler.external-default");
1025 nsPrintfCString
specificPref("network.protocol-handler.external.%s",
1027 if (!Preferences::GetBool(specificPref
.get(), defaultExternal
)) {
1028 raisePermissionDeniedScheme();
1032 // Check to make sure this isn't already handled internally (we don't
1033 // want to let them take over, say "chrome"). In theory, the checks above
1034 // should have already taken care of this.
1035 nsCOMPtr
<nsIExternalProtocolHandler
> externalHandler
=
1036 do_QueryInterface(handler
);
1039 "We should never allow overriding a builtin protocol handler");
1042 void Navigator::RegisterProtocolHandler(const nsAString
& aScheme
,
1043 const nsAString
& aURI
,
1045 if (!mWindow
|| !mWindow
->GetOuterWindow() || !mWindow
->GetDocShell() ||
1046 !mWindow
->GetDoc()) {
1049 nsCOMPtr
<nsILoadContext
> loadContext
= do_GetInterface(mWindow
);
1050 if (loadContext
->UsePrivateBrowsing()) {
1051 // If we're a private window, don't alert the user or webpage. We log to the
1052 // console so that web developers have some way to tell what's going wrong.
1053 nsContentUtils::ReportToConsole(
1054 nsIScriptError::warningFlag
, "DOM"_ns
, mWindow
->GetDoc(),
1055 nsContentUtils::eDOM_PROPERTIES
,
1056 "RegisterProtocolHandlerPrivateBrowsingWarning");
1060 nsCOMPtr
<Document
> doc
= mWindow
->GetDoc();
1062 // Determine if doc is allowed to assign this handler
1063 nsIURI
* docURI
= doc
->GetDocumentURIObject();
1064 nsCOMPtr
<nsIURI
> handlerURI
;
1065 NS_NewURI(getter_AddRefs(handlerURI
), NS_ConvertUTF16toUTF8(aURI
),
1066 doc
->GetDocumentCharacterSet(), docURI
);
1067 CheckProtocolHandlerAllowed(aScheme
, handlerURI
, docURI
, aRv
);
1072 // Determine a title from the document URI.
1073 nsAutoCString docDisplayHostPort
;
1074 docURI
->GetDisplayHostPort(docDisplayHostPort
);
1075 NS_ConvertASCIItoUTF16
title(docDisplayHostPort
);
1077 if (XRE_IsContentProcess()) {
1078 nsAutoString
scheme(aScheme
);
1079 RefPtr
<BrowserChild
> browserChild
= BrowserChild::GetFrom(mWindow
);
1080 browserChild
->SendRegisterProtocolHandler(scheme
, handlerURI
, title
,
1085 nsCOMPtr
<nsIWebProtocolHandlerRegistrar
> registrar
=
1086 do_GetService(NS_WEBPROTOCOLHANDLERREGISTRAR_CONTRACTID
);
1088 aRv
= registrar
->RegisterProtocolHandler(aScheme
, handlerURI
, title
, docURI
,
1089 mWindow
->GetOuterWindow());
1093 Geolocation
* Navigator::GetGeolocation(ErrorResult
& aRv
) {
1095 return mGeolocation
;
1098 if (!mWindow
|| !mWindow
->GetOuterWindow() || !mWindow
->GetDocShell()) {
1099 aRv
.Throw(NS_ERROR_FAILURE
);
1103 mGeolocation
= new Geolocation();
1104 if (NS_FAILED(mGeolocation
->Init(mWindow
))) {
1105 mGeolocation
= nullptr;
1106 aRv
.Throw(NS_ERROR_FAILURE
);
1110 return mGeolocation
;
1113 class BeaconStreamListener final
: public nsIStreamListener
{
1114 ~BeaconStreamListener() = default;
1117 BeaconStreamListener() : mLoadGroup(nullptr) {}
1119 void SetLoadGroup(nsILoadGroup
* aLoadGroup
) { mLoadGroup
= aLoadGroup
; }
1122 NS_DECL_NSISTREAMLISTENER
1123 NS_DECL_NSIREQUESTOBSERVER
1126 nsCOMPtr
<nsILoadGroup
> mLoadGroup
;
1129 NS_IMPL_ISUPPORTS(BeaconStreamListener
, nsIStreamListener
, nsIRequestObserver
)
1132 BeaconStreamListener::OnStartRequest(nsIRequest
* aRequest
) {
1133 // release the loadgroup first
1134 mLoadGroup
= nullptr;
1136 return NS_ERROR_ABORT
;
1140 BeaconStreamListener::OnStopRequest(nsIRequest
* aRequest
, nsresult aStatus
) {
1145 BeaconStreamListener::OnDataAvailable(nsIRequest
* aRequest
,
1146 nsIInputStream
* inStr
,
1147 uint64_t sourceOffset
, uint32_t count
) {
1152 bool Navigator::SendBeacon(const nsAString
& aUrl
,
1153 const Nullable
<fetch::BodyInit
>& aData
,
1155 if (aData
.IsNull()) {
1156 return SendBeaconInternal(aUrl
, nullptr, eBeaconTypeOther
, aRv
);
1159 if (aData
.Value().IsArrayBuffer()) {
1160 BodyExtractor
<const ArrayBuffer
> body(&aData
.Value().GetAsArrayBuffer());
1161 return SendBeaconInternal(aUrl
, &body
, eBeaconTypeArrayBuffer
, aRv
);
1164 if (aData
.Value().IsArrayBufferView()) {
1165 BodyExtractor
<const ArrayBufferView
> body(
1166 &aData
.Value().GetAsArrayBufferView());
1167 return SendBeaconInternal(aUrl
, &body
, eBeaconTypeArrayBuffer
, aRv
);
1170 if (aData
.Value().IsBlob()) {
1171 BodyExtractor
<const Blob
> body(&aData
.Value().GetAsBlob());
1172 return SendBeaconInternal(aUrl
, &body
, eBeaconTypeBlob
, aRv
);
1175 if (aData
.Value().IsFormData()) {
1176 BodyExtractor
<const FormData
> body(&aData
.Value().GetAsFormData());
1177 return SendBeaconInternal(aUrl
, &body
, eBeaconTypeOther
, aRv
);
1180 if (aData
.Value().IsUSVString()) {
1181 BodyExtractor
<const nsAString
> body(&aData
.Value().GetAsUSVString());
1182 return SendBeaconInternal(aUrl
, &body
, eBeaconTypeOther
, aRv
);
1185 if (aData
.Value().IsURLSearchParams()) {
1186 BodyExtractor
<const URLSearchParams
> body(
1187 &aData
.Value().GetAsURLSearchParams());
1188 return SendBeaconInternal(aUrl
, &body
, eBeaconTypeOther
, aRv
);
1191 MOZ_CRASH("Invalid data type.");
1195 bool Navigator::SendBeaconInternal(const nsAString
& aUrl
,
1196 BodyExtractorBase
* aBody
, BeaconType aType
,
1199 aRv
.Throw(NS_ERROR_DOM_INVALID_STATE_ERR
);
1203 nsCOMPtr
<Document
> doc
= mWindow
->GetDoc();
1205 aRv
.Throw(NS_ERROR_DOM_INVALID_STATE_ERR
);
1209 nsIURI
* documentURI
= doc
->GetDocumentURI();
1211 aRv
.Throw(NS_ERROR_DOM_INVALID_STATE_ERR
);
1215 nsCOMPtr
<nsIURI
> uri
;
1216 nsresult rv
= nsContentUtils::NewURIWithDocumentCharset(
1217 getter_AddRefs(uri
), aUrl
, doc
, doc
->GetDocBaseURI());
1218 if (NS_FAILED(rv
)) {
1219 aRv
.ThrowTypeError
<MSG_INVALID_URL
>(NS_ConvertUTF16toUTF8(aUrl
));
1223 // Spec disallows any schemes save for HTTP/HTTPs
1224 if (!uri
->SchemeIs("http") && !uri
->SchemeIs("https")) {
1225 aRv
.ThrowTypeError
<MSG_INVALID_URL_SCHEME
>("Beacon",
1226 uri
->GetSpecOrDefault());
1230 nsCOMPtr
<nsIInputStream
> in
;
1231 nsAutoCString contentTypeWithCharset
;
1232 nsAutoCString charset
;
1233 uint64_t length
= 0;
1235 aRv
= aBody
->GetAsStream(getter_AddRefs(in
), &length
,
1236 contentTypeWithCharset
, charset
);
1237 if (NS_WARN_IF(aRv
.Failed())) {
1242 nsSecurityFlags securityFlags
= nsILoadInfo::SEC_COOKIES_INCLUDE
;
1243 // Ensure that only streams with content types that are safelisted ignore CORS
1245 if (aBody
&& !contentTypeWithCharset
.IsVoid() &&
1246 !nsContentUtils::IsCORSSafelistedRequestHeader("content-type"_ns
,
1247 contentTypeWithCharset
)) {
1248 securityFlags
|= nsILoadInfo::SEC_REQUIRE_CORS_INHERITS_SEC_CONTEXT
;
1250 securityFlags
|= nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_INHERITS_SEC_CONTEXT
;
1253 nsCOMPtr
<nsIChannel
> channel
;
1254 rv
= NS_NewChannel(getter_AddRefs(channel
), uri
, doc
, securityFlags
,
1255 nsIContentPolicy::TYPE_BEACON
);
1257 if (NS_FAILED(rv
)) {
1262 nsCOMPtr
<nsIHttpChannel
> httpChannel
= do_QueryInterface(channel
);
1264 // Beacon spec only supports HTTP requests at this time
1265 aRv
.Throw(NS_ERROR_DOM_BAD_URI
);
1269 auto referrerInfo
= MakeRefPtr
<ReferrerInfo
>(*doc
);
1270 rv
= httpChannel
->SetReferrerInfoWithoutClone(referrerInfo
);
1271 MOZ_ASSERT(NS_SUCCEEDED(rv
));
1274 nsCOMPtr
<nsIUploadChannel2
> uploadChannel
= do_QueryInterface(channel
);
1275 if (!uploadChannel
) {
1276 aRv
.Throw(NS_ERROR_FAILURE
);
1280 uploadChannel
->ExplicitSetUploadStream(in
, contentTypeWithCharset
, length
,
1283 rv
= httpChannel
->SetRequestMethod("POST"_ns
);
1284 MOZ_ASSERT(NS_SUCCEEDED(rv
));
1287 nsCOMPtr
<nsISupportsPriority
> p
= do_QueryInterface(channel
);
1289 p
->SetPriority(nsISupportsPriority::PRIORITY_LOWEST
);
1292 nsCOMPtr
<nsIClassOfService
> cos(do_QueryInterface(channel
));
1294 cos
->AddClassFlags(nsIClassOfService::Background
);
1297 // The channel needs to have a loadgroup associated with it, so that we can
1298 // cancel the channel and any redirected channels it may create.
1299 nsCOMPtr
<nsILoadGroup
> loadGroup
= do_CreateInstance(NS_LOADGROUP_CONTRACTID
);
1300 nsCOMPtr
<nsIInterfaceRequestor
> callbacks
=
1301 do_QueryInterface(mWindow
->GetDocShell());
1302 loadGroup
->SetNotificationCallbacks(callbacks
);
1303 channel
->SetLoadGroup(loadGroup
);
1305 RefPtr
<BeaconStreamListener
> beaconListener
= new BeaconStreamListener();
1306 rv
= channel
->AsyncOpen(beaconListener
);
1307 // do not throw if security checks fail within asyncOpen
1308 NS_ENSURE_SUCCESS(rv
, false);
1310 // make the beaconListener hold a strong reference to the loadgroup
1311 // which is released in ::OnStartRequest
1312 beaconListener
->SetLoadGroup(loadGroup
);
1317 MediaDevices
* Navigator::GetMediaDevices(ErrorResult
& aRv
) {
1318 if (!mMediaDevices
) {
1319 if (!mWindow
|| !mWindow
->GetOuterWindow() ||
1320 mWindow
->GetOuterWindow()->GetCurrentInnerWindow() != mWindow
) {
1321 aRv
.Throw(NS_ERROR_NOT_AVAILABLE
);
1324 mMediaDevices
= new MediaDevices(mWindow
);
1326 return mMediaDevices
;
1329 void Navigator::MozGetUserMedia(const MediaStreamConstraints
& aConstraints
,
1330 NavigatorUserMediaSuccessCallback
& aOnSuccess
,
1331 NavigatorUserMediaErrorCallback
& aOnError
,
1332 CallerType aCallerType
, ErrorResult
& aRv
) {
1333 MOZ_ASSERT(NS_IsMainThread());
1334 if (!mWindow
|| !mWindow
->IsFullyActive()) {
1335 aRv
.ThrowInvalidStateError("The document is not fully active.");
1338 GetMediaDevices(aRv
);
1342 MOZ_ASSERT(mMediaDevices
);
1343 if (Document
* doc
= mWindow
->GetExtantDoc()) {
1344 if (!mWindow
->IsSecureContext()) {
1345 doc
->SetUseCounter(eUseCounter_custom_MozGetUserMediaInsec
);
1348 RefPtr
<MediaManager::StreamPromise
> sp
;
1349 if (!MediaManager::IsOn(aConstraints
.mVideo
) &&
1350 !MediaManager::IsOn(aConstraints
.mAudio
)) {
1351 sp
= MediaManager::StreamPromise::CreateAndReject(
1352 MakeRefPtr
<MediaMgrError
>(MediaMgrError::Name::TypeError
,
1353 "audio and/or video is required"),
1356 sp
= mMediaDevices
->GetUserMedia(mWindow
, aConstraints
, aCallerType
);
1358 RefPtr
<NavigatorUserMediaSuccessCallback
> onsuccess(&aOnSuccess
);
1359 RefPtr
<NavigatorUserMediaErrorCallback
> onerror(&aOnError
);
1361 nsWeakPtr weakWindow
= nsWeakPtr(do_GetWeakReference(mWindow
));
1363 GetMainThreadSerialEventTarget(), __func__
,
1364 [weakWindow
, onsuccess
= std::move(onsuccess
)](
1365 const RefPtr
<DOMMediaStream
>& aStream
) MOZ_CAN_RUN_SCRIPT
{
1366 nsCOMPtr
<nsPIDOMWindowInner
> window
= do_QueryReferent(weakWindow
);
1367 if (!window
|| !window
->GetOuterWindow() ||
1368 window
->GetOuterWindow()->GetCurrentInnerWindow() != window
) {
1369 return; // Leave Promise pending after navigation by design.
1371 MediaManager::CallOnSuccess(*onsuccess
, *aStream
);
1373 [weakWindow
, onerror
= std::move(onerror
)](
1374 const RefPtr
<MediaMgrError
>& aError
) MOZ_CAN_RUN_SCRIPT
{
1375 nsCOMPtr
<nsPIDOMWindowInner
> window
= do_QueryReferent(weakWindow
);
1376 if (!window
|| !window
->GetOuterWindow() ||
1377 window
->GetOuterWindow()->GetCurrentInnerWindow() != window
) {
1378 return; // Leave Promise pending after navigation by design.
1380 auto error
= MakeRefPtr
<MediaStreamError
>(window
, *aError
);
1381 MediaManager::CallOnError(*onerror
, *error
);
1385 //*****************************************************************************
1386 // Navigator::nsINavigatorBattery
1387 //*****************************************************************************
1389 Promise
* Navigator::GetBattery(ErrorResult
& aRv
) {
1390 if (mBatteryPromise
) {
1391 return mBatteryPromise
;
1394 if (!mWindow
|| !mWindow
->GetDocShell()) {
1395 aRv
.Throw(NS_ERROR_UNEXPECTED
);
1399 RefPtr
<Promise
> batteryPromise
= Promise::Create(mWindow
->AsGlobal(), aRv
);
1400 if (NS_WARN_IF(aRv
.Failed())) {
1403 mBatteryPromise
= batteryPromise
;
1405 if (!mBatteryManager
) {
1406 mBatteryManager
= new battery::BatteryManager(mWindow
);
1407 mBatteryManager
->Init();
1410 mBatteryPromise
->MaybeResolve(mBatteryManager
);
1412 return mBatteryPromise
;
1415 //*****************************************************************************
1416 // Navigator::Share() - Web Share API
1417 //*****************************************************************************
1419 already_AddRefed
<Promise
> Navigator::Share(const ShareData
& aData
,
1421 if (!mWindow
|| !mWindow
->IsFullyActive()) {
1422 aRv
.ThrowInvalidStateError("The document is not fully active.");
1426 if (NS_WARN_IF(!mWindow
->GetDocShell() || !mWindow
->GetExtantDoc())) {
1427 aRv
.Throw(NS_ERROR_UNEXPECTED
);
1431 if (!FeaturePolicyUtils::IsFeatureAllowed(mWindow
->GetExtantDoc(),
1433 aRv
.ThrowNotAllowedError(
1434 "Document's Permissions Policy does not allow calling "
1435 "share() from this context.");
1439 if (mSharePromise
) {
1440 NS_WARNING("Only one share picker at a time per navigator instance");
1441 aRv
.Throw(NS_ERROR_DOM_INVALID_STATE_ERR
);
1445 // null checked above
1446 Document
* doc
= mWindow
->GetExtantDoc();
1448 if (StaticPrefs::dom_webshare_requireinteraction() &&
1449 !doc
->ConsumeTransientUserGestureActivation()) {
1450 aRv
.ThrowNotAllowedError(
1451 "User activation was already consumed "
1452 "or share() was not activated by a user gesture.");
1456 ValidateShareData(aData
, aRv
);
1462 // TODO: Process file member, which we don't currently support.
1464 // If data's url member is present, try to resolve it...
1465 nsCOMPtr
<nsIURI
> url
;
1466 if (aData
.mUrl
.WasPassed()) {
1467 auto result
= doc
->ResolveWithBaseURI(aData
.mUrl
.Value());
1468 url
= result
.unwrap();
1472 // Process the title member...
1474 if (aData
.mTitle
.WasPassed()) {
1475 title
.Assign(NS_ConvertUTF16toUTF8(aData
.mTitle
.Value()));
1477 title
.SetIsVoid(true);
1480 // Process the text member...
1482 if (aData
.mText
.WasPassed()) {
1483 text
.Assign(NS_ConvertUTF16toUTF8(aData
.mText
.Value()));
1485 text
.SetIsVoid(true);
1488 // Let mSharePromise be a new promise.
1489 mSharePromise
= Promise::Create(mWindow
->AsGlobal(), aRv
);
1494 IPCWebShareData
data(title
, text
, url
);
1495 auto wgc
= mWindow
->GetWindowGlobalChild();
1497 aRv
.Throw(NS_ERROR_FAILURE
);
1502 wgc
->SendShare(data
)->Then(
1503 GetCurrentSerialEventTarget(), __func__
,
1504 [self
= RefPtr
{this}](
1505 PWindowGlobalChild::SharePromise::ResolveOrRejectValue
&& aResult
) {
1506 if (aResult
.IsResolve()) {
1507 if (NS_SUCCEEDED(aResult
.ResolveValue())) {
1508 self
->mSharePromise
->MaybeResolveWithUndefined();
1510 self
->mSharePromise
->MaybeReject(aResult
.ResolveValue());
1512 } else if (self
->mSharePromise
) {
1514 self
->mSharePromise
->MaybeReject(NS_BINDING_ABORTED
);
1516 self
->mSharePromise
= nullptr;
1518 return do_AddRef(mSharePromise
);
1521 //*****************************************************************************
1522 // Navigator::CanShare() - Web Share API
1523 //*****************************************************************************
1524 bool Navigator::CanShare(const ShareData
& aData
) {
1525 if (!mWindow
|| !mWindow
->IsFullyActive()) {
1529 if (!FeaturePolicyUtils::IsFeatureAllowed(mWindow
->GetExtantDoc(),
1534 IgnoredErrorResult rv
;
1535 ValidateShareData(aData
, rv
);
1536 return !rv
.Failed();
1539 void Navigator::ValidateShareData(const ShareData
& aData
, ErrorResult
& aRv
) {
1540 // TODO: remove this check when we support files share.
1541 if (aData
.mFiles
.WasPassed() && !aData
.mFiles
.Value().IsEmpty()) {
1542 aRv
.ThrowTypeError("Passing files is currently not supported.");
1546 bool titleTextOrUrlPassed
= aData
.mTitle
.WasPassed() ||
1547 aData
.mText
.WasPassed() || aData
.mUrl
.WasPassed();
1549 // At least one member must be present.
1550 if (!titleTextOrUrlPassed
) {
1552 "Must have a title, text, or url member in the ShareData dictionary");
1556 // If data's url member is present, try to resolve it...
1557 nsCOMPtr
<nsIURI
> url
;
1558 if (aData
.mUrl
.WasPassed()) {
1559 Document
* doc
= mWindow
->GetExtantDoc();
1560 Result
<OwningNonNull
<nsIURI
>, nsresult
> result
=
1561 doc
->ResolveWithBaseURI(aData
.mUrl
.Value());
1562 if (NS_WARN_IF(result
.isErr())) {
1563 aRv
.ThrowTypeError
<MSG_INVALID_URL
>(
1564 NS_ConvertUTF16toUTF8(aData
.mUrl
.Value()));
1567 url
= result
.unwrap();
1568 // Check that we only share loadable URLs (e.g., http/https).
1569 // we also exclude blobs, as it doesn't make sense to share those outside
1570 // the context of the browser.
1571 const uint32_t flags
=
1572 nsIScriptSecurityManager::DISALLOW_INHERIT_PRINCIPAL
|
1573 nsIScriptSecurityManager::DISALLOW_SCRIPT
;
1575 nsContentUtils::GetSecurityManager()->CheckLoadURIWithPrincipal(
1576 doc
->NodePrincipal(), url
, flags
, doc
->InnerWindowID())) ||
1577 url
->SchemeIs("blob")) {
1578 aRv
.ThrowTypeError
<MSG_INVALID_URL_SCHEME
>("Share",
1579 url
->GetSpecOrDefault());
1585 static bool ShouldResistFingerprinting(const Document
* aDoc
,
1586 RFPTarget aTarget
) {
1587 return aDoc
? aDoc
->ShouldResistFingerprinting(aTarget
)
1588 : nsContentUtils::ShouldResistFingerprinting("Fallback", aTarget
);
1591 already_AddRefed
<LegacyMozTCPSocket
> Navigator::MozTCPSocket() {
1592 RefPtr
<LegacyMozTCPSocket
> socket
= new LegacyMozTCPSocket(GetWindow());
1593 return socket
.forget();
1596 void Navigator::GetGamepads(nsTArray
<RefPtr
<Gamepad
>>& aGamepads
,
1598 if (!mWindow
|| !mWindow
->IsFullyActive()) {
1601 NS_ENSURE_TRUE_VOID(mWindow
->GetDocShell());
1602 nsGlobalWindowInner
* win
= nsGlobalWindowInner::Cast(mWindow
);
1604 if (!FeaturePolicyUtils::IsFeatureAllowed(win
->GetExtantDoc(),
1606 aRv
.ThrowSecurityError(
1607 "Document's Permission Policy does not allow calling "
1608 "getGamepads() from this context.");
1612 win
->SetHasGamepadEventListener(true);
1613 win
->GetGamepads(aGamepads
);
1616 GamepadServiceTest
* Navigator::RequestGamepadServiceTest(ErrorResult
& aRv
) {
1618 if (!StaticPrefs::fuzzing_enabled()) {
1619 aRv
.Throw(NS_ERROR_UNEXPECTED
);
1623 if (!xpc::IsInAutomation()) {
1624 aRv
.Throw(NS_ERROR_UNEXPECTED
);
1629 if (!mGamepadServiceTest
) {
1630 mGamepadServiceTest
= GamepadServiceTest::CreateTestService(mWindow
);
1632 return mGamepadServiceTest
;
1635 already_AddRefed
<Promise
> Navigator::GetVRDisplays(ErrorResult
& aRv
) {
1636 if (!mWindow
|| !mWindow
->GetDocShell() || !mWindow
->GetExtantDoc()) {
1637 aRv
.Throw(NS_ERROR_UNEXPECTED
);
1641 if (!FeaturePolicyUtils::IsFeatureAllowed(mWindow
->GetExtantDoc(),
1643 aRv
.Throw(NS_ERROR_DOM_SECURITY_ERR
);
1647 RefPtr
<Promise
> p
= Promise::Create(mWindow
->AsGlobal(), aRv
);
1652 RefPtr
<BrowserChild
> browser(BrowserChild::GetFrom(mWindow
));
1654 MOZ_ASSERT(XRE_IsParentProcess());
1655 FinishGetVRDisplays(true, p
);
1657 RefPtr
<Navigator
> self(this);
1658 int browserID
= browser
->ChromeOuterWindowID();
1660 browser
->SendIsWindowSupportingWebVR(browserID
)->Then(
1661 GetCurrentSerialEventTarget(), __func__
,
1662 [self
, p
](bool isSupported
) {
1663 self
->FinishGetVRDisplays(isSupported
, p
);
1665 [p
](const mozilla::ipc::ResponseRejectReason
) {
1666 p
->MaybeRejectWithTypeError("Unable to start display enumeration");
1673 void Navigator::FinishGetVRDisplays(bool isWebVRSupportedInwindow
, Promise
* p
) {
1674 if (!isWebVRSupportedInwindow
) {
1675 // WebVR in this window is not supported, so resolve the promise
1676 // with no displays available
1677 nsTArray
<RefPtr
<VRDisplay
>> vrDisplaysEmpty
;
1678 p
->MaybeResolve(vrDisplaysEmpty
);
1682 // Since FinishGetVRDisplays can be called asynchronously after an IPC
1683 // response, it's possible that the Window can be torn down before this
1684 // call. In that case, the Window's cyclic references to VR objects are
1685 // also torn down and should not be recreated via
1686 // NotifyHasXRSession.
1687 nsGlobalWindowInner
* win
= nsGlobalWindowInner::Cast(mWindow
);
1688 if (win
->IsDying()) {
1689 // The Window has been torn down, so there is no further work that can
1691 p
->MaybeRejectWithTypeError(
1692 "Unable to return VRDisplays for a closed window.");
1696 mVRGetDisplaysPromises
.AppendElement(p
);
1697 win
->RequestXRPermission();
1700 void Navigator::OnXRPermissionRequestAllow() {
1701 // The permission request that results in this callback could have
1702 // been instantiated by WebVR, WebXR, or both.
1703 nsGlobalWindowInner
* win
= nsGlobalWindowInner::Cast(mWindow
);
1704 bool usingWebXR
= false;
1707 usingWebXR
= mXRSystem
->OnXRPermissionRequestAllow();
1710 bool rejectWebVR
= true;
1711 // If WebVR and WebXR both requested permission, only grant it to
1712 // WebXR, which takes priority.
1714 // We pass mWindow's id to RefreshVRDisplays, so NotifyVRDisplaysUpdated
1715 // will be called asynchronously, resolving the promises in
1716 // mVRGetDisplaysPromises.
1717 rejectWebVR
= !VRDisplay::RefreshVRDisplays(win
->WindowID());
1719 // Even if WebXR took priority, reject requests for WebVR in case they were
1720 // made simultaneously and coelesced into a single permission prompt.
1722 for (auto& p
: mVRGetDisplaysPromises
) {
1723 // Failed to refresh, reject the promise now
1724 p
->MaybeRejectWithTypeError("Failed to find attached VR displays.");
1726 mVRGetDisplaysPromises
.Clear();
1730 void Navigator::OnXRPermissionRequestCancel() {
1732 mXRSystem
->OnXRPermissionRequestCancel();
1735 nsTArray
<RefPtr
<VRDisplay
>> vrDisplays
;
1736 for (auto& p
: mVRGetDisplaysPromises
) {
1737 // Resolve the promise with no vr displays when
1738 // the user blocks access.
1739 p
->MaybeResolve(vrDisplays
);
1741 mVRGetDisplaysPromises
.Clear();
1744 void Navigator::GetActiveVRDisplays(
1745 nsTArray
<RefPtr
<VRDisplay
>>& aDisplays
) const {
1747 * Get only the active VR displays.
1748 * GetActiveVRDisplays should only enumerate displays that
1749 * are already active without causing any other hardware to be
1751 * We must not call nsGlobalWindowInner::NotifyHasXRSession here,
1752 * as that would cause enumeration and activation of other VR hardware.
1753 * Activating VR hardware is intrusive to the end user, as it may
1754 * involve physically powering on devices that the user did not
1757 if (!mWindow
|| !mWindow
->GetDocShell()) {
1760 nsGlobalWindowInner
* win
= nsGlobalWindowInner::Cast(mWindow
);
1761 nsTArray
<RefPtr
<VRDisplay
>> displays
;
1762 if (win
->UpdateVRDisplays(displays
)) {
1763 for (auto display
: displays
) {
1764 if (display
->IsPresenting()) {
1765 aDisplays
.AppendElement(display
);
1771 void Navigator::NotifyVRDisplaysUpdated() {
1772 // Synchronize the VR devices and resolve the promises in
1773 // mVRGetDisplaysPromises
1774 nsGlobalWindowInner
* win
= nsGlobalWindowInner::Cast(mWindow
);
1776 nsTArray
<RefPtr
<VRDisplay
>> vrDisplays
;
1777 if (win
->UpdateVRDisplays(vrDisplays
)) {
1778 for (auto p
: mVRGetDisplaysPromises
) {
1779 p
->MaybeResolve(vrDisplays
);
1782 for (auto p
: mVRGetDisplaysPromises
) {
1783 p
->MaybeReject(NS_ERROR_FAILURE
);
1786 mVRGetDisplaysPromises
.Clear();
1789 void Navigator::NotifyActiveVRDisplaysChanged() {
1790 Navigator_Binding::ClearCachedActiveVRDisplaysValue(this);
1793 VRServiceTest
* Navigator::RequestVRServiceTest(ErrorResult
& aRv
) {
1794 if (!xpc::IsInAutomation()) {
1795 aRv
.Throw(NS_ERROR_UNEXPECTED
);
1799 // Ensure that the Mock VR devices are not released prematurely
1800 nsGlobalWindowInner
* win
= nsGlobalWindowInner::Cast(mWindow
);
1801 win
->NotifyHasXRSession();
1803 if (!mVRServiceTest
) {
1804 mVRServiceTest
= VRServiceTest::CreateTestService(mWindow
);
1806 return mVRServiceTest
;
1809 XRSystem
* Navigator::GetXr(ErrorResult
& aRv
) {
1811 aRv
.Throw(NS_ERROR_UNEXPECTED
);
1815 mXRSystem
= XRSystem::Create(mWindow
);
1820 bool Navigator::IsWebVRContentDetected() const {
1821 nsGlobalWindowInner
* win
= nsGlobalWindowInner::Cast(mWindow
);
1822 return win
->IsVRContentDetected();
1825 bool Navigator::IsWebVRContentPresenting() const {
1826 nsGlobalWindowInner
* win
= nsGlobalWindowInner::Cast(mWindow
);
1827 return win
->IsVRContentPresenting();
1830 void Navigator::RequestVRPresentation(VRDisplay
& aDisplay
) {
1831 nsGlobalWindowInner
* win
= nsGlobalWindowInner::Cast(mWindow
);
1832 win
->DispatchVRDisplayActivate(aDisplay
.DisplayId(),
1833 VRDisplayEventReason::Requested
);
1836 already_AddRefed
<Promise
> Navigator::RequestMIDIAccess(
1837 const MIDIOptions
& aOptions
, ErrorResult
& aRv
) {
1839 aRv
.Throw(NS_ERROR_UNEXPECTED
);
1842 MIDIAccessManager
* accessMgr
= MIDIAccessManager::Get();
1843 return accessMgr
->RequestMIDIAccess(mWindow
, aOptions
, aRv
);
1846 network::Connection
* Navigator::GetConnection(ErrorResult
& aRv
) {
1849 aRv
.Throw(NS_ERROR_UNEXPECTED
);
1852 mConnection
= network::Connection::CreateForWindow(
1853 mWindow
, nsGlobalWindowInner::Cast(mWindow
)->ShouldResistFingerprinting(
1854 RFPTarget::NavigatorConnection
));
1860 already_AddRefed
<ServiceWorkerContainer
> Navigator::ServiceWorker() {
1861 MOZ_ASSERT(mWindow
);
1863 if (!mServiceWorkerContainer
) {
1864 mServiceWorkerContainer
=
1865 ServiceWorkerContainer::Create(mWindow
->AsGlobal());
1868 RefPtr
<ServiceWorkerContainer
> ref
= mServiceWorkerContainer
;
1869 return ref
.forget();
1872 already_AddRefed
<ServiceWorkerContainer
> Navigator::ServiceWorkerJS() {
1873 if (mWindow
->AsGlobal()->GetStorageAccess() ==
1874 StorageAccess::ePrivateBrowsing
) {
1875 SetUseCounter(mWindow
->AsGlobal()->GetGlobalJSObject(),
1876 eUseCounter_custom_PrivateBrowsingNavigatorServiceWorker
);
1879 return ServiceWorker();
1882 size_t Navigator::SizeOfIncludingThis(
1883 mozilla::MallocSizeOf aMallocSizeOf
) const {
1884 size_t n
= aMallocSizeOf(this);
1886 // TODO: add SizeOfIncludingThis() to nsMimeTypeArray, bug 674113.
1887 // TODO: add SizeOfIncludingThis() to nsPluginArray, bug 674114.
1888 // TODO: add SizeOfIncludingThis() to Geolocation, bug 674115.
1889 // TODO: add SizeOfIncludingThis() to DesktopNotificationCenter, bug 674116.
1894 void Navigator::OnNavigation() {
1899 // If MediaManager is open let it inform any live streams or pending callbacks
1900 MediaManager
* manager
= MediaManager::GetIfExists();
1902 manager
->OnNavigation(mWindow
->WindowID());
1906 JSObject
* Navigator::WrapObject(JSContext
* cx
,
1907 JS::Handle
<JSObject
*> aGivenProto
) {
1908 return Navigator_Binding::Wrap(cx
, this, aGivenProto
);
1912 bool Navigator::HasUserMediaSupport(JSContext
* cx
, JSObject
* obj
) {
1913 // Make enabling peerconnection enable getUserMedia() as well.
1914 // Emulate [SecureContext] unless media.devices.insecure.enabled=true
1915 return (StaticPrefs::media_navigator_enabled() ||
1916 StaticPrefs::media_peerconnection_enabled()) &&
1917 (IsSecureContextOrObjectIsFromSecureContext(cx
, obj
) ||
1918 StaticPrefs::media_devices_insecure_enabled());
1922 bool Navigator::HasShareSupport(JSContext
* cx
, JSObject
* obj
) {
1923 if (!StaticPrefs::dom_webshare_enabled()) {
1926 #if defined(XP_WIN) && !defined(__MINGW32__)
1927 // The first public build that supports ShareCanceled API
1928 return IsWindows10BuildOrLater(18956);
1935 bool Navigator::HasMidiSupport(JSContext
* cx
, JSObject
* obj
) {
1936 nsIPrincipal
* principal
= nsContentUtils::SubjectPrincipal(cx
);
1938 // Enable on secure contexts but exclude file schemes.
1939 return StaticPrefs::dom_webmidi_enabled() &&
1940 IsSecureContextOrObjectIsFromSecureContext(cx
, obj
) &&
1941 !principal
->SchemeIs("file");
1945 already_AddRefed
<nsPIDOMWindowInner
> Navigator::GetWindowFromGlobal(
1946 JSObject
* aGlobal
) {
1947 nsCOMPtr
<nsPIDOMWindowInner
> win
= xpc::WindowOrNull(aGlobal
);
1948 return win
.forget();
1951 void Navigator::ClearPlatformCache() {
1952 Navigator_Binding::ClearCachedPlatformValue(this);
1955 nsresult
Navigator::GetPlatform(nsAString
& aPlatform
, Document
* aCallerDoc
,
1956 bool aUsePrefOverriddenValue
) {
1957 MOZ_ASSERT(NS_IsMainThread());
1959 if (aUsePrefOverriddenValue
) {
1960 // If fingerprinting resistance is on, we will spoof this value. See
1961 // nsRFPService.h for details about spoofed values.
1962 if (ShouldResistFingerprinting(aCallerDoc
, RFPTarget::NavigatorPlatform
)) {
1963 aPlatform
.AssignLiteral(SPOOFED_PLATFORM
);
1966 nsAutoString override
;
1968 mozilla::Preferences::GetString("general.platform.override", override
);
1970 if (NS_SUCCEEDED(rv
)) {
1971 aPlatform
= override
;
1977 aPlatform
.AssignLiteral("Win32");
1978 #elif defined(XP_MACOSX)
1979 // Always return "MacIntel", even on ARM64 macOS like Safari does.
1980 aPlatform
.AssignLiteral("MacIntel");
1983 nsCOMPtr
<nsIHttpProtocolHandler
> service(
1984 do_GetService(NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX
"http", &rv
));
1985 NS_ENSURE_SUCCESS(rv
, rv
);
1988 rv
= service
->GetOscpu(plat
);
1989 NS_ENSURE_SUCCESS(rv
, rv
);
1991 CopyASCIItoUTF16(plat
, aPlatform
);
1998 nsresult
Navigator::GetAppVersion(nsAString
& aAppVersion
, Document
* aCallerDoc
,
1999 bool aUsePrefOverriddenValue
) {
2000 MOZ_ASSERT(NS_IsMainThread());
2002 if (aUsePrefOverriddenValue
) {
2003 // If fingerprinting resistance is on, we will spoof this value. See
2004 // nsRFPService.h for details about spoofed values.
2005 if (ShouldResistFingerprinting(aCallerDoc
,
2006 RFPTarget::NavigatorAppVersion
)) {
2007 aAppVersion
.AssignLiteral(SPOOFED_APPVERSION
);
2010 nsAutoString override
;
2011 nsresult rv
= mozilla::Preferences::GetString("general.appversion.override",
2014 if (NS_SUCCEEDED(rv
)) {
2015 aAppVersion
= override
;
2022 nsCOMPtr
<nsIHttpProtocolHandler
> service(
2023 do_GetService(NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX
"http", &rv
));
2024 NS_ENSURE_SUCCESS(rv
, rv
);
2027 rv
= service
->GetAppVersion(str
);
2028 CopyASCIItoUTF16(str
, aAppVersion
);
2029 NS_ENSURE_SUCCESS(rv
, rv
);
2031 aAppVersion
.AppendLiteral(" (");
2033 rv
= service
->GetPlatform(str
);
2034 NS_ENSURE_SUCCESS(rv
, rv
);
2036 AppendASCIItoUTF16(str
, aAppVersion
);
2037 aAppVersion
.Append(char16_t(')'));
2042 void Navigator::ClearUserAgentCache() {
2043 Navigator_Binding::ClearCachedUserAgentValue(this);
2046 nsresult
Navigator::GetUserAgent(nsPIDOMWindowInner
* aWindow
,
2047 Document
* aCallerDoc
,
2048 Maybe
<bool> aShouldResistFingerprinting
,
2049 nsAString
& aUserAgent
) {
2050 MOZ_ASSERT(NS_IsMainThread());
2053 ResistFingerprinting is migrating to fine-grained control based off
2054 either a channel or Principal+OriginAttributes
2056 This function can be called from Workers, Main Thread, and at least one
2057 other (unusual) case.
2059 For Main Thread, we will generally have a window and an associated
2060 Document, for Workers we will not.
2062 If aShouldResistFingerprinting is provided, we should respect it.
2063 If it is not provided, we will use aCallerDoc to determine our behavior.
2066 bool shouldResistFingerprinting
=
2067 aShouldResistFingerprinting
.isSome()
2068 ? aShouldResistFingerprinting
.value()
2069 : ShouldResistFingerprinting(aCallerDoc
,
2070 RFPTarget::NavigatorUserAgent
);
2072 // We will skip the override and pass to httpHandler to get spoofed userAgent
2073 // when 'privacy.resistFingerprinting' is true.
2074 if (!shouldResistFingerprinting
) {
2075 nsAutoString override
;
2077 mozilla::Preferences::GetString("general.useragent.override", override
);
2079 if (NS_SUCCEEDED(rv
)) {
2080 aUserAgent
= override
;
2085 // When the caller is content and 'privacy.resistFingerprinting' is true,
2086 // return a spoofed userAgent which reveals the platform but not the
2087 // specific OS version, etc.
2088 if (shouldResistFingerprinting
) {
2089 nsAutoCString spoofedUA
;
2090 nsRFPService::GetSpoofedUserAgent(spoofedUA
, false);
2091 CopyASCIItoUTF16(spoofedUA
, aUserAgent
);
2096 nsCOMPtr
<nsIHttpProtocolHandler
> service(
2097 do_GetService(NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX
"http", &rv
));
2098 if (NS_WARN_IF(NS_FAILED(rv
))) {
2103 rv
= service
->GetUserAgent(ua
);
2104 if (NS_WARN_IF(NS_FAILED(rv
))) {
2108 CopyASCIItoUTF16(ua
, aUserAgent
);
2114 // Copy the User-Agent header from the document channel which has already been
2115 // subject to UA overrides.
2116 nsCOMPtr
<Document
> doc
= aWindow
->GetExtantDoc();
2120 nsCOMPtr
<nsIHttpChannel
> httpChannel
= do_QueryInterface(doc
->GetChannel());
2122 nsAutoCString userAgent
;
2123 rv
= httpChannel
->GetRequestHeader("User-Agent"_ns
, userAgent
);
2124 if (NS_WARN_IF(NS_FAILED(rv
))) {
2127 CopyASCIItoUTF16(userAgent
, aUserAgent
);
2132 static nsCString
RequestKeySystemAccessLogString(
2133 const nsAString
& aKeySystem
,
2134 const Sequence
<MediaKeySystemConfiguration
>& aConfigs
,
2135 bool aIsSecureContext
) {
2138 "Navigator::RequestMediaKeySystemAccess(keySystem='%s' options=",
2139 NS_ConvertUTF16toUTF8(aKeySystem
).get());
2140 str
.Append(MediaKeySystemAccess::ToCString(aConfigs
));
2141 str
.AppendLiteral(") secureContext=");
2142 str
.AppendInt(aIsSecureContext
);
2146 already_AddRefed
<Promise
> Navigator::RequestMediaKeySystemAccess(
2147 const nsAString
& aKeySystem
,
2148 const Sequence
<MediaKeySystemConfiguration
>& aConfigs
, ErrorResult
& aRv
) {
2149 EME_LOG("%s", RequestKeySystemAccessLogString(aKeySystem
, aConfigs
,
2150 mWindow
->IsSecureContext())
2153 if (!mWindow
->IsSecureContext()) {
2154 Document
* doc
= mWindow
->GetExtantDoc();
2155 AutoTArray
<nsString
, 1> params
;
2156 nsString
* uri
= params
.AppendElement();
2158 Unused
<< doc
->GetDocumentURI(*uri
);
2160 nsContentUtils::ReportToConsole(nsIScriptError::warningFlag
, "Media"_ns
,
2161 doc
, nsContentUtils::eDOM_PROPERTIES
,
2162 "MediaEMEInsecureContextDeprecatedWarning",
2166 Document
* doc
= mWindow
->GetExtantDoc();
2168 !FeaturePolicyUtils::IsFeatureAllowed(doc
, u
"encrypted-media"_ns
)) {
2169 aRv
.Throw(NS_ERROR_DOM_SECURITY_ERR
);
2173 RefPtr
<DetailedPromise
> promise
= DetailedPromise::Create(
2174 mWindow
->AsGlobal(), aRv
, "navigator.requestMediaKeySystemAccess"_ns
);
2179 if (!mMediaKeySystemAccessManager
) {
2180 mMediaKeySystemAccessManager
= new MediaKeySystemAccessManager(mWindow
);
2183 mMediaKeySystemAccessManager
->Request(promise
, aKeySystem
, aConfigs
);
2184 return promise
.forget();
2187 CredentialsContainer
* Navigator::Credentials() {
2188 if (!mCredentials
) {
2189 mCredentials
= new CredentialsContainer(GetWindow());
2191 return mCredentials
;
2194 dom::MediaCapabilities
* Navigator::MediaCapabilities() {
2195 if (!mMediaCapabilities
) {
2196 mMediaCapabilities
= new dom::MediaCapabilities(GetWindow()->AsGlobal());
2198 return mMediaCapabilities
;
2201 dom::MediaSession
* Navigator::MediaSession() {
2202 if (!mMediaSession
) {
2203 mMediaSession
= new dom::MediaSession(GetWindow());
2205 return mMediaSession
;
2208 bool Navigator::HasCreatedMediaSession() const {
2209 return mMediaSession
!= nullptr;
2212 Clipboard
* Navigator::Clipboard() {
2214 mClipboard
= new dom::Clipboard(GetWindow());
2219 AddonManager
* Navigator::GetMozAddonManager(ErrorResult
& aRv
) {
2220 if (!mAddonManager
) {
2221 nsPIDOMWindowInner
* win
= GetWindow();
2223 aRv
.Throw(NS_ERROR_UNEXPECTED
);
2227 mAddonManager
= ConstructJSImplementation
<AddonManager
>(
2228 "@mozilla.org/addon-web-api/manager;1", win
->AsGlobal(), aRv
);
2234 return mAddonManager
;
2237 webgpu::Instance
* Navigator::Gpu() {
2239 mWebGpu
= webgpu::Instance::Create(GetWindow()->AsGlobal());
2244 dom::LockManager
* Navigator::Locks() {
2246 mLocks
= dom::LockManager::Create(*GetWindow()->AsGlobal());
2252 bool Navigator::Webdriver() {
2253 #ifdef ENABLE_WEBDRIVER
2254 nsCOMPtr
<nsIMarionette
> marionette
= do_GetService(NS_MARIONETTE_CONTRACTID
);
2256 bool marionetteRunning
= false;
2257 marionette
->GetRunning(&marionetteRunning
);
2258 if (marionetteRunning
) {
2263 nsCOMPtr
<nsIRemoteAgent
> agent
= do_GetService(NS_REMOTEAGENT_CONTRACTID
);
2265 bool remoteAgentRunning
= false;
2266 agent
->GetRunning(&remoteAgentRunning
);
2267 if (remoteAgentRunning
) {
2276 AutoplayPolicy
Navigator::GetAutoplayPolicy(AutoplayPolicyMediaType aType
) {
2278 return AutoplayPolicy::Disallowed
;
2280 nsCOMPtr
<Document
> doc
= mWindow
->GetExtantDoc();
2282 return AutoplayPolicy::Disallowed
;
2284 return media::AutoplayPolicy::GetAutoplayPolicy(aType
, *doc
);
2287 AutoplayPolicy
Navigator::GetAutoplayPolicy(HTMLMediaElement
& aElement
) {
2288 return media::AutoplayPolicy::GetAutoplayPolicy(aElement
);
2291 AutoplayPolicy
Navigator::GetAutoplayPolicy(AudioContext
& aContext
) {
2292 return media::AutoplayPolicy::GetAutoplayPolicy(aContext
);
2295 already_AddRefed
<dom::UserActivation
> Navigator::UserActivation() {
2296 if (!mUserActivation
) {
2297 mUserActivation
= new dom::UserActivation(GetWindow());
2299 return do_AddRef(mUserActivation
);
2302 } // namespace mozilla::dom