Coverage Report

Created: 2018-09-25 14:53

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