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/. */
6
7 // Needs to be first.
8 #include "base/basictypes.h"
9
10 #include "Navigator.h"
11 #include "nsIXULAppInfo.h"
12 #include "nsPluginArray.h"
13 #include "nsMimeTypeArray.h"
14 #include "mozilla/MemoryReporting.h"
15 #include "mozilla/dom/BodyExtractor.h"
16 #include "mozilla/dom/FetchBinding.h"
17 #include "mozilla/dom/File.h"
18 #include "nsGeolocation.h"
19 #include "nsIClassOfService.h"
20 #include "nsIHttpProtocolHandler.h"
21 #include "nsIContentPolicy.h"
22 #include "nsIContentSecurityPolicy.h"
23 #include "nsContentPolicyUtils.h"
24 #include "nsISupportsPriority.h"
25 #include "nsICachingChannel.h"
26 #include "nsIWebContentHandlerRegistrar.h"
27 #include "nsICookiePermission.h"
28 #include "nsIScriptSecurityManager.h"
29 #include "nsCharSeparatedTokenizer.h"
30 #include "nsContentUtils.h"
31 #include "nsUnicharUtils.h"
32 #include "mozilla/Preferences.h"
33 #include "mozilla/Telemetry.h"
34 #include "BatteryManager.h"
35 #include "mozilla/dom/CredentialsContainer.h"
36 #include "mozilla/dom/GamepadServiceTest.h"
37 #include "mozilla/dom/WakeLock.h"
38 #include "mozilla/dom/power/PowerManagerService.h"
39 #include "mozilla/dom/MIDIAccessManager.h"
40 #include "mozilla/dom/MIDIOptionsBinding.h"
41 #include "mozilla/dom/Permissions.h"
42 #include "mozilla/dom/Presentation.h"
43 #include "mozilla/dom/ServiceWorkerContainer.h"
44 #include "mozilla/dom/StorageManager.h"
45 #include "mozilla/dom/TCPSocket.h"
46 #include "mozilla/dom/URLSearchParams.h"
47 #include "mozilla/dom/VRDisplay.h"
48 #include "mozilla/dom/VRDisplayEvent.h"
49 #include "mozilla/dom/VRServiceTest.h"
50 #include "mozilla/dom/workerinternals/RuntimeService.h"
51 #include "mozilla/Hal.h"
52 #include "mozilla/ClearOnShutdown.h"
53 #include "mozilla/StaticPtr.h"
54 #include "Connection.h"
55 #include "mozilla/dom/Event.h" // for nsIDOMEvent::InternalDOMEvent()
56 #include "nsGlobalWindow.h"
57 #include "nsIIdleObserver.h"
58 #include "nsIPermissionManager.h"
59 #include "nsMimeTypes.h"
60 #include "nsNetUtil.h"
61 #include "nsRFPService.h"
62 #include "nsStringStream.h"
63 #include "nsComponentManagerUtils.h"
64 #include "nsIStringStream.h"
65 #include "nsIHttpChannel.h"
66 #include "nsIHttpChannelInternal.h"
67 #include "nsStreamUtils.h"
68 #include "WidgetUtils.h"
69 #include "nsIPresentationService.h"
70 #include "nsIScriptError.h"
71
72 #include "mozilla/dom/MediaDevices.h"
73 #include "MediaManager.h"
74
75 #include "nsIDOMGlobalPropertyInitializer.h"
76 #include "nsJSUtils.h"
77
78 #include "nsScriptNameSpaceManager.h"
79
80 #include "mozilla/dom/NavigatorBinding.h"
81 #include "mozilla/dom/Promise.h"
82
83 #include "nsIUploadChannel2.h"
84 #include "mozilla/dom/FormData.h"
85 #include "nsIDocShell.h"
86
87 #include "mozilla/dom/WorkerPrivate.h"
88 #include "mozilla/dom/WorkerRunnable.h"
89
90 #if defined(XP_LINUX)
91 #include "mozilla/Hal.h"
92 #endif
93 #include "mozilla/dom/ContentChild.h"
94
95 #include "mozilla/EMEUtils.h"
96 #include "mozilla/DetailedPromise.h"
97 #include "mozilla/Unused.h"
98
99 namespace mozilla {
100 namespace dom {
101
102 static bool sVibratorEnabled = false;
103 static uint32_t sMaxVibrateMS = 0;
104 static uint32_t sMaxVibrateListLen = 0;
105 static const char* kVibrationPermissionType = "vibration";
106
AddPermission(nsIPrincipal * aPrincipal,const char * aType,uint32_t aPermission,uint32_t aExpireType,int64_t aExpireTime)107 static void AddPermission(nsIPrincipal* aPrincipal, const char* aType,
108 uint32_t aPermission, uint32_t aExpireType,
109 int64_t aExpireTime) {
110 MOZ_ASSERT(aType);
111 MOZ_ASSERT(aPrincipal);
112
113 nsCOMPtr<nsIPermissionManager> permMgr = services::GetPermissionManager();
114 if (!permMgr) {
115 return;
116 }
117 permMgr->AddFromPrincipal(aPrincipal, aType, aPermission, aExpireType,
118 aExpireTime);
119 }
120
GetPermission(nsPIDOMWindowInner * aWindow,const char * aType)121 static uint32_t GetPermission(nsPIDOMWindowInner* aWindow, const char* aType) {
122 MOZ_ASSERT(aType);
123
124 uint32_t permission = nsIPermissionManager::UNKNOWN_ACTION;
125
126 nsCOMPtr<nsIPermissionManager> permMgr = services::GetPermissionManager();
127 if (!permMgr) {
128 return permission;
129 }
130 permMgr->TestPermissionFromWindow(aWindow, aType, &permission);
131 return permission;
132 }
133
GetPermission(nsIPrincipal * aPrincipal,const char * aType)134 static uint32_t GetPermission(nsIPrincipal* aPrincipal, const char* aType) {
135 MOZ_ASSERT(aType);
136 MOZ_ASSERT(aPrincipal);
137
138 uint32_t permission = nsIPermissionManager::UNKNOWN_ACTION;
139
140 nsCOMPtr<nsIPermissionManager> permMgr = services::GetPermissionManager();
141 if (!permMgr) {
142 return permission;
143 }
144 permMgr->TestPermissionFromPrincipal(aPrincipal, aType, &permission);
145 return permission;
146 }
147
148 /* static */
Init()149 void Navigator::Init() {
150 Preferences::AddBoolVarCache(&sVibratorEnabled, "dom.vibrator.enabled", true);
151 Preferences::AddUintVarCache(&sMaxVibrateMS, "dom.vibrator.max_vibrate_ms",
152 10000);
153 Preferences::AddUintVarCache(&sMaxVibrateListLen,
154 "dom.vibrator.max_vibrate_list_len", 128);
155 }
156
Navigator(nsPIDOMWindowInner * aWindow)157 Navigator::Navigator(nsPIDOMWindowInner* aWindow) : mWindow(aWindow) {}
158
~Navigator()159 Navigator::~Navigator() { Invalidate(); }
160
161 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(Navigator)
162 NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
163 NS_INTERFACE_MAP_ENTRY(nsISupports)
164 NS_INTERFACE_MAP_END
165
166 NS_IMPL_CYCLE_COLLECTING_ADDREF(Navigator)
167 NS_IMPL_CYCLE_COLLECTING_RELEASE(Navigator)
168
169 NS_IMPL_CYCLE_COLLECTION_CLASS(Navigator)
170
171 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(Navigator)
172 tmp->Invalidate();
NS_IMPL_CYCLE_COLLECTION_UNLINK(mWindow)173 NS_IMPL_CYCLE_COLLECTION_UNLINK(mWindow)
174 NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
175 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
176
177 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(Navigator)
178 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mMimeTypes)
179 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPlugins)
180 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPermissions)
181 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mGeolocation)
182 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mBatteryManager)
183 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mBatteryPromise)
184 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mConnection)
185 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mStorageManager)
186 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mCredentials)
187 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mMediaDevices)
188 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mServiceWorkerContainer)
189
190 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mWindow)
191 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mMediaKeySystemAccessManager)
192 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPresentation)
193 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mGamepadServiceTest)
194 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mVRGetDisplaysPromises)
195 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mVRServiceTest)
196 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
197
198 NS_IMPL_CYCLE_COLLECTION_TRACE_WRAPPERCACHE(Navigator)
199
200 void Navigator::Invalidate() {
201 // Don't clear mWindow here so we know we've got a non-null mWindow
202 // until we're unlinked.
203
204 mMimeTypes = nullptr;
205
206 if (mPlugins) {
207 mPlugins->Invalidate();
208 mPlugins = nullptr;
209 }
210
211 mPermissions = nullptr;
212
213 mStorageManager = nullptr;
214
215 // If there is a page transition, make sure delete the geolocation object.
216 if (mGeolocation) {
217 mGeolocation->Shutdown();
218 mGeolocation = nullptr;
219 }
220
221 if (mBatteryManager) {
222 mBatteryManager->Shutdown();
223 mBatteryManager = nullptr;
224 }
225
226 mBatteryPromise = nullptr;
227
228 if (mConnection) {
229 mConnection->Shutdown();
230 mConnection = nullptr;
231 }
232
233 mMediaDevices = nullptr;
234
235 if (mPresentation) {
236 mPresentation = nullptr;
237 }
238
239 mServiceWorkerContainer = nullptr;
240
241 if (mMediaKeySystemAccessManager) {
242 mMediaKeySystemAccessManager->Shutdown();
243 mMediaKeySystemAccessManager = nullptr;
244 }
245
246 if (mGamepadServiceTest) {
247 mGamepadServiceTest->Shutdown();
248 mGamepadServiceTest = nullptr;
249 }
250
251 mVRGetDisplaysPromises.Clear();
252
253 if (mVRServiceTest) {
254 mVRServiceTest->Shutdown();
255 mVRServiceTest = nullptr;
256 }
257 }
258
GetUserAgent(nsAString & aUserAgent,CallerType aCallerType,ErrorResult & aRv) const259 void Navigator::GetUserAgent(nsAString& aUserAgent, CallerType aCallerType,
260 ErrorResult& aRv) const {
261 nsCOMPtr<nsPIDOMWindowInner> window;
262
263 if (mWindow) {
264 window = mWindow;
265 nsIDocShell* docshell = window->GetDocShell();
266 nsString customUserAgent;
267 if (docshell) {
268 docshell->GetCustomUserAgent(customUserAgent);
269
270 if (!customUserAgent.IsEmpty()) {
271 aUserAgent = customUserAgent;
272 return;
273 }
274 }
275 }
276
277 nsresult rv =
278 GetUserAgent(window, aCallerType == CallerType::System, aUserAgent);
279 if (NS_WARN_IF(NS_FAILED(rv))) {
280 aRv.Throw(rv);
281 }
282 }
283
GetAppCodeName(nsAString & aAppCodeName,ErrorResult & aRv)284 void Navigator::GetAppCodeName(nsAString& aAppCodeName, ErrorResult& aRv) {
285 nsresult rv;
286
287 nsCOMPtr<nsIHttpProtocolHandler> service(
288 do_GetService(NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX "http", &rv));
289 if (NS_WARN_IF(NS_FAILED(rv))) {
290 aRv.Throw(rv);
291 return;
292 }
293
294 nsAutoCString appName;
295 rv = service->GetAppName(appName);
296 if (NS_WARN_IF(NS_FAILED(rv))) {
297 aRv.Throw(rv);
298 return;
299 }
300
301 CopyASCIItoUTF16(appName, aAppCodeName);
302 }
303
GetAppVersion(nsAString & aAppVersion,CallerType aCallerType,ErrorResult & aRv) const304 void Navigator::GetAppVersion(nsAString& aAppVersion, CallerType aCallerType,
305 ErrorResult& aRv) const {
306 nsresult rv = GetAppVersion(
307 aAppVersion,
308 /* aUsePrefOverriddenValue = */ aCallerType != CallerType::System);
309 if (NS_WARN_IF(NS_FAILED(rv))) {
310 aRv.Throw(rv);
311 }
312 }
313
GetAppName(nsAString & aAppName,CallerType aCallerType) const314 void Navigator::GetAppName(nsAString& aAppName, CallerType aCallerType) const {
315 AppName(aAppName,
316 /* aUsePrefOverriddenValue = */ aCallerType != CallerType::System);
317 }
318
319 /**
320 * Returns the value of Accept-Languages (HTTP header) as a nsTArray of
321 * languages. The value is set in the preference by the user ("Content
322 * Languages").
323 *
324 * "en", "en-US" and "i-cherokee" and "" are valid languages tokens.
325 *
326 * An empty array will be returned if there is no valid languages.
327 */
GetAcceptLanguages(nsTArray<nsString> & aLanguages)328 /* static */ void Navigator::GetAcceptLanguages(
329 nsTArray<nsString>& aLanguages) {
330 MOZ_ASSERT(NS_IsMainThread());
331
332 aLanguages.Clear();
333
334 // E.g. "de-de, en-us,en".
335 nsAutoString acceptLang;
336 Preferences::GetLocalizedString("intl.accept_languages", acceptLang);
337
338 // Split values on commas.
339 nsCharSeparatedTokenizer langTokenizer(acceptLang, ',');
340 while (langTokenizer.hasMoreTokens()) {
341 nsDependentSubstring lang = langTokenizer.nextToken();
342
343 // Replace "_" with "-" to avoid POSIX/Windows "en_US" notation.
344 // NOTE: we should probably rely on the pref being set correctly.
345 if (lang.Length() > 2 && lang[2] == char16_t('_')) {
346 lang.Replace(2, 1, char16_t('-'));
347 }
348
349 // Use uppercase for country part, e.g. "en-US", not "en-us", see BCP47
350 // only uppercase 2-letter country codes, not "zh-Hant", "de-DE-x-goethe".
351 // NOTE: we should probably rely on the pref being set correctly.
352 if (lang.Length() > 2) {
353 nsCharSeparatedTokenizer localeTokenizer(lang, '-');
354 int32_t pos = 0;
355 bool first = true;
356 while (localeTokenizer.hasMoreTokens()) {
357 const nsAString& code = localeTokenizer.nextToken();
358
359 if (code.Length() == 2 && !first) {
360 nsAutoString upper(code);
361 ToUpperCase(upper);
362 lang.Replace(pos, code.Length(), upper);
363 }
364
365 pos += code.Length() + 1; // 1 is the separator
366 first = false;
367 }
368 }
369
370 aLanguages.AppendElement(lang);
371 }
372 }
373
374 /**
375 * Do not use UI language (chosen app locale) here but the first value set in
376 * the Accept Languages header, see ::GetAcceptLanguages().
377 *
378 * See RFC 2616, Section 15.1.4 "Privacy Issues Connected to Accept Headers" for
379 * the reasons why.
380 */
GetLanguage(nsAString & aLanguage)381 void Navigator::GetLanguage(nsAString& aLanguage) {
382 nsTArray<nsString> languages;
383 GetLanguages(languages);
384 if (languages.Length() >= 1) {
385 aLanguage.Assign(languages[0]);
386 } else {
387 aLanguage.Truncate();
388 }
389 }
390
GetLanguages(nsTArray<nsString> & aLanguages)391 void Navigator::GetLanguages(nsTArray<nsString>& aLanguages) {
392 GetAcceptLanguages(aLanguages);
393
394 // The returned value is cached by the binding code. The window listen to the
395 // accept languages change and will clear the cache when needed. It has to
396 // take care of dispatching the DOM event already and the invalidation and the
397 // event has to be timed correctly.
398 }
399
GetPlatform(nsAString & aPlatform,CallerType aCallerType,ErrorResult & aRv) const400 void Navigator::GetPlatform(nsAString& aPlatform, CallerType aCallerType,
401 ErrorResult& aRv) const {
402 nsresult rv = GetPlatform(
403 aPlatform,
404 /* aUsePrefOverriddenValue = */ aCallerType != CallerType::System);
405 if (NS_WARN_IF(NS_FAILED(rv))) {
406 aRv.Throw(rv);
407 }
408 }
409
GetOscpu(nsAString & aOSCPU,CallerType aCallerType,ErrorResult & aRv) const410 void Navigator::GetOscpu(nsAString& aOSCPU, CallerType aCallerType,
411 ErrorResult& aRv) const {
412 if (aCallerType != CallerType::System) {
413 // If fingerprinting resistance is on, we will spoof this value. See
414 // nsRFPService.h for details about spoofed values.
415 if (nsContentUtils::ShouldResistFingerprinting()) {
416 aOSCPU.AssignLiteral(SPOOFED_OSCPU);
417 return;
418 }
419
420 nsAutoString override;
421 nsresult rv = Preferences::GetString("general.oscpu.override", override);
422 if (NS_SUCCEEDED(rv)) {
423 aOSCPU = override;
424 return;
425 }
426 }
427
428 nsresult rv;
429 nsCOMPtr<nsIHttpProtocolHandler> service(
430 do_GetService(NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX "http", &rv));
431 if (NS_WARN_IF(NS_FAILED(rv))) {
432 aRv.Throw(rv);
433 return;
434 }
435
436 nsAutoCString oscpu;
437 rv = service->GetOscpu(oscpu);
438 if (NS_WARN_IF(NS_FAILED(rv))) {
439 aRv.Throw(rv);
440 return;
441 }
442
443 CopyASCIItoUTF16(oscpu, aOSCPU);
444 }
445
GetVendor(nsAString & aVendor)446 void Navigator::GetVendor(nsAString& aVendor) { aVendor.Truncate(); }
447
GetVendorSub(nsAString & aVendorSub)448 void Navigator::GetVendorSub(nsAString& aVendorSub) { aVendorSub.Truncate(); }
449
GetProduct(nsAString & aProduct)450 void Navigator::GetProduct(nsAString& aProduct) {
451 aProduct.AssignLiteral("Gecko");
452 }
453
GetProductSub(nsAString & aProductSub)454 void Navigator::GetProductSub(nsAString& aProductSub) {
455 // Legacy build ID hardcoded for backward compatibility (bug 776376)
456 aProductSub.AssignLiteral(LEGACY_BUILD_ID);
457 }
458
GetMimeTypes(ErrorResult & aRv)459 nsMimeTypeArray* Navigator::GetMimeTypes(ErrorResult& aRv) {
460 if (!mMimeTypes) {
461 if (!mWindow) {
462 aRv.Throw(NS_ERROR_UNEXPECTED);
463 return nullptr;
464 }
465 mMimeTypes = new nsMimeTypeArray(mWindow);
466 }
467
468 return mMimeTypes;
469 }
470
GetPlugins(ErrorResult & aRv)471 nsPluginArray* Navigator::GetPlugins(ErrorResult& aRv) {
472 if (!mPlugins) {
473 if (!mWindow) {
474 aRv.Throw(NS_ERROR_UNEXPECTED);
475 return nullptr;
476 }
477 mPlugins = new nsPluginArray(mWindow);
478 mPlugins->Init();
479 }
480
481 return mPlugins;
482 }
483
GetPermissions(ErrorResult & aRv)484 Permissions* Navigator::GetPermissions(ErrorResult& aRv) {
485 if (!mWindow) {
486 aRv.Throw(NS_ERROR_UNEXPECTED);
487 return nullptr;
488 }
489
490 if (!mPermissions) {
491 mPermissions = new Permissions(mWindow);
492 }
493
494 return mPermissions;
495 }
496
Storage()497 StorageManager* Navigator::Storage() {
498 MOZ_ASSERT(mWindow);
499
500 if (!mStorageManager) {
501 mStorageManager = new StorageManager(mWindow->AsGlobal());
502 }
503
504 return mStorageManager;
505 }
506
507 // Values for the network.cookie.cookieBehavior pref are documented in
508 // nsCookieService.cpp.
509 #define COOKIE_BEHAVIOR_REJECT 2
510
CookieEnabled()511 bool Navigator::CookieEnabled() {
512 bool cookieEnabled =
513 (Preferences::GetInt("network.cookie.cookieBehavior",
514 COOKIE_BEHAVIOR_REJECT) != COOKIE_BEHAVIOR_REJECT);
515
516 // Check whether an exception overrides the global cookie behavior
517 // Note that the code for getting the URI here matches that in
518 // nsHTMLDocument::SetCookie.
519 if (!mWindow || !mWindow->GetDocShell()) {
520 return cookieEnabled;
521 }
522
523 nsCOMPtr<nsIDocument> doc = mWindow->GetExtantDoc();
524 if (!doc) {
525 return cookieEnabled;
526 }
527
528 nsCOMPtr<nsIURI> codebaseURI;
529 doc->NodePrincipal()->GetURI(getter_AddRefs(codebaseURI));
530
531 if (!codebaseURI) {
532 // Not a codebase, so technically can't set cookies, but let's
533 // just return the default value.
534 return cookieEnabled;
535 }
536
537 nsCOMPtr<nsICookiePermission> permMgr =
538 do_GetService(NS_COOKIEPERMISSION_CONTRACTID);
539 NS_ENSURE_TRUE(permMgr, cookieEnabled);
540
541 // Pass null for the channel, just like the cookie service does.
542 nsCookieAccess access;
543 nsresult rv = permMgr->CanAccess(doc->NodePrincipal(), &access);
544 NS_ENSURE_SUCCESS(rv, cookieEnabled);
545
546 if (access != nsICookiePermission::ACCESS_DEFAULT) {
547 cookieEnabled = access != nsICookiePermission::ACCESS_DENY;
548 }
549
550 return cookieEnabled;
551 }
552
OnLine()553 bool Navigator::OnLine() { return !NS_IsOffline(); }
554
GetBuildID(nsAString & aBuildID,CallerType aCallerType,ErrorResult & aRv) const555 void Navigator::GetBuildID(nsAString& aBuildID, CallerType aCallerType,
556 ErrorResult& aRv) const {
557 if (aCallerType != CallerType::System) {
558 // If fingerprinting resistance is on, we will spoof this value. See
559 // nsRFPService.h for details about spoofed values.
560 if (nsContentUtils::ShouldResistFingerprinting()) {
561 aBuildID.AssignLiteral(LEGACY_BUILD_ID);
562 return;
563 }
564 nsAutoString override;
565 nsresult rv = Preferences::GetString("general.buildID.override", override);
566 if (NS_SUCCEEDED(rv)) {
567 aBuildID = override;
568 return;
569 }
570 }
571
572 nsCOMPtr<nsIXULAppInfo> appInfo =
573 do_GetService("@mozilla.org/xre/app-info;1");
574 if (!appInfo) {
575 aRv.Throw(NS_ERROR_NOT_IMPLEMENTED);
576 return;
577 }
578
579 nsAutoCString buildID;
580 nsresult rv = appInfo->GetAppBuildID(buildID);
581 if (NS_WARN_IF(NS_FAILED(rv))) {
582 aRv.Throw(rv);
583 return;
584 }
585
586 aBuildID.Truncate();
587 AppendASCIItoUTF16(buildID, aBuildID);
588 }
589
GetDoNotTrack(nsAString & aResult)590 void Navigator::GetDoNotTrack(nsAString& aResult) {
591 bool doNotTrack = nsContentUtils::DoNotTrackEnabled();
592 if (!doNotTrack) {
593 nsCOMPtr<nsILoadContext> loadContext = do_GetInterface(mWindow);
594 doNotTrack = loadContext && loadContext->UseTrackingProtection();
595 }
596
597 if (doNotTrack) {
598 aResult.AssignLiteral("1");
599 } else {
600 aResult.AssignLiteral("unspecified");
601 }
602 }
603
JavaEnabled(CallerType aCallerType,ErrorResult & aRv)604 bool Navigator::JavaEnabled(CallerType aCallerType, ErrorResult& aRv) {
605 Telemetry::AutoTimer<Telemetry::CHECK_JAVA_ENABLED> telemetryTimer;
606
607 // Return true if we have a handler for the java mime
608 nsAutoString javaMIME;
609 Preferences::GetString("plugin.java.mime", javaMIME);
610 NS_ENSURE_TRUE(!javaMIME.IsEmpty(), false);
611
612 if (!mMimeTypes) {
613 if (!mWindow) {
614 aRv.Throw(NS_ERROR_UNEXPECTED);
615 return false;
616 }
617 mMimeTypes = new nsMimeTypeArray(mWindow);
618 }
619
620 RefreshMIMEArray();
621
622 nsMimeType* mimeType = mMimeTypes->NamedItem(javaMIME, aCallerType);
623
624 return mimeType && mimeType->GetEnabledPlugin();
625 }
626
HardwareConcurrency()627 uint64_t Navigator::HardwareConcurrency() {
628 workerinternals::RuntimeService* rts =
629 workerinternals::RuntimeService::GetOrCreateService();
630 if (!rts) {
631 return 1;
632 }
633
634 return rts->ClampedHardwareConcurrency();
635 }
636
RefreshMIMEArray()637 void Navigator::RefreshMIMEArray() {
638 if (mMimeTypes) {
639 mMimeTypes->Refresh();
640 }
641 }
642
643 namespace {
644
645 class VibrateWindowListener : public nsIDOMEventListener {
646 public:
VibrateWindowListener(nsPIDOMWindowInner * aWindow,nsIDocument * aDocument)647 VibrateWindowListener(nsPIDOMWindowInner* aWindow, nsIDocument* aDocument) {
648 mWindow = do_GetWeakReference(aWindow);
649 mDocument = do_GetWeakReference(aDocument);
650
651 NS_NAMED_LITERAL_STRING(visibilitychange, "visibilitychange");
652 aDocument->AddSystemEventListener(visibilitychange, this, /* listener */
653 true, /* use capture */
654 false /* wants untrusted */);
655 }
656
657 void RemoveListener();
658
659 NS_DECL_ISUPPORTS
660 NS_DECL_NSIDOMEVENTLISTENER
661
662 private:
~VibrateWindowListener()663 virtual ~VibrateWindowListener() {}
664
665 nsWeakPtr mWindow;
666 nsWeakPtr mDocument;
667 };
668
669 NS_IMPL_ISUPPORTS(VibrateWindowListener, nsIDOMEventListener)
670
671 StaticRefPtr<VibrateWindowListener> gVibrateWindowListener;
672
MayVibrate(nsIDocument * doc)673 static bool MayVibrate(nsIDocument* doc) {
674 // Hidden documents cannot start or stop a vibration.
675 return (doc && !doc->Hidden());
676 }
677
678 NS_IMETHODIMP
HandleEvent(nsIDOMEvent * aEvent)679 VibrateWindowListener::HandleEvent(nsIDOMEvent* aEvent) {
680 nsCOMPtr<nsIDocument> doc =
681 do_QueryInterface(aEvent->InternalDOMEvent()->GetTarget());
682
683 if (!MayVibrate(doc)) {
684 // It's important that we call CancelVibrate(), not Vibrate() with an
685 // empty list, because Vibrate() will fail if we're no longer focused, but
686 // CancelVibrate() will succeed, so long as nobody else has started a new
687 // vibration pattern.
688 nsCOMPtr<nsPIDOMWindowInner> window = do_QueryReferent(mWindow);
689 hal::CancelVibrate(window);
690 RemoveListener();
691 gVibrateWindowListener = nullptr;
692 // Careful: The line above might have deleted |this|!
693 }
694
695 return NS_OK;
696 }
697
RemoveListener()698 void VibrateWindowListener::RemoveListener() {
699 nsCOMPtr<EventTarget> target = do_QueryReferent(mDocument);
700 if (!target) {
701 return;
702 }
703 NS_NAMED_LITERAL_STRING(visibilitychange, "visibilitychange");
704 target->RemoveSystemEventListener(visibilitychange, this,
705 true /* use capture */);
706 }
707
708 } // namespace
709
AddIdleObserver(MozIdleObserver & aIdleObserver,ErrorResult & aRv)710 void Navigator::AddIdleObserver(MozIdleObserver& aIdleObserver,
711 ErrorResult& aRv) {
712 if (!mWindow) {
713 aRv.Throw(NS_ERROR_UNEXPECTED);
714 return;
715 }
716 CallbackObjectHolder<MozIdleObserver, nsIIdleObserver> holder(&aIdleObserver);
717 nsCOMPtr<nsIIdleObserver> obs = holder.ToXPCOMCallback();
718 if (NS_FAILED(mWindow->RegisterIdleObserver(obs))) {
719 NS_WARNING("Failed to add idle observer.");
720 }
721 }
722
RemoveIdleObserver(MozIdleObserver & aIdleObserver,ErrorResult & aRv)723 void Navigator::RemoveIdleObserver(MozIdleObserver& aIdleObserver,
724 ErrorResult& aRv) {
725 if (!mWindow) {
726 aRv.Throw(NS_ERROR_UNEXPECTED);
727 return;
728 }
729 CallbackObjectHolder<MozIdleObserver, nsIIdleObserver> holder(&aIdleObserver);
730 nsCOMPtr<nsIIdleObserver> obs = holder.ToXPCOMCallback();
731 if (NS_FAILED(mWindow->UnregisterIdleObserver(obs))) {
732 NS_WARNING("Failed to remove idle observer.");
733 }
734 }
735
SetVibrationPermission(bool aPermitted,bool aPersistent)736 void Navigator::SetVibrationPermission(bool aPermitted, bool aPersistent) {
737 MOZ_ASSERT(NS_IsMainThread());
738
739 nsTArray<uint32_t> pattern;
740 pattern.SwapElements(mRequestedVibrationPattern);
741
742 if (!mWindow) {
743 return;
744 }
745
746 nsCOMPtr<nsIDocument> doc = mWindow->GetExtantDoc();
747
748 if (!MayVibrate(doc)) {
749 return;
750 }
751
752 if (aPermitted) {
753 // Add a listener to cancel the vibration if the document becomes hidden,
754 // and remove the old visibility listener, if there was one.
755 if (!gVibrateWindowListener) {
756 // If gVibrateWindowListener is null, this is the first time we've
757 // vibrated, and we need to register a listener to clear
758 // gVibrateWindowListener on shutdown.
759 ClearOnShutdown(&gVibrateWindowListener);
760 } else {
761 gVibrateWindowListener->RemoveListener();
762 }
763 gVibrateWindowListener = new VibrateWindowListener(mWindow, doc);
764 hal::Vibrate(pattern, mWindow);
765 }
766
767 if (aPersistent) {
768 AddPermission(doc->NodePrincipal(), kVibrationPermissionType,
769 aPermitted ? nsIPermissionManager::ALLOW_ACTION
770 : nsIPermissionManager::DENY_ACTION,
771 nsIPermissionManager::EXPIRE_SESSION, 0);
772 }
773 }
774
Vibrate(uint32_t aDuration)775 bool Navigator::Vibrate(uint32_t aDuration) {
776 AutoTArray<uint32_t, 1> pattern;
777 pattern.AppendElement(aDuration);
778 return Vibrate(pattern);
779 }
780
Vibrate(const nsTArray<uint32_t> & aPattern)781 bool Navigator::Vibrate(const nsTArray<uint32_t>& aPattern) {
782 MOZ_ASSERT(NS_IsMainThread());
783
784 if (!mWindow) {
785 return false;
786 }
787
788 nsCOMPtr<nsIDocument> doc = mWindow->GetExtantDoc();
789
790 if (!MayVibrate(doc)) {
791 return false;
792 }
793
794 nsTArray<uint32_t> pattern(aPattern);
795
796 if (pattern.Length() > sMaxVibrateListLen) {
797 pattern.SetLength(sMaxVibrateListLen);
798 }
799
800 for (size_t i = 0; i < pattern.Length(); ++i) {
801 pattern[i] = std::min(sMaxVibrateMS, pattern[i]);
802 }
803
804 // The spec says we check sVibratorEnabled after we've done the sanity
805 // checking on the pattern.
806 if (!sVibratorEnabled) {
807 return true;
808 }
809
810 mRequestedVibrationPattern.SwapElements(pattern);
811 uint32_t permission = GetPermission(mWindow, kVibrationPermissionType);
812
813 if (permission == nsIPermissionManager::ALLOW_ACTION ||
814 mRequestedVibrationPattern.IsEmpty() ||
815 (mRequestedVibrationPattern.Length() == 1 &&
816 mRequestedVibrationPattern[0] == 0)) {
817 // Always allow cancelling vibration and respect session permissions.
818 SetVibrationPermission(true /* permitted */, false /* persistent */);
819 return true;
820 }
821
822 nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
823 if (!obs || permission == nsIPermissionManager::DENY_ACTION) {
824 // Abort without observer service or on denied session permission.
825 SetVibrationPermission(false /* permitted */, false /* persistent */);
826 return true;
827 }
828
829 // Request user permission.
830 obs->NotifyObservers(ToSupports(this), "Vibration:Request", nullptr);
831
832 return true;
833 }
834
835 //*****************************************************************************
836 // Pointer Events interface
837 //*****************************************************************************
838
MaxTouchPoints()839 uint32_t Navigator::MaxTouchPoints() {
840 nsCOMPtr<nsIWidget> widget =
841 widget::WidgetUtils::DOMWindowToWidget(mWindow->GetOuterWindow());
842
843 NS_ENSURE_TRUE(widget, 0);
844 return widget->GetMaxTouchPoints();
845 }
846
847 //*****************************************************************************
848 // Navigator::nsIDOMClientInformation
849 //*****************************************************************************
850
RegisterContentHandler(const nsAString & aMIMEType,const nsAString & aURI,const nsAString & aTitle,ErrorResult & aRv)851 void Navigator::RegisterContentHandler(const nsAString& aMIMEType,
852 const nsAString& aURI,
853 const nsAString& aTitle,
854 ErrorResult& aRv) {
855 if (!mWindow || !mWindow->GetOuterWindow() || !mWindow->GetDocShell()) {
856 return;
857 }
858
859 nsCOMPtr<nsIWebContentHandlerRegistrar> registrar =
860 do_GetService(NS_WEBCONTENTHANDLERREGISTRAR_CONTRACTID);
861 if (!registrar) {
862 return;
863 }
864
865 aRv = registrar->RegisterContentHandler(aMIMEType, aURI, aTitle,
866 mWindow->GetOuterWindow());
867 }
868
RegisterProtocolHandler(const nsAString & aProtocol,const nsAString & aURI,const nsAString & aTitle,ErrorResult & aRv)869 void Navigator::RegisterProtocolHandler(const nsAString& aProtocol,
870 const nsAString& aURI,
871 const nsAString& aTitle,
872 ErrorResult& aRv) {
873 if (!mWindow || !mWindow->GetOuterWindow() || !mWindow->GetDocShell()) {
874 return;
875 }
876
877 if (!mWindow->IsSecureContext() && mWindow->GetDoc()) {
878 mWindow->GetDoc()->WarnOnceAbout(
879 nsIDocument::eRegisterProtocolHandlerInsecure);
880 }
881
882 nsCOMPtr<nsIWebContentHandlerRegistrar> registrar =
883 do_GetService(NS_WEBCONTENTHANDLERREGISTRAR_CONTRACTID);
884 if (!registrar) {
885 return;
886 }
887
888 aRv = registrar->RegisterProtocolHandler(aProtocol, aURI, aTitle,
889 mWindow->GetOuterWindow());
890 }
891
GetGeolocation(ErrorResult & aRv)892 Geolocation* Navigator::GetGeolocation(ErrorResult& aRv) {
893 if (mGeolocation) {
894 return mGeolocation;
895 }
896
897 if (!mWindow || !mWindow->GetOuterWindow() || !mWindow->GetDocShell()) {
898 aRv.Throw(NS_ERROR_FAILURE);
899 return nullptr;
900 }
901
902 mGeolocation = new Geolocation();
903 if (NS_FAILED(mGeolocation->Init(mWindow))) {
904 mGeolocation = nullptr;
905 aRv.Throw(NS_ERROR_FAILURE);
906 return nullptr;
907 }
908
909 return mGeolocation;
910 }
911
912 class BeaconStreamListener final : public nsIStreamListener {
~BeaconStreamListener()913 ~BeaconStreamListener() {}
914
915 public:
BeaconStreamListener()916 BeaconStreamListener() : mLoadGroup(nullptr) {}
917
SetLoadGroup(nsILoadGroup * aLoadGroup)918 void SetLoadGroup(nsILoadGroup* aLoadGroup) { mLoadGroup = aLoadGroup; }
919
920 NS_DECL_ISUPPORTS
921 NS_DECL_NSISTREAMLISTENER
922 NS_DECL_NSIREQUESTOBSERVER
923
924 private:
925 nsCOMPtr<nsILoadGroup> mLoadGroup;
926 };
927
NS_IMPL_ISUPPORTS(BeaconStreamListener,nsIStreamListener,nsIRequestObserver)928 NS_IMPL_ISUPPORTS(BeaconStreamListener, nsIStreamListener, nsIRequestObserver)
929
930 NS_IMETHODIMP
931 BeaconStreamListener::OnStartRequest(nsIRequest* aRequest,
932 nsISupports* aContext) {
933 // release the loadgroup first
934 mLoadGroup = nullptr;
935
936 aRequest->Cancel(NS_ERROR_NET_INTERRUPT);
937 return NS_BINDING_ABORTED;
938 }
939
940 NS_IMETHODIMP
OnStopRequest(nsIRequest * aRequest,nsISupports * aContext,nsresult aStatus)941 BeaconStreamListener::OnStopRequest(nsIRequest* aRequest, nsISupports* aContext,
942 nsresult aStatus) {
943 return NS_OK;
944 }
945
946 NS_IMETHODIMP
OnDataAvailable(nsIRequest * aRequest,nsISupports * ctxt,nsIInputStream * inStr,uint64_t sourceOffset,uint32_t count)947 BeaconStreamListener::OnDataAvailable(nsIRequest* aRequest, nsISupports* ctxt,
948 nsIInputStream* inStr,
949 uint64_t sourceOffset, uint32_t count) {
950 MOZ_ASSERT(false);
951 return NS_OK;
952 }
953
SendBeacon(const nsAString & aUrl,const Nullable<fetch::BodyInit> & aData,ErrorResult & aRv)954 bool Navigator::SendBeacon(const nsAString& aUrl,
955 const Nullable<fetch::BodyInit>& aData,
956 ErrorResult& aRv) {
957 if (aData.IsNull()) {
958 return SendBeaconInternal(aUrl, nullptr, eBeaconTypeOther, aRv);
959 }
960
961 if (aData.Value().IsArrayBuffer()) {
962 BodyExtractor<const ArrayBuffer> body(&aData.Value().GetAsArrayBuffer());
963 return SendBeaconInternal(aUrl, &body, eBeaconTypeArrayBuffer, aRv);
964 }
965
966 if (aData.Value().IsArrayBufferView()) {
967 BodyExtractor<const ArrayBufferView> body(
968 &aData.Value().GetAsArrayBufferView());
969 return SendBeaconInternal(aUrl, &body, eBeaconTypeArrayBuffer, aRv);
970 }
971
972 if (aData.Value().IsBlob()) {
973 BodyExtractor<const Blob> body(&aData.Value().GetAsBlob());
974 return SendBeaconInternal(aUrl, &body, eBeaconTypeBlob, aRv);
975 }
976
977 if (aData.Value().IsFormData()) {
978 BodyExtractor<const FormData> body(&aData.Value().GetAsFormData());
979 return SendBeaconInternal(aUrl, &body, eBeaconTypeOther, aRv);
980 }
981
982 if (aData.Value().IsUSVString()) {
983 BodyExtractor<const nsAString> body(&aData.Value().GetAsUSVString());
984 return SendBeaconInternal(aUrl, &body, eBeaconTypeOther, aRv);
985 }
986
987 if (aData.Value().IsURLSearchParams()) {
988 BodyExtractor<const URLSearchParams> body(
989 &aData.Value().GetAsURLSearchParams());
990 return SendBeaconInternal(aUrl, &body, eBeaconTypeOther, aRv);
991 }
992
993 MOZ_CRASH("Invalid data type.");
994 return false;
995 }
996
SendBeaconInternal(const nsAString & aUrl,BodyExtractorBase * aBody,BeaconType aType,ErrorResult & aRv)997 bool Navigator::SendBeaconInternal(const nsAString& aUrl,
998 BodyExtractorBase* aBody, BeaconType aType,
999 ErrorResult& aRv) {
1000 if (!mWindow) {
1001 aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
1002 return false;
1003 }
1004
1005 nsCOMPtr<nsIDocument> doc = mWindow->GetDoc();
1006 if (!doc) {
1007 aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
1008 return false;
1009 }
1010
1011 nsIURI* documentURI = doc->GetDocumentURI();
1012 if (!documentURI) {
1013 aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
1014 return false;
1015 }
1016
1017 nsCOMPtr<nsIURI> uri;
1018 nsresult rv = nsContentUtils::NewURIWithDocumentCharset(
1019 getter_AddRefs(uri), aUrl, doc, doc->GetDocBaseURI());
1020 if (NS_FAILED(rv)) {
1021 aRv.ThrowTypeError<MSG_INVALID_URL>(aUrl);
1022 return false;
1023 }
1024
1025 // Spec disallows any schemes save for HTTP/HTTPs
1026 bool isValidScheme;
1027 if (!(NS_SUCCEEDED(uri->SchemeIs("http", &isValidScheme)) && isValidScheme) &&
1028 !(NS_SUCCEEDED(uri->SchemeIs("https", &isValidScheme)) &&
1029 isValidScheme)) {
1030 aRv.ThrowTypeError<MSG_INVALID_URL_SCHEME>(NS_LITERAL_STRING("Beacon"),
1031 aUrl);
1032 return false;
1033 }
1034
1035 nsLoadFlags loadFlags =
1036 nsIRequest::LOAD_NORMAL | nsIChannel::LOAD_CLASSIFY_URI;
1037
1038 // No need to use CORS for sendBeacon unless it's a BLOB
1039 nsSecurityFlags securityFlags =
1040 aType == eBeaconTypeBlob
1041 ? nsILoadInfo::SEC_REQUIRE_CORS_DATA_INHERITS
1042 : nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_DATA_INHERITS;
1043 securityFlags |= nsILoadInfo::SEC_COOKIES_INCLUDE;
1044
1045 nsCOMPtr<nsIChannel> channel;
1046 rv = NS_NewChannel(getter_AddRefs(channel), uri, doc, securityFlags,
1047 nsIContentPolicy::TYPE_BEACON,
1048 nullptr, // aPerformanceStorage
1049 nullptr, // aLoadGroup
1050 nullptr, // aCallbacks
1051 loadFlags);
1052
1053 if (NS_FAILED(rv)) {
1054 aRv.Throw(rv);
1055 return false;
1056 }
1057
1058 nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(channel);
1059 if (!httpChannel) {
1060 // Beacon spec only supports HTTP requests at this time
1061 aRv.Throw(NS_ERROR_DOM_BAD_URI);
1062 return false;
1063 }
1064 mozilla::net::ReferrerPolicy referrerPolicy = doc->GetReferrerPolicy();
1065 rv = httpChannel->SetReferrerWithPolicy(documentURI, referrerPolicy);
1066 MOZ_ASSERT(NS_SUCCEEDED(rv));
1067
1068 nsCOMPtr<nsIInputStream> in;
1069 nsAutoCString contentTypeWithCharset;
1070 nsAutoCString charset;
1071 uint64_t length = 0;
1072
1073 if (aBody) {
1074 aRv = aBody->GetAsStream(getter_AddRefs(in), &length,
1075 contentTypeWithCharset, charset);
1076 if (NS_WARN_IF(aRv.Failed())) {
1077 return false;
1078 }
1079
1080 nsCOMPtr<nsIUploadChannel2> uploadChannel = do_QueryInterface(channel);
1081 if (!uploadChannel) {
1082 aRv.Throw(NS_ERROR_FAILURE);
1083 return false;
1084 }
1085
1086 uploadChannel->ExplicitSetUploadStream(in, contentTypeWithCharset, length,
1087 NS_LITERAL_CSTRING("POST"), false);
1088 } else {
1089 rv = httpChannel->SetRequestMethod(NS_LITERAL_CSTRING("POST"));
1090 MOZ_ASSERT(NS_SUCCEEDED(rv));
1091 }
1092
1093 nsCOMPtr<nsISupportsPriority> p = do_QueryInterface(channel);
1094 if (p) {
1095 p->SetPriority(nsISupportsPriority::PRIORITY_LOWEST);
1096 }
1097
1098 nsCOMPtr<nsIClassOfService> cos(do_QueryInterface(channel));
1099 if (cos) {
1100 cos->AddClassFlags(nsIClassOfService::Background);
1101 }
1102
1103 // The channel needs to have a loadgroup associated with it, so that we can
1104 // cancel the channel and any redirected channels it may create.
1105 nsCOMPtr<nsILoadGroup> loadGroup = do_CreateInstance(NS_LOADGROUP_CONTRACTID);
1106 nsCOMPtr<nsIInterfaceRequestor> callbacks =
1107 do_QueryInterface(mWindow->GetDocShell());
1108 loadGroup->SetNotificationCallbacks(callbacks);
1109 channel->SetLoadGroup(loadGroup);
1110
1111 RefPtr<BeaconStreamListener> beaconListener = new BeaconStreamListener();
1112 rv = channel->AsyncOpen2(beaconListener);
1113 // do not throw if security checks fail within asyncOpen2
1114 NS_ENSURE_SUCCESS(rv, false);
1115
1116 // make the beaconListener hold a strong reference to the loadgroup
1117 // which is released in ::OnStartRequest
1118 beaconListener->SetLoadGroup(loadGroup);
1119
1120 return true;
1121 }
1122
GetMediaDevices(ErrorResult & aRv)1123 MediaDevices* Navigator::GetMediaDevices(ErrorResult& aRv) {
1124 if (!mMediaDevices) {
1125 if (!mWindow || !mWindow->GetOuterWindow() ||
1126 mWindow->GetOuterWindow()->GetCurrentInnerWindow() != mWindow) {
1127 aRv.Throw(NS_ERROR_NOT_AVAILABLE);
1128 return nullptr;
1129 }
1130 mMediaDevices = new MediaDevices(mWindow);
1131 }
1132 return mMediaDevices;
1133 }
1134
MozGetUserMedia(const MediaStreamConstraints & aConstraints,NavigatorUserMediaSuccessCallback & aOnSuccess,NavigatorUserMediaErrorCallback & aOnError,CallerType aCallerType,ErrorResult & aRv)1135 void Navigator::MozGetUserMedia(const MediaStreamConstraints& aConstraints,
1136 NavigatorUserMediaSuccessCallback& aOnSuccess,
1137 NavigatorUserMediaErrorCallback& aOnError,
1138 CallerType aCallerType, ErrorResult& aRv) {
1139 CallbackObjectHolder<NavigatorUserMediaSuccessCallback,
1140 nsIDOMGetUserMediaSuccessCallback>
1141 holder1(&aOnSuccess);
1142 nsCOMPtr<nsIDOMGetUserMediaSuccessCallback> onsuccess =
1143 holder1.ToXPCOMCallback();
1144
1145 CallbackObjectHolder<NavigatorUserMediaErrorCallback,
1146 nsIDOMGetUserMediaErrorCallback>
1147 holder2(&aOnError);
1148 nsCOMPtr<nsIDOMGetUserMediaErrorCallback> onerror = holder2.ToXPCOMCallback();
1149
1150 if (!mWindow || !mWindow->GetOuterWindow() ||
1151 mWindow->GetOuterWindow()->GetCurrentInnerWindow() != mWindow) {
1152 aRv.Throw(NS_ERROR_NOT_AVAILABLE);
1153 return;
1154 }
1155
1156 MediaManager* manager = MediaManager::Get();
1157 aRv = manager->GetUserMedia(mWindow, aConstraints, onsuccess, onerror,
1158 aCallerType);
1159 }
1160
MozGetUserMediaDevices(const MediaStreamConstraints & aConstraints,MozGetUserMediaDevicesSuccessCallback & aOnSuccess,NavigatorUserMediaErrorCallback & aOnError,uint64_t aInnerWindowID,const nsAString & aCallID,ErrorResult & aRv)1161 void Navigator::MozGetUserMediaDevices(
1162 const MediaStreamConstraints& aConstraints,
1163 MozGetUserMediaDevicesSuccessCallback& aOnSuccess,
1164 NavigatorUserMediaErrorCallback& aOnError, uint64_t aInnerWindowID,
1165 const nsAString& aCallID, ErrorResult& aRv) {
1166 CallbackObjectHolder<MozGetUserMediaDevicesSuccessCallback,
1167 nsIGetUserMediaDevicesSuccessCallback>
1168 holder1(&aOnSuccess);
1169 nsCOMPtr<nsIGetUserMediaDevicesSuccessCallback> onsuccess =
1170 holder1.ToXPCOMCallback();
1171
1172 CallbackObjectHolder<NavigatorUserMediaErrorCallback,
1173 nsIDOMGetUserMediaErrorCallback>
1174 holder2(&aOnError);
1175 nsCOMPtr<nsIDOMGetUserMediaErrorCallback> onerror = holder2.ToXPCOMCallback();
1176
1177 if (!mWindow || !mWindow->GetOuterWindow() ||
1178 mWindow->GetOuterWindow()->GetCurrentInnerWindow() != mWindow) {
1179 aRv.Throw(NS_ERROR_NOT_AVAILABLE);
1180 return;
1181 }
1182
1183 MediaManager* manager = MediaManager::Get();
1184 aRv = manager->GetUserMediaDevices(mWindow, aConstraints, onsuccess, onerror,
1185 aInnerWindowID, aCallID);
1186 }
1187
1188 //*****************************************************************************
1189 // Navigator::nsINavigatorBattery
1190 //*****************************************************************************
1191
GetBattery(ErrorResult & aRv)1192 Promise* Navigator::GetBattery(ErrorResult& aRv) {
1193 if (mBatteryPromise) {
1194 return mBatteryPromise;
1195 }
1196
1197 if (!mWindow || !mWindow->GetDocShell()) {
1198 aRv.Throw(NS_ERROR_UNEXPECTED);
1199 return nullptr;
1200 }
1201
1202 RefPtr<Promise> batteryPromise = Promise::Create(mWindow->AsGlobal(), aRv);
1203 if (NS_WARN_IF(aRv.Failed())) {
1204 return nullptr;
1205 }
1206 mBatteryPromise = batteryPromise;
1207
1208 if (!mBatteryManager) {
1209 mBatteryManager = new battery::BatteryManager(mWindow);
1210 mBatteryManager->Init();
1211 }
1212
1213 mBatteryPromise->MaybeResolve(mBatteryManager);
1214
1215 return mBatteryPromise;
1216 }
1217
MozTCPSocket()1218 already_AddRefed<LegacyMozTCPSocket> Navigator::MozTCPSocket() {
1219 RefPtr<LegacyMozTCPSocket> socket = new LegacyMozTCPSocket(GetWindow());
1220 return socket.forget();
1221 }
1222
GetGamepads(nsTArray<RefPtr<Gamepad>> & aGamepads,ErrorResult & aRv)1223 void Navigator::GetGamepads(nsTArray<RefPtr<Gamepad>>& aGamepads,
1224 ErrorResult& aRv) {
1225 if (!mWindow) {
1226 aRv.Throw(NS_ERROR_UNEXPECTED);
1227 return;
1228 }
1229 NS_ENSURE_TRUE_VOID(mWindow->GetDocShell());
1230 nsGlobalWindowInner* win = nsGlobalWindowInner::Cast(mWindow);
1231 win->SetHasGamepadEventListener(true);
1232 win->GetGamepads(aGamepads);
1233 }
1234
RequestGamepadServiceTest()1235 GamepadServiceTest* Navigator::RequestGamepadServiceTest() {
1236 if (!mGamepadServiceTest) {
1237 mGamepadServiceTest = GamepadServiceTest::CreateTestService(mWindow);
1238 }
1239 return mGamepadServiceTest;
1240 }
1241
GetVRDisplays(ErrorResult & aRv)1242 already_AddRefed<Promise> Navigator::GetVRDisplays(ErrorResult& aRv) {
1243 if (!mWindow || !mWindow->GetDocShell()) {
1244 aRv.Throw(NS_ERROR_UNEXPECTED);
1245 return nullptr;
1246 }
1247
1248 nsGlobalWindowInner* win = nsGlobalWindowInner::Cast(mWindow);
1249 win->NotifyVREventListenerAdded();
1250
1251 RefPtr<Promise> p = Promise::Create(mWindow->AsGlobal(), aRv);
1252 if (aRv.Failed()) {
1253 return nullptr;
1254 }
1255
1256 // We pass mWindow's id to RefreshVRDisplays, so NotifyVRDisplaysUpdated will
1257 // be called asynchronously, resolving the promises in mVRGetDisplaysPromises.
1258 if (!VRDisplay::RefreshVRDisplays(win->WindowID())) {
1259 p->MaybeReject(NS_ERROR_FAILURE);
1260 return p.forget();
1261 }
1262
1263 mVRGetDisplaysPromises.AppendElement(p);
1264 return p.forget();
1265 }
1266
GetActiveVRDisplays(nsTArray<RefPtr<VRDisplay>> & aDisplays) const1267 void Navigator::GetActiveVRDisplays(
1268 nsTArray<RefPtr<VRDisplay>>& aDisplays) const {
1269 /**
1270 * Get only the active VR displays.
1271 * GetActiveVRDisplays should only enumerate displays that
1272 * are already active without causing any other hardware to be
1273 * activated.
1274 * We must not call nsGlobalWindow::NotifyVREventListenerAdded here,
1275 * as that would cause enumeration and activation of other VR hardware.
1276 * Activating VR hardware is intrusive to the end user, as it may
1277 * involve physically powering on devices that the user did not
1278 * intend to use.
1279 */
1280 if (!mWindow || !mWindow->GetDocShell()) {
1281 return;
1282 }
1283 nsGlobalWindowInner* win = nsGlobalWindowInner::Cast(mWindow);
1284 nsTArray<RefPtr<VRDisplay>> displays;
1285 if (win->UpdateVRDisplays(displays)) {
1286 for (auto display : displays) {
1287 if (display->IsPresenting()) {
1288 aDisplays.AppendElement(display);
1289 }
1290 }
1291 }
1292 }
1293
NotifyVRDisplaysUpdated()1294 void Navigator::NotifyVRDisplaysUpdated() {
1295 // Synchronize the VR devices and resolve the promises in
1296 // mVRGetDisplaysPromises
1297 nsGlobalWindowInner* win = nsGlobalWindowInner::Cast(mWindow);
1298
1299 nsTArray<RefPtr<VRDisplay>> vrDisplays;
1300 if (win->UpdateVRDisplays(vrDisplays)) {
1301 for (auto p : mVRGetDisplaysPromises) {
1302 p->MaybeResolve(vrDisplays);
1303 }
1304 } else {
1305 for (auto p : mVRGetDisplaysPromises) {
1306 p->MaybeReject(NS_ERROR_FAILURE);
1307 }
1308 }
1309 mVRGetDisplaysPromises.Clear();
1310 }
1311
NotifyActiveVRDisplaysChanged()1312 void Navigator::NotifyActiveVRDisplaysChanged() {
1313 NavigatorBinding::ClearCachedActiveVRDisplaysValue(this);
1314 }
1315
RequestVRServiceTest()1316 VRServiceTest* Navigator::RequestVRServiceTest() {
1317 // Ensure that the Mock VR devices are not released prematurely
1318 nsGlobalWindowInner* win = nsGlobalWindowInner::Cast(mWindow);
1319 win->NotifyVREventListenerAdded();
1320
1321 if (!mVRServiceTest) {
1322 mVRServiceTest = VRServiceTest::CreateTestService(mWindow);
1323 }
1324 return mVRServiceTest;
1325 }
1326
IsWebVRContentDetected() const1327 bool Navigator::IsWebVRContentDetected() const {
1328 nsGlobalWindowInner* win = nsGlobalWindowInner::Cast(mWindow);
1329 return win->IsVRContentDetected();
1330 }
1331
IsWebVRContentPresenting() const1332 bool Navigator::IsWebVRContentPresenting() const {
1333 nsGlobalWindowInner* win = nsGlobalWindowInner::Cast(mWindow);
1334 return win->IsVRContentPresenting();
1335 }
1336
RequestVRPresentation(VRDisplay & aDisplay)1337 void Navigator::RequestVRPresentation(VRDisplay& aDisplay) {
1338 nsGlobalWindowInner* win = nsGlobalWindowInner::Cast(mWindow);
1339 win->DispatchVRDisplayActivate(aDisplay.DisplayId(),
1340 VRDisplayEventReason::Requested);
1341 }
1342
RequestMIDIAccess(const MIDIOptions & aOptions,ErrorResult & aRv)1343 already_AddRefed<Promise> Navigator::RequestMIDIAccess(
1344 const MIDIOptions& aOptions, ErrorResult& aRv) {
1345 if (!mWindow) {
1346 aRv.Throw(NS_ERROR_UNEXPECTED);
1347 return nullptr;
1348 }
1349 MIDIAccessManager* accessMgr = MIDIAccessManager::Get();
1350 return accessMgr->RequestMIDIAccess(mWindow, aOptions, aRv);
1351 }
1352
GetNetworkProperties()1353 nsINetworkProperties* Navigator::GetNetworkProperties() {
1354 return GetConnection(IgnoreErrors());
1355 }
1356
GetConnection(ErrorResult & aRv)1357 network::Connection* Navigator::GetConnection(ErrorResult& aRv) {
1358 if (!mConnection) {
1359 if (!mWindow) {
1360 aRv.Throw(NS_ERROR_UNEXPECTED);
1361 return nullptr;
1362 }
1363 mConnection = network::Connection::CreateForWindow(mWindow);
1364 }
1365
1366 return mConnection;
1367 }
1368
ServiceWorker()1369 already_AddRefed<ServiceWorkerContainer> Navigator::ServiceWorker() {
1370 MOZ_ASSERT(mWindow);
1371
1372 if (!mServiceWorkerContainer) {
1373 mServiceWorkerContainer = new ServiceWorkerContainer(mWindow);
1374 }
1375
1376 RefPtr<ServiceWorkerContainer> ref = mServiceWorkerContainer;
1377 return ref.forget();
1378 }
1379
SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const1380 size_t Navigator::SizeOfIncludingThis(
1381 mozilla::MallocSizeOf aMallocSizeOf) const {
1382 size_t n = aMallocSizeOf(this);
1383
1384 // TODO: add SizeOfIncludingThis() to nsMimeTypeArray, bug 674113.
1385 // TODO: add SizeOfIncludingThis() to nsPluginArray, bug 674114.
1386 // TODO: add SizeOfIncludingThis() to Geolocation, bug 674115.
1387 // TODO: add SizeOfIncludingThis() to DesktopNotificationCenter, bug 674116.
1388
1389 return n;
1390 }
1391
SetWindow(nsPIDOMWindowInner * aInnerWindow)1392 void Navigator::SetWindow(nsPIDOMWindowInner* aInnerWindow) {
1393 mWindow = aInnerWindow;
1394 }
1395
OnNavigation()1396 void Navigator::OnNavigation() {
1397 if (!mWindow) {
1398 return;
1399 }
1400
1401 // If MediaManager is open let it inform any live streams or pending callbacks
1402 MediaManager* manager = MediaManager::GetIfExists();
1403 if (manager) {
1404 manager->OnNavigation(mWindow->WindowID());
1405 }
1406 }
1407
CheckPermission(const char * type)1408 bool Navigator::CheckPermission(const char* type) {
1409 return CheckPermission(mWindow, type);
1410 }
1411
1412 /* static */
CheckPermission(nsPIDOMWindowInner * aWindow,const char * aType)1413 bool Navigator::CheckPermission(nsPIDOMWindowInner* aWindow,
1414 const char* aType) {
1415 if (!aWindow) {
1416 return false;
1417 }
1418
1419 uint32_t permission = GetPermission(aWindow, aType);
1420 return permission == nsIPermissionManager::ALLOW_ACTION;
1421 }
1422
WrapObject(JSContext * cx,JS::Handle<JSObject * > aGivenProto)1423 JSObject* Navigator::WrapObject(JSContext* cx,
1424 JS::Handle<JSObject*> aGivenProto) {
1425 return NavigatorBinding::Wrap(cx, this, aGivenProto);
1426 }
1427
1428 /* static */
HasWakeLockSupport(JSContext *,JSObject *)1429 bool Navigator::HasWakeLockSupport(JSContext* /* unused*/,
1430 JSObject* /*unused */) {
1431 nsCOMPtr<nsIPowerManagerService> pmService =
1432 do_GetService(POWERMANAGERSERVICE_CONTRACTID);
1433 // No service means no wake lock support
1434 return !!pmService;
1435 }
1436
1437 /* static */
HasWifiManagerSupport(JSContext *,JSObject * aGlobal)1438 bool Navigator::HasWifiManagerSupport(JSContext* /* unused */,
1439 JSObject* aGlobal) {
1440 // On XBL scope, the global object is NOT |window|. So we have
1441 // to use nsContentUtils::GetObjectPrincipal to get the principal
1442 // and test directly with permission manager.
1443
1444 nsIPrincipal* principal = nsContentUtils::ObjectPrincipal(aGlobal);
1445 uint32_t permission = GetPermission(principal, "wifi-manage");
1446
1447 return permission == nsIPermissionManager::ALLOW_ACTION;
1448 }
1449
1450 /* static */
HasUserMediaSupport(JSContext *,JSObject *)1451 bool Navigator::HasUserMediaSupport(JSContext* /* unused */,
1452 JSObject* /* unused */) {
1453 // Make enabling peerconnection enable getUserMedia() as well
1454 return Preferences::GetBool("media.navigator.enabled", false) ||
1455 Preferences::GetBool("media.peerconnection.enabled", false);
1456 }
1457
1458 /* static */
GetWindowFromGlobal(JSObject * aGlobal)1459 already_AddRefed<nsPIDOMWindowInner> Navigator::GetWindowFromGlobal(
1460 JSObject* aGlobal) {
1461 nsCOMPtr<nsPIDOMWindowInner> win =
1462 do_QueryInterface(nsJSUtils::GetStaticScriptGlobal(aGlobal));
1463 return win.forget();
1464 }
1465
GetPlatform(nsAString & aPlatform,bool aUsePrefOverriddenValue)1466 nsresult Navigator::GetPlatform(nsAString& aPlatform,
1467 bool aUsePrefOverriddenValue) {
1468 MOZ_ASSERT(NS_IsMainThread());
1469
1470 if (aUsePrefOverriddenValue) {
1471 // If fingerprinting resistance is on, we will spoof this value. See
1472 // nsRFPService.h for details about spoofed values.
1473 if (nsContentUtils::ShouldResistFingerprinting()) {
1474 aPlatform.AssignLiteral(SPOOFED_PLATFORM);
1475 return NS_OK;
1476 }
1477 nsAutoString override;
1478 nsresult rv =
1479 mozilla::Preferences::GetString("general.platform.override", override);
1480
1481 if (NS_SUCCEEDED(rv)) {
1482 aPlatform = override;
1483 return NS_OK;
1484 }
1485 }
1486
1487 nsresult rv;
1488
1489 nsCOMPtr<nsIHttpProtocolHandler> service(
1490 do_GetService(NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX "http", &rv));
1491 NS_ENSURE_SUCCESS(rv, rv);
1492
1493 // Sorry for the #if platform ugliness, but Communicator is likewise
1494 // hardcoded and we are seeking backward compatibility here (bug 47080).
1495 #if defined(_WIN64)
1496 aPlatform.AssignLiteral("Win64");
1497 #elif defined(WIN32)
1498 aPlatform.AssignLiteral("Win32");
1499 #elif defined(XP_MACOSX) && defined(__ppc__)
1500 aPlatform.AssignLiteral("MacPPC");
1501 #elif defined(XP_MACOSX) && defined(__i386__)
1502 aPlatform.AssignLiteral("MacIntel");
1503 #elif defined(XP_MACOSX) && defined(__x86_64__)
1504 aPlatform.AssignLiteral("MacIntel");
1505 #else
1506 // XXX Communicator uses compiled-in build-time string defines
1507 // to indicate the platform it was compiled *for*, not what it is
1508 // currently running *on* which is what this does.
1509 nsAutoCString plat;
1510 rv = service->GetOscpu(plat);
1511 CopyASCIItoUTF16(plat, aPlatform);
1512 #endif
1513
1514 return rv;
1515 }
1516
GetAppVersion(nsAString & aAppVersion,bool aUsePrefOverriddenValue)1517 /* static */ nsresult Navigator::GetAppVersion(nsAString& aAppVersion,
1518 bool aUsePrefOverriddenValue) {
1519 MOZ_ASSERT(NS_IsMainThread());
1520
1521 if (aUsePrefOverriddenValue) {
1522 // If fingerprinting resistance is on, we will spoof this value. See
1523 // nsRFPService.h for details about spoofed values.
1524 if (nsContentUtils::ShouldResistFingerprinting()) {
1525 aAppVersion.AssignLiteral(SPOOFED_APPVERSION);
1526 return NS_OK;
1527 }
1528 nsAutoString override;
1529 nsresult rv = mozilla::Preferences::GetString("general.appversion.override",
1530 override);
1531
1532 if (NS_SUCCEEDED(rv)) {
1533 aAppVersion = override;
1534 return NS_OK;
1535 }
1536 }
1537
1538 nsresult rv;
1539
1540 nsCOMPtr<nsIHttpProtocolHandler> service(
1541 do_GetService(NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX "http", &rv));
1542 NS_ENSURE_SUCCESS(rv, rv);
1543
1544 nsAutoCString str;
1545 rv = service->GetAppVersion(str);
1546 CopyASCIItoUTF16(str, aAppVersion);
1547 NS_ENSURE_SUCCESS(rv, rv);
1548
1549 aAppVersion.AppendLiteral(" (");
1550
1551 rv = service->GetPlatform(str);
1552 NS_ENSURE_SUCCESS(rv, rv);
1553
1554 AppendASCIItoUTF16(str, aAppVersion);
1555 aAppVersion.Append(char16_t(')'));
1556
1557 return rv;
1558 }
1559
AppName(nsAString & aAppName,bool aUsePrefOverriddenValue)1560 /* static */ void Navigator::AppName(nsAString& aAppName,
1561 bool aUsePrefOverriddenValue) {
1562 MOZ_ASSERT(NS_IsMainThread());
1563
1564 if (aUsePrefOverriddenValue) {
1565 // If fingerprinting resistance is on, we will spoof this value. See
1566 // nsRFPService.h for details about spoofed values.
1567 if (nsContentUtils::ShouldResistFingerprinting()) {
1568 aAppName.AssignLiteral(SPOOFED_APPNAME);
1569 return;
1570 }
1571
1572 nsAutoString override;
1573 nsresult rv =
1574 mozilla::Preferences::GetString("general.appname.override", override);
1575
1576 if (NS_SUCCEEDED(rv)) {
1577 aAppName = override;
1578 return;
1579 }
1580 }
1581
1582 aAppName.AssignLiteral("Netscape");
1583 }
1584
ClearUserAgentCache()1585 void Navigator::ClearUserAgentCache() {
1586 NavigatorBinding::ClearCachedUserAgentValue(this);
1587 }
1588
GetUserAgent(nsPIDOMWindowInner * aWindow,bool aIsCallerChrome,nsAString & aUserAgent)1589 nsresult Navigator::GetUserAgent(nsPIDOMWindowInner* aWindow,
1590 bool aIsCallerChrome, nsAString& aUserAgent) {
1591 MOZ_ASSERT(NS_IsMainThread());
1592
1593 // We will skip the override and pass to httpHandler to get spoofed userAgent
1594 // when 'privacy.resistFingerprinting' is true.
1595 if (!aIsCallerChrome && !nsContentUtils::ShouldResistFingerprinting()) {
1596 nsAutoString override;
1597 nsresult rv =
1598 mozilla::Preferences::GetString("general.useragent.override", override);
1599
1600 if (NS_SUCCEEDED(rv)) {
1601 aUserAgent = override;
1602 return NS_OK;
1603 }
1604 }
1605
1606 // When the caller is content and 'privacy.resistFingerprinting' is true,
1607 // return a spoofed userAgent which reveals the platform but not the
1608 // specific OS version, etc.
1609 if (!aIsCallerChrome && nsContentUtils::ShouldResistFingerprinting()) {
1610 nsAutoCString spoofedUA;
1611 nsresult rv = nsRFPService::GetSpoofedUserAgent(spoofedUA, false);
1612 if (NS_WARN_IF(NS_FAILED(rv))) {
1613 return rv;
1614 }
1615 CopyASCIItoUTF16(spoofedUA, aUserAgent);
1616 return NS_OK;
1617 }
1618
1619 nsresult rv;
1620 nsCOMPtr<nsIHttpProtocolHandler> service(
1621 do_GetService(NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX "http", &rv));
1622 if (NS_WARN_IF(NS_FAILED(rv))) {
1623 return rv;
1624 }
1625
1626 nsAutoCString ua;
1627 rv = service->GetUserAgent(ua);
1628 if (NS_WARN_IF(NS_FAILED(rv))) {
1629 return rv;
1630 }
1631
1632 CopyASCIItoUTF16(ua, aUserAgent);
1633
1634 // When the caller is content, we will always return spoofed userAgent and
1635 // ignore the User-Agent header from the document channel when
1636 // 'privacy.resistFingerprinting' is true.
1637 if (!aWindow ||
1638 (nsContentUtils::ShouldResistFingerprinting() && !aIsCallerChrome)) {
1639 return NS_OK;
1640 }
1641
1642 // Copy the User-Agent header from the document channel which has already been
1643 // subject to UA overrides.
1644 nsCOMPtr<nsIDocument> doc = aWindow->GetExtantDoc();
1645 if (!doc) {
1646 return NS_OK;
1647 }
1648 nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(doc->GetChannel());
1649 if (httpChannel) {
1650 nsAutoCString userAgent;
1651 rv = httpChannel->GetRequestHeader(NS_LITERAL_CSTRING("User-Agent"),
1652 userAgent);
1653 if (NS_WARN_IF(NS_FAILED(rv))) {
1654 return rv;
1655 }
1656 CopyASCIItoUTF16(userAgent, aUserAgent);
1657 }
1658 return NS_OK;
1659 }
1660
RequestKeySystemAccessLogString(const nsAString & aKeySystem,const Sequence<MediaKeySystemConfiguration> & aConfigs,bool aIsSecureContext)1661 static nsCString RequestKeySystemAccessLogString(
1662 const nsAString& aKeySystem,
1663 const Sequence<MediaKeySystemConfiguration>& aConfigs,
1664 bool aIsSecureContext) {
1665 nsCString str;
1666 str.AppendPrintf(
1667 "Navigator::RequestMediaKeySystemAccess(keySystem='%s' options=",
1668 NS_ConvertUTF16toUTF8(aKeySystem).get());
1669 str.Append(MediaKeySystemAccess::ToCString(aConfigs));
1670 str.AppendLiteral(") secureContext=");
1671 str.AppendInt(aIsSecureContext);
1672 return str;
1673 }
1674
RequestMediaKeySystemAccess(const nsAString & aKeySystem,const Sequence<MediaKeySystemConfiguration> & aConfigs,ErrorResult & aRv)1675 already_AddRefed<Promise> Navigator::RequestMediaKeySystemAccess(
1676 const nsAString& aKeySystem,
1677 const Sequence<MediaKeySystemConfiguration>& aConfigs, ErrorResult& aRv) {
1678 EME_LOG("%s", RequestKeySystemAccessLogString(aKeySystem, aConfigs,
1679 mWindow->IsSecureContext())
1680 .get());
1681
1682 Telemetry::Accumulate(Telemetry::MEDIA_EME_SECURE_CONTEXT,
1683 mWindow->IsSecureContext());
1684
1685 if (!mWindow->IsSecureContext()) {
1686 nsIDocument* doc = mWindow->GetExtantDoc();
1687 nsString uri;
1688 if (doc) {
1689 Unused << doc->GetDocumentURI(uri);
1690 }
1691 const char16_t* params[] = {uri.get()};
1692 nsContentUtils::ReportToConsole(nsIScriptError::warningFlag,
1693 NS_LITERAL_CSTRING("Media"), doc,
1694 nsContentUtils::eDOM_PROPERTIES,
1695 "MediaEMEInsecureContextDeprecatedWarning",
1696 params, ArrayLength(params));
1697 }
1698
1699 RefPtr<DetailedPromise> promise = DetailedPromise::Create(
1700 mWindow->AsGlobal(), aRv,
1701 NS_LITERAL_CSTRING("navigator.requestMediaKeySystemAccess"),
1702 Telemetry::VIDEO_EME_REQUEST_SUCCESS_LATENCY_MS,
1703 Telemetry::VIDEO_EME_REQUEST_FAILURE_LATENCY_MS);
1704 if (aRv.Failed()) {
1705 return nullptr;
1706 }
1707
1708 if (!mMediaKeySystemAccessManager) {
1709 mMediaKeySystemAccessManager = new MediaKeySystemAccessManager(mWindow);
1710 }
1711
1712 mMediaKeySystemAccessManager->Request(promise, aKeySystem, aConfigs);
1713 return promise.forget();
1714 }
1715
GetPresentation(ErrorResult & aRv)1716 Presentation* Navigator::GetPresentation(ErrorResult& aRv) {
1717 if (!mPresentation) {
1718 if (!mWindow) {
1719 aRv.Throw(NS_ERROR_UNEXPECTED);
1720 return nullptr;
1721 }
1722 mPresentation = Presentation::Create(mWindow);
1723 }
1724
1725 return mPresentation;
1726 }
1727
Credentials()1728 CredentialsContainer* Navigator::Credentials() {
1729 if (!mCredentials) {
1730 mCredentials = new CredentialsContainer(GetWindow());
1731 }
1732 return mCredentials;
1733 }
1734
1735 /* static */
Webdriver()1736 bool Navigator::Webdriver() {
1737 return Preferences::GetBool("marionette.enabled", false);
1738 }
1739
1740 } // namespace dom
1741 } // namespace mozilla
1742