dom/base/Navigator.cpp

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

     1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
     2 /* vim: set sw=2 ts=2 et tw=78: */
     3 /* This Source Code Form is subject to the terms of the Mozilla Public
     4  * License, v. 2.0. If a copy of the MPL was not distributed with this
     5  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     7 // Needs to be first.
     8 #include "base/basictypes.h"
    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/DesktopNotification.h"
    16 #include "nsGeolocation.h"
    17 #include "nsIHttpProtocolHandler.h"
    18 #include "nsIContentPolicy.h"
    19 #include "nsIContentSecurityPolicy.h"
    20 #include "nsContentPolicyUtils.h"
    21 #include "nsCrossSiteListenerProxy.h"
    22 #include "nsISupportsPriority.h"
    23 #include "nsICachingChannel.h"
    24 #include "nsIWebContentHandlerRegistrar.h"
    25 #include "nsICookiePermission.h"
    26 #include "nsIScriptSecurityManager.h"
    27 #include "nsCharSeparatedTokenizer.h"
    28 #include "nsContentUtils.h"
    29 #include "nsUnicharUtils.h"
    30 #include "mozilla/Preferences.h"
    31 #include "mozilla/Telemetry.h"
    32 #include "BatteryManager.h"
    33 #include "mozilla/dom/PowerManager.h"
    34 #include "mozilla/dom/WakeLock.h"
    35 #include "mozilla/dom/power/PowerManagerService.h"
    36 #include "mozilla/dom/MobileMessageManager.h"
    37 #include "mozilla/dom/Telephony.h"
    38 #include "mozilla/Hal.h"
    39 #include "nsISiteSpecificUserAgent.h"
    40 #include "mozilla/ClearOnShutdown.h"
    41 #include "mozilla/StaticPtr.h"
    42 #include "Connection.h"
    43 #include "mozilla/dom/Event.h" // for nsIDOMEvent::InternalDOMEvent()
    44 #include "nsGlobalWindow.h"
    45 #ifdef MOZ_B2G_RIL
    46 #include "mozilla/dom/IccManager.h"
    47 #include "mozilla/dom/CellBroadcast.h"
    48 #include "mozilla/dom/MobileConnectionArray.h"
    49 #include "mozilla/dom/Voicemail.h"
    50 #endif
    51 #include "nsIIdleObserver.h"
    52 #include "nsIPermissionManager.h"
    53 #include "nsMimeTypes.h"
    54 #include "nsNetUtil.h"
    55 #include "nsIHttpChannel.h"
    56 #include "nsIHttpChannelInternal.h"
    57 #include "TimeManager.h"
    58 #include "DeviceStorage.h"
    59 #include "nsIDOMNavigatorSystemMessages.h"
    60 #include "nsStreamUtils.h"
    61 #include "nsIAppsService.h"
    62 #include "mozIApplication.h"
    63 #include "WidgetUtils.h"
    64 #include "mozIThirdPartyUtil.h"
    65 #include "nsChannelPolicy.h"
    67 #ifdef MOZ_MEDIA_NAVIGATOR
    68 #include "MediaManager.h"
    69 #endif
    70 #ifdef MOZ_B2G_BT
    71 #include "BluetoothManager.h"
    72 #endif
    73 #include "DOMCameraManager.h"
    75 #ifdef MOZ_AUDIO_CHANNEL_MANAGER
    76 #include "AudioChannelManager.h"
    77 #endif
    79 #ifdef MOZ_B2G_FM
    80 #include "mozilla/dom/FMRadio.h"
    81 #endif
    83 #include "nsIDOMGlobalPropertyInitializer.h"
    84 #include "nsIDataStoreService.h"
    85 #include "nsJSUtils.h"
    87 #include "nsScriptNameSpaceManager.h"
    89 #include "mozilla/dom/NavigatorBinding.h"
    90 #include "mozilla/dom/Promise.h"
    92 #include "nsIUploadChannel2.h"
    93 #include "nsFormData.h"
    94 #include "nsIPrivateBrowsingChannel.h"
    95 #include "nsIDocShell.h"
    97 namespace mozilla {
    98 namespace dom {
   100 static bool sDoNotTrackEnabled = false;
   101 static bool sVibratorEnabled   = false;
   102 static uint32_t sMaxVibrateMS  = 0;
   103 static uint32_t sMaxVibrateListLen = 0;
   105 /* static */
   106 void
   107 Navigator::Init()
   108 {
   109   Preferences::AddBoolVarCache(&sDoNotTrackEnabled,
   110                                "privacy.donottrackheader.enabled",
   111                                false);
   112   Preferences::AddBoolVarCache(&sVibratorEnabled,
   113                                "dom.vibrator.enabled", true);
   114   Preferences::AddUintVarCache(&sMaxVibrateMS,
   115                                "dom.vibrator.max_vibrate_ms", 10000);
   116   Preferences::AddUintVarCache(&sMaxVibrateListLen,
   117                                "dom.vibrator.max_vibrate_list_len", 128);
   118 }
   120 Navigator::Navigator(nsPIDOMWindow* aWindow)
   121   : mWindow(aWindow)
   122 {
   123   MOZ_ASSERT(aWindow->IsInnerWindow(), "Navigator must get an inner window!");
   124   SetIsDOMBinding();
   125 }
   127 Navigator::~Navigator()
   128 {
   129   Invalidate();
   130 }
   132 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(Navigator)
   133   NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
   134   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDOMNavigator)
   135   NS_INTERFACE_MAP_ENTRY(nsIDOMNavigator)
   136   NS_INTERFACE_MAP_ENTRY(nsIMozNavigatorNetwork)
   137 NS_INTERFACE_MAP_END
   139 NS_IMPL_CYCLE_COLLECTING_ADDREF(Navigator)
   140 NS_IMPL_CYCLE_COLLECTING_RELEASE(Navigator)
   142 NS_IMPL_CYCLE_COLLECTION_CLASS(Navigator)
   144 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(Navigator)
   145   tmp->Invalidate();
   146   NS_IMPL_CYCLE_COLLECTION_UNLINK(mWindow)
   147   NS_IMPL_CYCLE_COLLECTION_UNLINK(mCachedResolveResults)
   148   NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
   149 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
   151 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(Navigator)
   152   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPlugins)
   153   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mMimeTypes)
   154   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mGeolocation)
   155   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mNotification)
   156   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mBatteryManager)
   157   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPowerManager)
   158   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mMobileMessageManager)
   159   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mTelephony)
   160   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mConnection)
   161 #ifdef MOZ_B2G_RIL
   162   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mMobileConnections)
   163   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mCellBroadcast)
   164   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mIccManager)
   165   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mVoicemail)
   166 #endif
   167 #ifdef MOZ_B2G_BT
   168   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mBluetooth)
   169 #endif
   170 #ifdef MOZ_AUDIO_CHANNEL_MANAGER
   171   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mAudioChannelManager)
   172 #endif
   173   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mCameraManager)
   174   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mMessagesManager)
   175   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDeviceStorageStores)
   176   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mTimeManager)
   178   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mWindow)
   179   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mCachedResolveResults)
   180   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
   181 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
   183 NS_IMPL_CYCLE_COLLECTION_TRACE_WRAPPERCACHE(Navigator)
   185 void
   186 Navigator::Invalidate()
   187 {
   188   // Don't clear mWindow here so we know we've got a non-null mWindow
   189   // until we're unlinked.
   191   if (mPlugins) {
   192     mPlugins->Invalidate();
   193     mPlugins = nullptr;
   194   }
   196   mMimeTypes = nullptr;
   198   // If there is a page transition, make sure delete the geolocation object.
   199   if (mGeolocation) {
   200     mGeolocation->Shutdown();
   201     mGeolocation = nullptr;
   202   }
   204   if (mNotification) {
   205     mNotification->Shutdown();
   206     mNotification = nullptr;
   207   }
   209   if (mBatteryManager) {
   210     mBatteryManager->Shutdown();
   211     mBatteryManager = nullptr;
   212   }
   214 #ifdef MOZ_B2G_FM
   215   if (mFMRadio) {
   216     mFMRadio->Shutdown();
   217     mFMRadio = nullptr;
   218   }
   219 #endif
   221   if (mPowerManager) {
   222     mPowerManager->Shutdown();
   223     mPowerManager = nullptr;
   224   }
   226   if (mMobileMessageManager) {
   227     mMobileMessageManager->Shutdown();
   228     mMobileMessageManager = nullptr;
   229   }
   231   if (mTelephony) {
   232     mTelephony = nullptr;
   233   }
   235   if (mConnection) {
   236     mConnection->Shutdown();
   237     mConnection = nullptr;
   238   }
   240 #ifdef MOZ_B2G_RIL
   241   if (mMobileConnections) {
   242     mMobileConnections = nullptr;
   243   }
   245   if (mCellBroadcast) {
   246     mCellBroadcast = nullptr;
   247   }
   249   if (mIccManager) {
   250     mIccManager->Shutdown();
   251     mIccManager = nullptr;
   252   }
   254   if (mVoicemail) {
   255     mVoicemail = nullptr;
   256   }
   257 #endif
   259 #ifdef MOZ_B2G_BT
   260   if (mBluetooth) {
   261     mBluetooth = nullptr;
   262   }
   263 #endif
   265   mCameraManager = nullptr;
   267   if (mMessagesManager) {
   268     mMessagesManager = nullptr;
   269   }
   271 #ifdef MOZ_AUDIO_CHANNEL_MANAGER
   272   if (mAudioChannelManager) {
   273     mAudioChannelManager = nullptr;
   274   }
   275 #endif
   277   uint32_t len = mDeviceStorageStores.Length();
   278   for (uint32_t i = 0; i < len; ++i) {
   279     mDeviceStorageStores[i]->Shutdown();
   280   }
   281   mDeviceStorageStores.Clear();
   283   if (mTimeManager) {
   284     mTimeManager = nullptr;
   285   }
   286 }
   288 //*****************************************************************************
   289 //    Navigator::nsIDOMNavigator
   290 //*****************************************************************************
   292 NS_IMETHODIMP
   293 Navigator::GetUserAgent(nsAString& aUserAgent)
   294 {
   295   nsresult rv = NS_GetNavigatorUserAgent(aUserAgent);
   296   NS_ENSURE_SUCCESS(rv, rv);
   298   if (!mWindow || !mWindow->GetDocShell()) {
   299     return NS_OK;
   300   }
   302   nsIDocument* doc = mWindow->GetExtantDoc();
   303   if (!doc) {
   304     return NS_OK;
   305   }
   307   nsCOMPtr<nsIURI> codebaseURI;
   308   doc->NodePrincipal()->GetURI(getter_AddRefs(codebaseURI));
   309   if (!codebaseURI) {
   310     return NS_OK;
   311   }
   313   nsCOMPtr<nsISiteSpecificUserAgent> siteSpecificUA =
   314     do_GetService("@mozilla.org/dom/site-specific-user-agent;1");
   315   NS_ENSURE_TRUE(siteSpecificUA, NS_OK);
   317   return siteSpecificUA->GetUserAgentForURIAndWindow(codebaseURI, mWindow,
   318                                                      aUserAgent);
   319 }
   321 NS_IMETHODIMP
   322 Navigator::GetAppCodeName(nsAString& aAppCodeName)
   323 {
   324   nsresult rv;
   326   nsCOMPtr<nsIHttpProtocolHandler>
   327     service(do_GetService(NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX "http", &rv));
   328   NS_ENSURE_SUCCESS(rv, rv);
   330   nsAutoCString appName;
   331   rv = service->GetAppName(appName);
   332   CopyASCIItoUTF16(appName, aAppCodeName);
   334   return rv;
   335 }
   337 NS_IMETHODIMP
   338 Navigator::GetAppVersion(nsAString& aAppVersion)
   339 {
   340   return GetAppVersion(aAppVersion, /* aUsePrefOverriddenValue */ true);
   341 }
   343 NS_IMETHODIMP
   344 Navigator::GetAppName(nsAString& aAppName)
   345 {
   346   AppName(aAppName, /* aUsePrefOverriddenValue */ true);
   347   return NS_OK;
   348 }
   350 /**
   351  * JS property navigator.language, exposed to web content.
   352  * Take first value from Accept-Languages (HTTP header), which is
   353  * the "content language" freely set by the user in the Pref window.
   354  *
   355  * Do not use UI language (chosen app locale) here.
   356  * See RFC 2616, Section 15.1.4 "Privacy Issues Connected to Accept Headers"
   357  *
   358  * "en", "en-US" and "i-cherokee" and "" are valid.
   359  * Fallback in case of invalid pref should be "" (empty string), to
   360  * let site do fallback, e.g. to site's local language.
   361  */
   362 NS_IMETHODIMP
   363 Navigator::GetLanguage(nsAString& aLanguage)
   364 {
   365   // E.g. "de-de, en-us,en".
   366   const nsAdoptingString& acceptLang =
   367     Preferences::GetLocalizedString("intl.accept_languages");
   369   // Take everything before the first "," or ";", without trailing space.
   370   nsCharSeparatedTokenizer langTokenizer(acceptLang, ',');
   371   const nsSubstring &firstLangPart = langTokenizer.nextToken();
   372   nsCharSeparatedTokenizer qTokenizer(firstLangPart, ';');
   373   aLanguage.Assign(qTokenizer.nextToken());
   375   // Checks and fixups:
   376   // replace "_" with "-" to avoid POSIX/Windows "en_US" notation.
   377   if (aLanguage.Length() > 2 && aLanguage[2] == char16_t('_')) {
   378     aLanguage.Replace(2, 1, char16_t('-')); // TODO replace all
   379   }
   381   // Use uppercase for country part, e.g. "en-US", not "en-us", see BCP47
   382   // only uppercase 2-letter country codes, not "zh-Hant", "de-DE-x-goethe".
   383   if (aLanguage.Length() <= 2) {
   384     return NS_OK;
   385   }
   387   nsCharSeparatedTokenizer localeTokenizer(aLanguage, '-');
   388   int32_t pos = 0;
   389   bool first = true;
   390   while (localeTokenizer.hasMoreTokens()) {
   391     const nsSubstring& code = localeTokenizer.nextToken();
   393     if (code.Length() == 2 && !first) {
   394       nsAutoString upper(code);
   395       ToUpperCase(upper);
   396       aLanguage.Replace(pos, code.Length(), upper);
   397     }
   399     pos += code.Length() + 1; // 1 is the separator
   400     first = false;
   401   }
   403   return NS_OK;
   404 }
   406 NS_IMETHODIMP
   407 Navigator::GetPlatform(nsAString& aPlatform)
   408 {
   409   return GetPlatform(aPlatform, /* aUsePrefOverriddenValue */ true);
   410 }
   412 NS_IMETHODIMP
   413 Navigator::GetOscpu(nsAString& aOSCPU)
   414 {
   415   if (!nsContentUtils::IsCallerChrome()) {
   416     const nsAdoptingString& override =
   417       Preferences::GetString("general.oscpu.override");
   419     if (override) {
   420       aOSCPU = override;
   421       return NS_OK;
   422     }
   423   }
   425   nsresult rv;
   427   nsCOMPtr<nsIHttpProtocolHandler>
   428     service(do_GetService(NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX "http", &rv));
   429   NS_ENSURE_SUCCESS(rv, rv);
   431   nsAutoCString oscpu;
   432   rv = service->GetOscpu(oscpu);
   433   CopyASCIItoUTF16(oscpu, aOSCPU);
   435   return rv;
   436 }
   438 NS_IMETHODIMP
   439 Navigator::GetVendor(nsAString& aVendor)
   440 {
   441   aVendor.Truncate();
   442   return NS_OK;
   443 }
   445 NS_IMETHODIMP
   446 Navigator::GetVendorSub(nsAString& aVendorSub)
   447 {
   448   aVendorSub.Truncate();
   449   return NS_OK;
   450 }
   452 NS_IMETHODIMP
   453 Navigator::GetProduct(nsAString& aProduct)
   454 {
   455   aProduct.AssignLiteral("Gecko");
   456   return NS_OK;
   457 }
   459 NS_IMETHODIMP
   460 Navigator::GetProductSub(nsAString& aProductSub)
   461 {
   462   // Legacy build ID hardcoded for backward compatibility (bug 776376)
   463   aProductSub.AssignLiteral("20100101");
   464   return NS_OK;
   465 }
   467 nsMimeTypeArray*
   468 Navigator::GetMimeTypes(ErrorResult& aRv)
   469 {
   470   if (!mMimeTypes) {
   471     if (!mWindow) {
   472       aRv.Throw(NS_ERROR_UNEXPECTED);
   473       return nullptr;
   474     }
   475     mMimeTypes = new nsMimeTypeArray(mWindow);
   476   }
   478   return mMimeTypes;
   479 }
   481 nsPluginArray*
   482 Navigator::GetPlugins(ErrorResult& aRv)
   483 {
   484   if (!mPlugins) {
   485     if (!mWindow) {
   486       aRv.Throw(NS_ERROR_UNEXPECTED);
   487       return nullptr;
   488     }
   489     mPlugins = new nsPluginArray(mWindow);
   490     mPlugins->Init();
   491   }
   493   return mPlugins;
   494 }
   496 // Values for the network.cookie.cookieBehavior pref are documented in
   497 // nsCookieService.cpp.
   498 #define COOKIE_BEHAVIOR_REJECT 2
   500 bool
   501 Navigator::CookieEnabled()
   502 {
   503   bool cookieEnabled =
   504     (Preferences::GetInt("network.cookie.cookieBehavior",
   505                          COOKIE_BEHAVIOR_REJECT) != COOKIE_BEHAVIOR_REJECT);
   507   // Check whether an exception overrides the global cookie behavior
   508   // Note that the code for getting the URI here matches that in
   509   // nsHTMLDocument::SetCookie.
   510   if (!mWindow || !mWindow->GetDocShell()) {
   511     return cookieEnabled;
   512   }
   514   nsCOMPtr<nsIDocument> doc = mWindow->GetExtantDoc();
   515   if (!doc) {
   516     return cookieEnabled;
   517   }
   519   nsCOMPtr<nsIURI> codebaseURI;
   520   doc->NodePrincipal()->GetURI(getter_AddRefs(codebaseURI));
   522   if (!codebaseURI) {
   523     // Not a codebase, so technically can't set cookies, but let's
   524     // just return the default value.
   525     return cookieEnabled;
   526   }
   528   nsCOMPtr<nsICookiePermission> permMgr =
   529     do_GetService(NS_COOKIEPERMISSION_CONTRACTID);
   530   NS_ENSURE_TRUE(permMgr, cookieEnabled);
   532   // Pass null for the channel, just like the cookie service does.
   533   nsCookieAccess access;
   534   nsresult rv = permMgr->CanAccess(codebaseURI, nullptr, &access);
   535   NS_ENSURE_SUCCESS(rv, cookieEnabled);
   537   if (access != nsICookiePermission::ACCESS_DEFAULT) {
   538     cookieEnabled = access != nsICookiePermission::ACCESS_DENY;
   539   }
   541   return cookieEnabled;
   542 }
   544 bool
   545 Navigator::OnLine()
   546 {
   547   return !NS_IsOffline();
   548 }
   550 NS_IMETHODIMP
   551 Navigator::GetBuildID(nsAString& aBuildID)
   552 {
   553   if (!nsContentUtils::IsCallerChrome()) {
   554     const nsAdoptingString& override =
   555       Preferences::GetString("general.buildID.override");
   557     if (override) {
   558       aBuildID = override;
   559       return NS_OK;
   560     }
   561   }
   563   nsCOMPtr<nsIXULAppInfo> appInfo =
   564     do_GetService("@mozilla.org/xre/app-info;1");
   565   if (!appInfo) {
   566     return NS_ERROR_NOT_IMPLEMENTED;
   567   }
   569   nsAutoCString buildID;
   570   nsresult rv = appInfo->GetAppBuildID(buildID);
   571   if (NS_FAILED(rv)) {
   572     return rv;
   573   }
   575   aBuildID.Truncate();
   576   AppendASCIItoUTF16(buildID, aBuildID);
   577   return NS_OK;
   578 }
   580 NS_IMETHODIMP
   581 Navigator::GetDoNotTrack(nsAString &aResult)
   582 {
   583   if (sDoNotTrackEnabled) {
   584     aResult.AssignLiteral("yes");
   585   } else {
   586     aResult.AssignLiteral("unspecified");
   587   }
   589   return NS_OK;
   590 }
   592 bool
   593 Navigator::JavaEnabled(ErrorResult& aRv)
   594 {
   595   Telemetry::AutoTimer<Telemetry::CHECK_JAVA_ENABLED> telemetryTimer;
   597   // Return true if we have a handler for the java mime
   598   nsAdoptingString javaMIME = Preferences::GetString("plugin.java.mime");
   599   NS_ENSURE_TRUE(!javaMIME.IsEmpty(), false);
   601   if (!mMimeTypes) {
   602     if (!mWindow) {
   603       aRv.Throw(NS_ERROR_UNEXPECTED);
   604       return false;
   605     }
   606     mMimeTypes = new nsMimeTypeArray(mWindow);
   607   }
   609   RefreshMIMEArray();
   611   nsMimeType *mimeType = mMimeTypes->NamedItem(javaMIME);
   613   return mimeType && mimeType->GetEnabledPlugin();
   614 }
   616 void
   617 Navigator::RefreshMIMEArray()
   618 {
   619   if (mMimeTypes) {
   620     mMimeTypes->Refresh();
   621   }
   622 }
   624 bool
   625 Navigator::HasDesktopNotificationSupport()
   626 {
   627   return Preferences::GetBool("notification.feature.enabled", false);
   628 }
   630 namespace {
   632 class VibrateWindowListener : public nsIDOMEventListener
   633 {
   634 public:
   635   VibrateWindowListener(nsIDOMWindow* aWindow, nsIDocument* aDocument)
   636   {
   637     mWindow = do_GetWeakReference(aWindow);
   638     mDocument = do_GetWeakReference(aDocument);
   640     NS_NAMED_LITERAL_STRING(visibilitychange, "visibilitychange");
   641     aDocument->AddSystemEventListener(visibilitychange,
   642                                       this, /* listener */
   643                                       true, /* use capture */
   644                                       false /* wants untrusted */);
   645   }
   647   virtual ~VibrateWindowListener()
   648   {
   649   }
   651   void RemoveListener();
   653   NS_DECL_ISUPPORTS
   654   NS_DECL_NSIDOMEVENTLISTENER
   656 private:
   657   nsWeakPtr mWindow;
   658   nsWeakPtr mDocument;
   659 };
   661 NS_IMPL_ISUPPORTS(VibrateWindowListener, nsIDOMEventListener)
   663 StaticRefPtr<VibrateWindowListener> gVibrateWindowListener;
   665 NS_IMETHODIMP
   666 VibrateWindowListener::HandleEvent(nsIDOMEvent* aEvent)
   667 {
   668   nsCOMPtr<nsIDocument> doc =
   669     do_QueryInterface(aEvent->InternalDOMEvent()->GetTarget());
   671   if (!doc || doc->Hidden()) {
   672     // It's important that we call CancelVibrate(), not Vibrate() with an
   673     // empty list, because Vibrate() will fail if we're no longer focused, but
   674     // CancelVibrate() will succeed, so long as nobody else has started a new
   675     // vibration pattern.
   676     nsCOMPtr<nsIDOMWindow> window = do_QueryReferent(mWindow);
   677     hal::CancelVibrate(window);
   678     RemoveListener();
   679     gVibrateWindowListener = nullptr;
   680     // Careful: The line above might have deleted |this|!
   681   }
   683   return NS_OK;
   684 }
   686 void
   687 VibrateWindowListener::RemoveListener()
   688 {
   689   nsCOMPtr<EventTarget> target = do_QueryReferent(mDocument);
   690   if (!target) {
   691     return;
   692   }
   693   NS_NAMED_LITERAL_STRING(visibilitychange, "visibilitychange");
   694   target->RemoveSystemEventListener(visibilitychange, this,
   695                                     true /* use capture */);
   696 }
   698 } // anonymous namespace
   700 void
   701 Navigator::AddIdleObserver(MozIdleObserver& aIdleObserver, ErrorResult& aRv)
   702 {
   703   if (!mWindow) {
   704     aRv.Throw(NS_ERROR_UNEXPECTED);
   705     return;
   706   }
   707   CallbackObjectHolder<MozIdleObserver, nsIIdleObserver> holder(&aIdleObserver);
   708   nsCOMPtr<nsIIdleObserver> obs = holder.ToXPCOMCallback();
   709   if (NS_FAILED(mWindow->RegisterIdleObserver(obs))) {
   710     NS_WARNING("Failed to add idle observer.");
   711   }
   712 }
   714 void
   715 Navigator::RemoveIdleObserver(MozIdleObserver& aIdleObserver, ErrorResult& aRv)
   716 {
   717   if (!mWindow) {
   718     aRv.Throw(NS_ERROR_UNEXPECTED);
   719     return;
   720   }
   721   CallbackObjectHolder<MozIdleObserver, nsIIdleObserver> holder(&aIdleObserver);
   722   nsCOMPtr<nsIIdleObserver> obs = holder.ToXPCOMCallback();
   723   if (NS_FAILED(mWindow->UnregisterIdleObserver(obs))) {
   724     NS_WARNING("Failed to remove idle observer.");
   725   }
   726 }
   728 bool
   729 Navigator::Vibrate(uint32_t aDuration)
   730 {
   731   nsAutoTArray<uint32_t, 1> pattern;
   732   pattern.AppendElement(aDuration);
   733   return Vibrate(pattern);
   734 }
   736 bool
   737 Navigator::Vibrate(const nsTArray<uint32_t>& aPattern)
   738 {
   739   if (!mWindow) {
   740     return false;
   741   }
   743   nsCOMPtr<nsIDocument> doc = mWindow->GetExtantDoc();
   744   if (!doc) {
   745     return false;
   746   }
   748   if (doc->Hidden()) {
   749     // Hidden documents cannot start or stop a vibration.
   750     return false;
   751   }
   753   if (aPattern.Length() > sMaxVibrateListLen) {
   754     return false;
   755   }
   757   for (size_t i = 0; i < aPattern.Length(); ++i) {
   758     if (aPattern[i] > sMaxVibrateMS) {
   759       return false;
   760     }
   761   }
   763   // The spec says we check sVibratorEnabled after we've done the sanity
   764   // checking on the pattern.
   765   if (aPattern.IsEmpty() || !sVibratorEnabled) {
   766     return true;
   767   }
   769   // Add a listener to cancel the vibration if the document becomes hidden,
   770   // and remove the old visibility listener, if there was one.
   772   if (!gVibrateWindowListener) {
   773     // If gVibrateWindowListener is null, this is the first time we've vibrated,
   774     // and we need to register a listener to clear gVibrateWindowListener on
   775     // shutdown.
   776     ClearOnShutdown(&gVibrateWindowListener);
   777   }
   778   else {
   779     gVibrateWindowListener->RemoveListener();
   780   }
   781   gVibrateWindowListener = new VibrateWindowListener(mWindow, doc);
   783   hal::Vibrate(aPattern, mWindow);
   784   return true;
   785 }
   787 //*****************************************************************************
   788 //  Pointer Events interface
   789 //*****************************************************************************
   791 uint32_t
   792 Navigator::MaxTouchPoints()
   793 {
   794   nsCOMPtr<nsIWidget> widget = widget::WidgetUtils::DOMWindowToWidget(mWindow);
   796   NS_ENSURE_TRUE(widget, 0);
   797   return widget->GetMaxTouchPoints();
   798 }
   800 //*****************************************************************************
   801 //    Navigator::nsIDOMClientInformation
   802 //*****************************************************************************
   804 void
   805 Navigator::RegisterContentHandler(const nsAString& aMIMEType,
   806                                   const nsAString& aURI,
   807                                   const nsAString& aTitle,
   808                                   ErrorResult& aRv)
   809 {
   810   if (!mWindow || !mWindow->GetOuterWindow() || !mWindow->GetDocShell()) {
   811     return;
   812   }
   814   nsCOMPtr<nsIWebContentHandlerRegistrar> registrar =
   815     do_GetService(NS_WEBCONTENTHANDLERREGISTRAR_CONTRACTID);
   816   if (!registrar) {
   817     return;
   818   }
   820   aRv = registrar->RegisterContentHandler(aMIMEType, aURI, aTitle,
   821                                           mWindow->GetOuterWindow());
   822 }
   824 void
   825 Navigator::RegisterProtocolHandler(const nsAString& aProtocol,
   826                                    const nsAString& aURI,
   827                                    const nsAString& aTitle,
   828                                    ErrorResult& aRv)
   829 {
   830   if (!mWindow || !mWindow->GetOuterWindow() || !mWindow->GetDocShell()) {
   831     return;
   832   }
   834   nsCOMPtr<nsIWebContentHandlerRegistrar> registrar =
   835     do_GetService(NS_WEBCONTENTHANDLERREGISTRAR_CONTRACTID);
   836   if (!registrar) {
   837     return;
   838   }
   840   aRv = registrar->RegisterProtocolHandler(aProtocol, aURI, aTitle,
   841                                            mWindow->GetOuterWindow());
   842 }
   844 bool
   845 Navigator::MozIsLocallyAvailable(const nsAString &aURI,
   846                                  bool aWhenOffline,
   847                                  ErrorResult& aRv)
   848 {
   849   nsCOMPtr<nsIURI> uri;
   850   nsresult rv = NS_NewURI(getter_AddRefs(uri), aURI);
   851   if (NS_FAILED(rv)) {
   852     aRv.Throw(rv);
   853     return false;
   854   }
   856   // This method of checking the cache will only work for http/https urls.
   857   bool match;
   858   rv = uri->SchemeIs("http", &match);
   859   if (NS_FAILED(rv)) {
   860     aRv.Throw(rv);
   861     return false;
   862   }
   864   if (!match) {
   865     rv = uri->SchemeIs("https", &match);
   866     if (NS_FAILED(rv)) {
   867       aRv.Throw(rv);
   868       return false;
   869     }
   870     if (!match) {
   871       aRv.Throw(NS_ERROR_DOM_BAD_URI);
   872       return false;
   873     }
   874   }
   876   // Same origin check.
   877   JSContext *cx = nsContentUtils::GetCurrentJSContext();
   878   if (!cx) {
   879     aRv.Throw(NS_ERROR_FAILURE);
   880     return false;
   881   }
   883   rv = nsContentUtils::GetSecurityManager()->CheckSameOrigin(cx, uri);
   884   if (NS_FAILED(rv)) {
   885     aRv.Throw(rv);
   886     return false;
   887   }
   889   // These load flags cause an error to be thrown if there is no
   890   // valid cache entry, and skip the load if there is.
   891   // If the cache is busy, assume that it is not yet available rather
   892   // than waiting for it to become available.
   893   uint32_t loadFlags = nsIChannel::INHIBIT_CACHING |
   894                        nsICachingChannel::LOAD_NO_NETWORK_IO |
   895                        nsICachingChannel::LOAD_ONLY_IF_MODIFIED |
   896                        nsICachingChannel::LOAD_BYPASS_LOCAL_CACHE_IF_BUSY;
   898   if (aWhenOffline) {
   899     loadFlags |= nsICachingChannel::LOAD_CHECK_OFFLINE_CACHE |
   900                  nsICachingChannel::LOAD_ONLY_FROM_CACHE |
   901                  nsIRequest::LOAD_FROM_CACHE;
   902   }
   904   if (!mWindow) {
   905     aRv.Throw(NS_ERROR_UNEXPECTED);
   906     return false;
   907   }
   909   nsCOMPtr<nsILoadGroup> loadGroup;
   910   nsCOMPtr<nsIDocument> doc = mWindow->GetDoc();
   911   if (doc) {
   912     loadGroup = doc->GetDocumentLoadGroup();
   913   }
   915   nsCOMPtr<nsIChannel> channel;
   916   rv = NS_NewChannel(getter_AddRefs(channel), uri,
   917                      nullptr, loadGroup, nullptr, loadFlags);
   918   if (NS_FAILED(rv)) {
   919     aRv.Throw(rv);
   920     return false;
   921   }
   923   nsCOMPtr<nsIInputStream> stream;
   924   rv = channel->Open(getter_AddRefs(stream));
   925   if (NS_FAILED(rv)) {
   926     aRv.Throw(rv);
   927     return false;
   928   }
   930   stream->Close();
   932   nsresult status;
   933   rv = channel->GetStatus(&status);
   934   if (NS_FAILED(rv)) {
   935     aRv.Throw(rv);
   936     return false;
   937   }
   939   if (NS_FAILED(status)) {
   940     return false;
   941   }
   943   nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(channel);
   944   bool isAvailable;
   945   rv = httpChannel->GetRequestSucceeded(&isAvailable);
   946   if (NS_FAILED(rv)) {
   947     aRv.Throw(rv);
   948     return false;
   949   }
   950   return isAvailable;
   951 }
   953 nsDOMDeviceStorage*
   954 Navigator::GetDeviceStorage(const nsAString& aType, ErrorResult& aRv)
   955 {
   956   if (!mWindow || !mWindow->GetOuterWindow() || !mWindow->GetDocShell()) {
   957     aRv.Throw(NS_ERROR_FAILURE);
   958     return nullptr;
   959   }
   961   nsRefPtr<nsDOMDeviceStorage> storage;
   962   nsDOMDeviceStorage::CreateDeviceStorageFor(mWindow, aType,
   963                                              getter_AddRefs(storage));
   965   if (!storage) {
   966     return nullptr;
   967   }
   969   mDeviceStorageStores.AppendElement(storage);
   970   return storage;
   971 }
   973 void
   974 Navigator::GetDeviceStorages(const nsAString& aType,
   975                              nsTArray<nsRefPtr<nsDOMDeviceStorage> >& aStores,
   976                              ErrorResult& aRv)
   977 {
   978   if (!mWindow || !mWindow->GetOuterWindow() || !mWindow->GetDocShell()) {
   979     aRv.Throw(NS_ERROR_FAILURE);
   980     return;
   981   }
   983   nsDOMDeviceStorage::CreateDeviceStoragesFor(mWindow, aType, aStores);
   985   mDeviceStorageStores.AppendElements(aStores);
   986 }
   988 Geolocation*
   989 Navigator::GetGeolocation(ErrorResult& aRv)
   990 {
   991   if (mGeolocation) {
   992     return mGeolocation;
   993   }
   995   if (!mWindow || !mWindow->GetOuterWindow() || !mWindow->GetDocShell()) {
   996     aRv.Throw(NS_ERROR_FAILURE);
   997     return nullptr;
   998   }
  1000   mGeolocation = new Geolocation();
  1001   if (NS_FAILED(mGeolocation->Init(mWindow->GetOuterWindow()))) {
  1002     mGeolocation = nullptr;
  1003     aRv.Throw(NS_ERROR_FAILURE);
  1004     return nullptr;
  1007   return mGeolocation;
  1010 class BeaconStreamListener MOZ_FINAL : public nsIStreamListener
  1012   public:
  1013     BeaconStreamListener() {}
  1015     NS_DECL_ISUPPORTS
  1016     NS_DECL_NSISTREAMLISTENER
  1017     NS_DECL_NSIREQUESTOBSERVER
  1018 };
  1020 NS_IMPL_ISUPPORTS(BeaconStreamListener,
  1021                   nsIStreamListener,
  1022                   nsIRequestObserver)
  1025 NS_IMETHODIMP
  1026 BeaconStreamListener::OnStartRequest(nsIRequest *aRequest,
  1027                                      nsISupports *aContext)
  1029   aRequest->Cancel(NS_ERROR_NET_INTERRUPT);
  1030   return NS_BINDING_ABORTED;
  1033 NS_IMETHODIMP
  1034 BeaconStreamListener::OnStopRequest(nsIRequest *aRequest,
  1035                                     nsISupports *aContext,
  1036                                     nsresult aStatus)
  1038   return NS_OK;
  1041 NS_IMETHODIMP
  1042 BeaconStreamListener::OnDataAvailable(nsIRequest *aRequest,
  1043                                       nsISupports *ctxt,
  1044                                       nsIInputStream *inStr,
  1045                                       uint64_t sourceOffset,
  1046                                       uint32_t count)
  1048   MOZ_ASSERT(false);
  1049   return NS_OK;
  1052 bool
  1053 Navigator::SendBeacon(const nsAString& aUrl,
  1054                       const Nullable<ArrayBufferViewOrBlobOrStringOrFormData>& aData,
  1055                       ErrorResult& aRv)
  1057   if (!mWindow) {
  1058     aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
  1059     return false;
  1062   nsCOMPtr<nsIDocument> doc = mWindow->GetDoc();
  1063   if (!doc) {
  1064     aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
  1065     return false;
  1068   nsIURI* documentURI = doc->GetDocumentURI();
  1069   if (!documentURI) {
  1070     aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
  1071     return false;
  1074   nsCOMPtr<nsIURI> uri;
  1075   nsresult rv = nsContentUtils::NewURIWithDocumentCharset(
  1076                   getter_AddRefs(uri),
  1077                   aUrl,
  1078                   doc,
  1079                   doc->GetDocBaseURI());
  1080   if (NS_FAILED(rv)) {
  1081     aRv.Throw(NS_ERROR_DOM_URL_MISMATCH_ERR);
  1082     return false;
  1085   // Check whether this is a sane URI to load
  1086   // Explicitly disallow things like chrome:, javascript:, and data: URIs
  1087   nsCOMPtr<nsIPrincipal> principal = doc->NodePrincipal();
  1088   nsCOMPtr<nsIScriptSecurityManager> secMan = nsContentUtils::GetSecurityManager();
  1089   uint32_t flags = nsIScriptSecurityManager::DISALLOW_INHERIT_PRINCIPAL
  1090                    & nsIScriptSecurityManager::DISALLOW_SCRIPT;
  1091   rv = secMan->CheckLoadURIWithPrincipal(principal,
  1092                                          uri,
  1093                                          flags);
  1094   if (NS_FAILED(rv)) {
  1095     // Bad URI
  1096     aRv.Throw(rv);
  1097     return false;
  1100   // Check whether the CSP allows us to load
  1101   int16_t shouldLoad = nsIContentPolicy::ACCEPT;
  1102   rv = NS_CheckContentLoadPolicy(nsIContentPolicy::TYPE_BEACON,
  1103                                  uri,
  1104                                  principal,
  1105                                  doc,
  1106                                  EmptyCString(), //mime guess
  1107                                  nullptr,         //extra
  1108                                  &shouldLoad,
  1109                                  nsContentUtils::GetContentPolicy(),
  1110                                  nsContentUtils::GetSecurityManager());
  1111   if (NS_FAILED(rv) || NS_CP_REJECTED(shouldLoad)) {
  1112     // Disallowed by content policy
  1113     aRv.Throw(NS_ERROR_CONTENT_BLOCKED);
  1114     return false;
  1117   nsCOMPtr<nsIChannel> channel;
  1118   nsCOMPtr<nsIChannelPolicy> channelPolicy;
  1119   nsCOMPtr<nsIContentSecurityPolicy> csp;
  1120   rv = principal->GetCsp(getter_AddRefs(csp));
  1121   if (NS_FAILED(rv)) {
  1122     aRv.Throw(NS_ERROR_FAILURE);
  1123     return false;
  1126   if (csp) {
  1127     channelPolicy = do_CreateInstance(NSCHANNELPOLICY_CONTRACTID);
  1128     channelPolicy->SetContentSecurityPolicy(csp);
  1129     channelPolicy->SetLoadType(nsIContentPolicy::TYPE_BEACON);
  1131   rv = NS_NewChannel(getter_AddRefs(channel),
  1132                      uri,
  1133                      nullptr,
  1134                      nullptr,
  1135                      nullptr,
  1136                      nsIRequest::LOAD_NORMAL,
  1137                      channelPolicy);
  1138   if (NS_FAILED(rv)) {
  1139     aRv.Throw(rv);
  1140     return false;
  1143   nsCOMPtr<nsIPrivateBrowsingChannel> pbChannel = do_QueryInterface(channel);
  1144   if (pbChannel) {
  1145     nsIDocShell* docShell = mWindow->GetDocShell();
  1146     nsCOMPtr<nsILoadContext> loadContext = do_QueryInterface(docShell);
  1147     if (loadContext) {
  1148       rv = pbChannel->SetPrivate(loadContext->UsePrivateBrowsing());
  1149       if (NS_FAILED(rv)) {
  1150         NS_WARNING("Setting the privacy status on the beacon channel failed");
  1155   nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(channel);
  1156   if (!httpChannel) {
  1157     // Beacon spec only supports HTTP requests at this time
  1158     aRv.Throw(NS_ERROR_DOM_BAD_URI);
  1159     return false;
  1161   httpChannel->SetReferrer(documentURI);
  1163   // Anything that will need to refer to the window during the request
  1164   // will need to be done now.  For example, detection of whether any
  1165   // cookies set by this request are foreign.  Note that ThirdPartyUtil
  1166   // (nsIThirdPartyUtil.isThirdPartyChannel) does a secondary check between
  1167   // the channel URI and the cookie URI even when forceAllowThirdPartyCookie
  1168   // is set, so this is safe with regard to redirects.
  1169   nsCOMPtr<nsIHttpChannelInternal> httpChannelInternal(do_QueryInterface(channel));
  1170   nsCOMPtr<mozIThirdPartyUtil> thirdPartyUtil = do_GetService(THIRDPARTYUTIL_CONTRACTID);
  1171   if (!httpChannelInternal) {
  1172     aRv.Throw(NS_ERROR_DOM_BAD_URI);
  1173     return false;
  1175   bool isForeign = true;
  1176   thirdPartyUtil->IsThirdPartyWindow(mWindow, uri, &isForeign);
  1177   httpChannelInternal->SetForceAllowThirdPartyCookie(!isForeign);
  1179   nsCString mimeType;
  1180   if (!aData.IsNull()) {
  1181     nsCOMPtr<nsIInputStream> in;
  1183     if (aData.Value().IsString()) {
  1184       nsCString stringData = NS_ConvertUTF16toUTF8(aData.Value().GetAsString());
  1185       nsCOMPtr<nsIStringInputStream> strStream = do_CreateInstance(NS_STRINGINPUTSTREAM_CONTRACTID, &rv);
  1186       if (NS_FAILED(rv)) {
  1187         aRv.Throw(NS_ERROR_FAILURE);
  1188         return false;
  1190       rv = strStream->SetData(stringData.BeginReading(), stringData.Length());
  1191       if (NS_FAILED(rv)) {
  1192         aRv.Throw(NS_ERROR_FAILURE);
  1193         return false;
  1195       mimeType.AssignLiteral("text/plain;charset=UTF-8");
  1196       in = strStream;
  1198     } else if (aData.Value().IsArrayBufferView()) {
  1200       nsCOMPtr<nsIStringInputStream> strStream = do_CreateInstance(NS_STRINGINPUTSTREAM_CONTRACTID, &rv);
  1201       if (NS_FAILED(rv)) {
  1202         aRv.Throw(NS_ERROR_FAILURE);
  1203         return false;
  1206       ArrayBufferView& view = aData.Value().GetAsArrayBufferView();
  1207       view.ComputeLengthAndData();
  1208       rv = strStream->SetData(reinterpret_cast<char*>(view.Data()),
  1209                               view.Length());
  1211       if (NS_FAILED(rv)) {
  1212         aRv.Throw(NS_ERROR_FAILURE);
  1213         return false;
  1215       mimeType.AssignLiteral("application/octet-stream");
  1216       in = strStream;
  1218     } else if (aData.Value().IsBlob()) {
  1219       nsCOMPtr<nsIDOMBlob> blob = aData.Value().GetAsBlob();
  1220       rv = blob->GetInternalStream(getter_AddRefs(in));
  1221       if (NS_FAILED(rv)) {
  1222         aRv.Throw(NS_ERROR_FAILURE);
  1223         return false;
  1225       nsAutoString type;
  1226       rv = blob->GetType(type);
  1227       if (NS_FAILED(rv)) {
  1228         aRv.Throw(NS_ERROR_FAILURE);
  1229         return false;
  1231       mimeType = NS_ConvertUTF16toUTF8(type);
  1233     } else if (aData.Value().IsFormData()) {
  1234       nsFormData& form = aData.Value().GetAsFormData();
  1235       uint64_t len;
  1236       nsAutoCString charset;
  1237       form.GetSendInfo(getter_AddRefs(in),
  1238                        &len,
  1239                        mimeType,
  1240                        charset);
  1241     } else {
  1242       MOZ_ASSERT(false, "switch statements not in sync");
  1243       aRv.Throw(NS_ERROR_FAILURE);
  1244       return false;
  1247     nsCOMPtr<nsIUploadChannel2> uploadChannel = do_QueryInterface(channel);
  1248     if (!uploadChannel) {
  1249       aRv.Throw(NS_ERROR_FAILURE);
  1250       return false;
  1252     uploadChannel->ExplicitSetUploadStream(in, mimeType, -1,
  1253                                            NS_LITERAL_CSTRING("POST"),
  1254                                            false);
  1255   } else {
  1256     httpChannel->SetRequestMethod(NS_LITERAL_CSTRING("POST"));
  1259   nsCOMPtr<nsISupportsPriority> p = do_QueryInterface(channel);
  1260   if (p) {
  1261     p->SetPriority(nsISupportsPriority::PRIORITY_LOWEST);
  1264   nsRefPtr<nsCORSListenerProxy> cors = new nsCORSListenerProxy(new BeaconStreamListener(),
  1265                                                                principal,
  1266                                                                true);
  1268   // Start a preflight if cross-origin and content type is not whitelisted
  1269   rv = secMan->CheckSameOriginURI(documentURI, uri, false);
  1270   bool crossOrigin = NS_FAILED(rv);
  1271   nsAutoCString contentType, parsedCharset;
  1272   rv = NS_ParseContentType(mimeType, contentType, parsedCharset);
  1273   if (crossOrigin &&
  1274       contentType.Length() > 0 &&
  1275       !contentType.Equals(APPLICATION_WWW_FORM_URLENCODED) &&
  1276       !contentType.Equals(MULTIPART_FORM_DATA) &&
  1277       !contentType.Equals(TEXT_PLAIN)) {
  1278     nsCOMPtr<nsIChannel> preflightChannel;
  1279     nsTArray<nsCString> unsafeHeaders;
  1280     unsafeHeaders.AppendElement(NS_LITERAL_CSTRING("Content-Type"));
  1281     rv = NS_StartCORSPreflight(channel,
  1282                                cors,
  1283                                principal,
  1284                                true,
  1285                                unsafeHeaders,
  1286                                getter_AddRefs(preflightChannel));
  1287   } else {
  1288     rv = channel->AsyncOpen(cors, nullptr);
  1290   if (NS_FAILED(rv)) {
  1291     aRv.Throw(rv);
  1292     return false;
  1294   return true;
  1297 #ifdef MOZ_MEDIA_NAVIGATOR
  1298 void
  1299 Navigator::MozGetUserMedia(const MediaStreamConstraints& aConstraints,
  1300                            NavigatorUserMediaSuccessCallback& aOnSuccess,
  1301                            NavigatorUserMediaErrorCallback& aOnError,
  1302                            ErrorResult& aRv)
  1304   CallbackObjectHolder<NavigatorUserMediaSuccessCallback,
  1305                        nsIDOMGetUserMediaSuccessCallback> holder1(&aOnSuccess);
  1306   nsCOMPtr<nsIDOMGetUserMediaSuccessCallback> onsuccess =
  1307     holder1.ToXPCOMCallback();
  1309   CallbackObjectHolder<NavigatorUserMediaErrorCallback,
  1310                        nsIDOMGetUserMediaErrorCallback> holder2(&aOnError);
  1311   nsCOMPtr<nsIDOMGetUserMediaErrorCallback> onerror = holder2.ToXPCOMCallback();
  1313   if (!mWindow || !mWindow->GetOuterWindow() ||
  1314       mWindow->GetOuterWindow()->GetCurrentInnerWindow() != mWindow) {
  1315     aRv.Throw(NS_ERROR_NOT_AVAILABLE);
  1316     return;
  1319   bool privileged = nsContentUtils::IsChromeDoc(mWindow->GetExtantDoc());
  1321   MediaManager* manager = MediaManager::Get();
  1322   aRv = manager->GetUserMedia(privileged, mWindow, aConstraints,
  1323                               onsuccess, onerror);
  1326 void
  1327 Navigator::MozGetUserMediaDevices(const MediaStreamConstraints& aConstraints,
  1328                                   MozGetUserMediaDevicesSuccessCallback& aOnSuccess,
  1329                                   NavigatorUserMediaErrorCallback& aOnError,
  1330                                   uint64_t aInnerWindowID,
  1331                                   ErrorResult& aRv)
  1333   CallbackObjectHolder<MozGetUserMediaDevicesSuccessCallback,
  1334                        nsIGetUserMediaDevicesSuccessCallback> holder1(&aOnSuccess);
  1335   nsCOMPtr<nsIGetUserMediaDevicesSuccessCallback> onsuccess =
  1336     holder1.ToXPCOMCallback();
  1338   CallbackObjectHolder<NavigatorUserMediaErrorCallback,
  1339                        nsIDOMGetUserMediaErrorCallback> holder2(&aOnError);
  1340   nsCOMPtr<nsIDOMGetUserMediaErrorCallback> onerror = holder2.ToXPCOMCallback();
  1342   if (!mWindow || !mWindow->GetOuterWindow() ||
  1343       mWindow->GetOuterWindow()->GetCurrentInnerWindow() != mWindow) {
  1344     aRv.Throw(NS_ERROR_NOT_AVAILABLE);
  1345     return;
  1348   MediaManager* manager = MediaManager::Get();
  1349   aRv = manager->GetUserMediaDevices(mWindow, aConstraints, onsuccess, onerror,
  1350                                      aInnerWindowID);
  1352 #endif
  1354 DesktopNotificationCenter*
  1355 Navigator::GetMozNotification(ErrorResult& aRv)
  1357   if (mNotification) {
  1358     return mNotification;
  1361   if (!mWindow || !mWindow->GetDocShell()) {
  1362     aRv.Throw(NS_ERROR_FAILURE);
  1363     return nullptr;
  1366   mNotification = new DesktopNotificationCenter(mWindow);
  1367   return mNotification;
  1370 #ifdef MOZ_B2G_FM
  1372 using mozilla::dom::FMRadio;
  1374 FMRadio*
  1375 Navigator::GetMozFMRadio(ErrorResult& aRv)
  1377   if (!mFMRadio) {
  1378     if (!mWindow) {
  1379       aRv.Throw(NS_ERROR_UNEXPECTED);
  1380       return nullptr;
  1383     NS_ENSURE_TRUE(mWindow->GetDocShell(), nullptr);
  1385     mFMRadio = new FMRadio();
  1386     mFMRadio->Init(mWindow);
  1389   return mFMRadio;
  1392 #endif  // MOZ_B2G_FM
  1394 //*****************************************************************************
  1395 //    Navigator::nsINavigatorBattery
  1396 //*****************************************************************************
  1398 battery::BatteryManager*
  1399 Navigator::GetBattery(ErrorResult& aRv)
  1401   if (!mBatteryManager) {
  1402     if (!mWindow) {
  1403       aRv.Throw(NS_ERROR_UNEXPECTED);
  1404       return nullptr;
  1406     NS_ENSURE_TRUE(mWindow->GetDocShell(), nullptr);
  1408     mBatteryManager = new battery::BatteryManager(mWindow);
  1409     mBatteryManager->Init();
  1412   return mBatteryManager;
  1415 already_AddRefed<Promise>
  1416 Navigator::GetDataStores(const nsAString& aName, ErrorResult& aRv)
  1418   if (!mWindow || !mWindow->GetDocShell()) {
  1419     aRv.Throw(NS_ERROR_UNEXPECTED);
  1420     return nullptr;
  1423   nsCOMPtr<nsIDataStoreService> service =
  1424     do_GetService("@mozilla.org/datastore-service;1");
  1425   if (!service) {
  1426     aRv.Throw(NS_ERROR_FAILURE);
  1427     return nullptr;
  1430   nsCOMPtr<nsISupports> promise;
  1431   aRv = service->GetDataStores(mWindow, aName, getter_AddRefs(promise));
  1433   nsRefPtr<Promise> p = static_cast<Promise*>(promise.get());
  1434   return p.forget();
  1437 PowerManager*
  1438 Navigator::GetMozPower(ErrorResult& aRv)
  1440   if (!mPowerManager) {
  1441     if (!mWindow) {
  1442       aRv.Throw(NS_ERROR_UNEXPECTED);
  1443       return nullptr;
  1445     mPowerManager = PowerManager::CreateInstance(mWindow);
  1446     if (!mPowerManager) {
  1447       // We failed to get the power manager service?
  1448       aRv.Throw(NS_ERROR_UNEXPECTED);
  1452   return mPowerManager;
  1455 already_AddRefed<WakeLock>
  1456 Navigator::RequestWakeLock(const nsAString &aTopic, ErrorResult& aRv)
  1458   if (!mWindow) {
  1459     aRv.Throw(NS_ERROR_UNEXPECTED);
  1460     return nullptr;
  1463   nsRefPtr<power::PowerManagerService> pmService =
  1464     power::PowerManagerService::GetInstance();
  1465   // Maybe it went away for some reason... Or maybe we're just called
  1466   // from our XPCOM method.
  1467   if (!pmService) {
  1468     aRv.Throw(NS_ERROR_UNEXPECTED);
  1469     return nullptr;
  1472   return pmService->NewWakeLock(aTopic, mWindow, aRv);
  1475 nsIDOMMozMobileMessageManager*
  1476 Navigator::GetMozMobileMessage()
  1478   if (!mMobileMessageManager) {
  1479     // Check that our window has not gone away
  1480     NS_ENSURE_TRUE(mWindow, nullptr);
  1481     NS_ENSURE_TRUE(mWindow->GetDocShell(), nullptr);
  1483     mMobileMessageManager = new MobileMessageManager();
  1484     mMobileMessageManager->Init(mWindow);
  1487   return mMobileMessageManager;
  1490 Telephony*
  1491 Navigator::GetMozTelephony(ErrorResult& aRv)
  1493   if (!mTelephony) {
  1494     if (!mWindow) {
  1495       aRv.Throw(NS_ERROR_UNEXPECTED);
  1496       return nullptr;
  1498     mTelephony = Telephony::Create(mWindow, aRv);
  1501   return mTelephony;
  1504 #ifdef MOZ_B2G_RIL
  1506 MobileConnectionArray*
  1507 Navigator::GetMozMobileConnections(ErrorResult& aRv)
  1509   if (!mMobileConnections) {
  1510     if (!mWindow) {
  1511       aRv.Throw(NS_ERROR_UNEXPECTED);
  1512       return nullptr;
  1514     mMobileConnections = new MobileConnectionArray(mWindow);
  1517   return mMobileConnections;
  1520 CellBroadcast*
  1521 Navigator::GetMozCellBroadcast(ErrorResult& aRv)
  1523   if (!mCellBroadcast) {
  1524     if (!mWindow) {
  1525       aRv.Throw(NS_ERROR_UNEXPECTED);
  1526       return nullptr;
  1528     mCellBroadcast = CellBroadcast::Create(mWindow, aRv);
  1531   return mCellBroadcast;
  1534 Voicemail*
  1535 Navigator::GetMozVoicemail(ErrorResult& aRv)
  1537   if (!mVoicemail) {
  1538     if (!mWindow) {
  1539       aRv.Throw(NS_ERROR_UNEXPECTED);
  1540       return nullptr;
  1543     aRv = NS_NewVoicemail(mWindow, getter_AddRefs(mVoicemail));
  1544     if (aRv.Failed()) {
  1545       return nullptr;
  1549   return mVoicemail;
  1552 IccManager*
  1553 Navigator::GetMozIccManager(ErrorResult& aRv)
  1555   if (!mIccManager) {
  1556     if (!mWindow) {
  1557       aRv.Throw(NS_ERROR_UNEXPECTED);
  1558       return nullptr;
  1560     NS_ENSURE_TRUE(mWindow->GetDocShell(), nullptr);
  1562     mIccManager = new IccManager(mWindow);
  1565   return mIccManager;
  1568 #endif // MOZ_B2G_RIL
  1570 #ifdef MOZ_GAMEPAD
  1571 void
  1572 Navigator::GetGamepads(nsTArray<nsRefPtr<Gamepad> >& aGamepads,
  1573                        ErrorResult& aRv)
  1575   if (!mWindow) {
  1576     aRv.Throw(NS_ERROR_UNEXPECTED);
  1577     return;
  1579   NS_ENSURE_TRUE_VOID(mWindow->GetDocShell());
  1580   nsGlobalWindow* win = static_cast<nsGlobalWindow*>(mWindow.get());
  1581   win->SetHasGamepadEventListener(true);
  1582   win->GetGamepads(aGamepads);
  1584 #endif
  1586 //*****************************************************************************
  1587 //    Navigator::nsIMozNavigatorNetwork
  1588 //*****************************************************************************
  1590 NS_IMETHODIMP
  1591 Navigator::GetProperties(nsINetworkProperties** aProperties)
  1593   ErrorResult rv;
  1594   NS_IF_ADDREF(*aProperties = GetConnection(rv));
  1595   return NS_OK;
  1598 network::Connection*
  1599 Navigator::GetConnection(ErrorResult& aRv)
  1601   if (!mConnection) {
  1602     if (!mWindow) {
  1603       aRv.Throw(NS_ERROR_UNEXPECTED);
  1604       return nullptr;
  1606     mConnection = new network::Connection();
  1607     mConnection->Init(mWindow);
  1610   return mConnection;
  1613 #ifdef MOZ_B2G_BT
  1614 bluetooth::BluetoothManager*
  1615 Navigator::GetMozBluetooth(ErrorResult& aRv)
  1617   if (!mBluetooth) {
  1618     if (!mWindow) {
  1619       aRv.Throw(NS_ERROR_UNEXPECTED);
  1620       return nullptr;
  1622     mBluetooth = bluetooth::BluetoothManager::Create(mWindow);
  1625   return mBluetooth;
  1627 #endif //MOZ_B2G_BT
  1629 nsresult
  1630 Navigator::EnsureMessagesManager()
  1632   if (mMessagesManager) {
  1633     return NS_OK;
  1636   NS_ENSURE_STATE(mWindow);
  1638   nsresult rv;
  1639   nsCOMPtr<nsIDOMNavigatorSystemMessages> messageManager =
  1640     do_CreateInstance("@mozilla.org/system-message-manager;1", &rv);
  1642   nsCOMPtr<nsIDOMGlobalPropertyInitializer> gpi =
  1643     do_QueryInterface(messageManager);
  1644   NS_ENSURE_TRUE(gpi, NS_ERROR_FAILURE);
  1646   // We don't do anything with the return value.
  1647   AutoJSContext cx;
  1648   JS::Rooted<JS::Value> prop_val(cx);
  1649   rv = gpi->Init(mWindow, &prop_val);
  1650   NS_ENSURE_SUCCESS(rv, rv);
  1652   mMessagesManager = messageManager.forget();
  1654   return NS_OK;
  1657 bool
  1658 Navigator::MozHasPendingMessage(const nsAString& aType, ErrorResult& aRv)
  1660   // The WebIDL binding is responsible for the pref check here.
  1661   nsresult rv = EnsureMessagesManager();
  1662   if (NS_FAILED(rv)) {
  1663     aRv.Throw(rv);
  1664     return false;
  1667   bool result = false;
  1668   rv = mMessagesManager->MozHasPendingMessage(aType, &result);
  1669   if (NS_FAILED(rv)) {
  1670     aRv.Throw(rv);
  1671     return false;
  1673   return result;
  1676 void
  1677 Navigator::MozSetMessageHandler(const nsAString& aType,
  1678                                 systemMessageCallback* aCallback,
  1679                                 ErrorResult& aRv)
  1681   // The WebIDL binding is responsible for the pref check here.
  1682   nsresult rv = EnsureMessagesManager();
  1683   if (NS_FAILED(rv)) {
  1684     aRv.Throw(rv);
  1685     return;
  1688   CallbackObjectHolder<systemMessageCallback, nsIDOMSystemMessageCallback>
  1689     holder(aCallback);
  1690   nsCOMPtr<nsIDOMSystemMessageCallback> callback = holder.ToXPCOMCallback();
  1692   rv = mMessagesManager->MozSetMessageHandler(aType, callback);
  1693   if (NS_FAILED(rv)) {
  1694     aRv.Throw(rv);
  1698 #ifdef MOZ_TIME_MANAGER
  1699 time::TimeManager*
  1700 Navigator::GetMozTime(ErrorResult& aRv)
  1702   if (!mWindow) {
  1703     aRv.Throw(NS_ERROR_UNEXPECTED);
  1704     return nullptr;
  1707   if (!mTimeManager) {
  1708     mTimeManager = new time::TimeManager(mWindow);
  1711   return mTimeManager;
  1713 #endif
  1715 nsDOMCameraManager*
  1716 Navigator::GetMozCameras(ErrorResult& aRv)
  1718   if (!mCameraManager) {
  1719     if (!mWindow ||
  1720         !mWindow->GetOuterWindow() ||
  1721         mWindow->GetOuterWindow()->GetCurrentInnerWindow() != mWindow) {
  1722       aRv.Throw(NS_ERROR_NOT_AVAILABLE);
  1723       return nullptr;
  1726     mCameraManager = nsDOMCameraManager::CreateInstance(mWindow);
  1729   return mCameraManager;
  1732 size_t
  1733 Navigator::SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const
  1735   size_t n = aMallocSizeOf(this);
  1737   // TODO: add SizeOfIncludingThis() to nsMimeTypeArray, bug 674113.
  1738   // TODO: add SizeOfIncludingThis() to nsPluginArray, bug 674114.
  1739   // TODO: add SizeOfIncludingThis() to Geolocation, bug 674115.
  1740   // TODO: add SizeOfIncludingThis() to DesktopNotificationCenter, bug 674116.
  1742   return n;
  1745 void
  1746 Navigator::SetWindow(nsPIDOMWindow *aInnerWindow)
  1748   NS_ASSERTION(aInnerWindow->IsInnerWindow(),
  1749                "Navigator must get an inner window!");
  1750   mWindow = aInnerWindow;
  1753 void
  1754 Navigator::OnNavigation()
  1756   if (!mWindow) {
  1757     return;
  1760 #ifdef MOZ_MEDIA_NAVIGATOR
  1761   // Inform MediaManager in case there are live streams or pending callbacks.
  1762   MediaManager *manager = MediaManager::Get();
  1763   if (manager) {
  1764     manager->OnNavigation(mWindow->WindowID());
  1766 #endif
  1767   if (mCameraManager) {
  1768     mCameraManager->OnNavigation(mWindow->WindowID());
  1772 bool
  1773 Navigator::CheckPermission(const char* type)
  1775   return CheckPermission(mWindow, type);
  1778 /* static */
  1779 bool
  1780 Navigator::CheckPermission(nsPIDOMWindow* aWindow, const char* aType)
  1782   if (!aWindow) {
  1783     return false;
  1786   nsCOMPtr<nsIPermissionManager> permMgr =
  1787     do_GetService(NS_PERMISSIONMANAGER_CONTRACTID);
  1788   NS_ENSURE_TRUE(permMgr, false);
  1790   uint32_t permission = nsIPermissionManager::DENY_ACTION;
  1791   permMgr->TestPermissionFromWindow(aWindow, aType, &permission);
  1792   return permission == nsIPermissionManager::ALLOW_ACTION;
  1795 #ifdef MOZ_AUDIO_CHANNEL_MANAGER
  1796 system::AudioChannelManager*
  1797 Navigator::GetMozAudioChannelManager(ErrorResult& aRv)
  1799   if (!mAudioChannelManager) {
  1800     if (!mWindow) {
  1801       aRv.Throw(NS_ERROR_UNEXPECTED);
  1802       return nullptr;
  1804     mAudioChannelManager = new system::AudioChannelManager();
  1805     mAudioChannelManager->Init(mWindow);
  1808   return mAudioChannelManager;
  1810 #endif
  1812 bool
  1813 Navigator::DoNewResolve(JSContext* aCx, JS::Handle<JSObject*> aObject,
  1814                         JS::Handle<jsid> aId,
  1815                         JS::MutableHandle<JSPropertyDescriptor> aDesc)
  1817   if (!JSID_IS_STRING(aId)) {
  1818     return true;
  1821   nsScriptNameSpaceManager* nameSpaceManager = GetNameSpaceManager();
  1822   if (!nameSpaceManager) {
  1823     return Throw(aCx, NS_ERROR_NOT_INITIALIZED);
  1826   nsDependentJSString name(aId);
  1828   const nsGlobalNameStruct* name_struct =
  1829     nameSpaceManager->LookupNavigatorName(name);
  1830   if (!name_struct) {
  1831     return true;
  1834   JS::Rooted<JSObject*> naviObj(aCx,
  1835                                 js::CheckedUnwrap(aObject,
  1836                                                   /* stopAtOuter = */ false));
  1837   if (!naviObj) {
  1838     return Throw(aCx, NS_ERROR_DOM_SECURITY_ERR);
  1841   if (name_struct->mType == nsGlobalNameStruct::eTypeNewDOMBinding) {
  1842     ConstructNavigatorProperty construct = name_struct->mConstructNavigatorProperty;
  1843     MOZ_ASSERT(construct);
  1845     JS::Rooted<JSObject*> domObject(aCx);
  1847       // Make sure to do the creation of our object in the compartment
  1848       // of naviObj, especially since we plan to cache that object.
  1849       JSAutoCompartment ac(aCx, naviObj);
  1851       // Check whether our constructor is enabled after we unwrap Xrays, since
  1852       // we don't want to define an interface on the Xray if it's disabled in
  1853       // the target global, even if it's enabled in the Xray's global.
  1854       if (name_struct->mConstructorEnabled &&
  1855           !(*name_struct->mConstructorEnabled)(aCx, naviObj)) {
  1856         return true;
  1859       if (name.EqualsLiteral("mozSettings")) {
  1860         bool hasPermission = CheckPermission("settings-read") ||
  1861                              CheckPermission("settings-write");
  1862         if (!hasPermission) {
  1863           FillPropertyDescriptor(aDesc, aObject, JS::NullValue(), false);
  1864           return true;
  1868       if (name.EqualsLiteral("mozDownloadManager")) {
  1869         if (!CheckPermission("downloads")) {
  1870           FillPropertyDescriptor(aDesc, aObject, JS::NullValue(), false);
  1871           return true;
  1875       nsISupports* existingObject = mCachedResolveResults.GetWeak(name);
  1876       if (existingObject) {
  1877         // We know all of our WebIDL objects here are wrappercached, so just go
  1878         // ahead and WrapObject() them.  We can't use WrapNewBindingObject,
  1879         // because we don't have the concrete type.
  1880         JS::Rooted<JS::Value> wrapped(aCx);
  1881         if (!dom::WrapObject(aCx, existingObject, &wrapped)) {
  1882           return false;
  1884         domObject = &wrapped.toObject();
  1885       } else {
  1886         domObject = construct(aCx, naviObj);
  1887         if (!domObject) {
  1888           return Throw(aCx, NS_ERROR_FAILURE);
  1891         // Store the value in our cache
  1892         nsISupports* native = UnwrapDOMObjectToISupports(domObject);
  1893         MOZ_ASSERT(native);
  1894         mCachedResolveResults.Put(name, native);
  1898     if (!JS_WrapObject(aCx, &domObject)) {
  1899       return false;
  1902     FillPropertyDescriptor(aDesc, aObject, JS::ObjectValue(*domObject), false);
  1903     return true;
  1906   NS_ASSERTION(name_struct->mType == nsGlobalNameStruct::eTypeNavigatorProperty,
  1907                "unexpected type");
  1909   nsresult rv = NS_OK;
  1911   nsCOMPtr<nsISupports> native;
  1912   bool hadCachedNative = mCachedResolveResults.Get(name, getter_AddRefs(native));
  1913   bool okToUseNative;
  1914   JS::Rooted<JS::Value> prop_val(aCx);
  1915   if (hadCachedNative) {
  1916     okToUseNative = true;
  1917   } else {
  1918     native = do_CreateInstance(name_struct->mCID, &rv);
  1919     if (NS_FAILED(rv)) {
  1920       return Throw(aCx, rv);
  1923     nsCOMPtr<nsIDOMGlobalPropertyInitializer> gpi(do_QueryInterface(native));
  1925     if (gpi) {
  1926       if (!mWindow) {
  1927         return Throw(aCx, NS_ERROR_UNEXPECTED);
  1930       rv = gpi->Init(mWindow, &prop_val);
  1931       if (NS_FAILED(rv)) {
  1932         return Throw(aCx, rv);
  1936     okToUseNative = !prop_val.isObjectOrNull();
  1939   if (okToUseNative) {
  1940     // Make sure to do the creation of our object in the compartment
  1941     // of naviObj, especially since we plan to cache that object.
  1942     JSAutoCompartment ac(aCx, naviObj);
  1944     rv = nsContentUtils::WrapNative(aCx, native, &prop_val);
  1946     if (NS_FAILED(rv)) {
  1947       return Throw(aCx, rv);
  1950     // Now that we know we managed to wrap this thing properly, go ahead and
  1951     // cache it as needed.
  1952     if (!hadCachedNative) {
  1953       mCachedResolveResults.Put(name, native);
  1957   if (!JS_WrapValue(aCx, &prop_val)) {
  1958     return Throw(aCx, NS_ERROR_UNEXPECTED);
  1961   FillPropertyDescriptor(aDesc, aObject, prop_val, false);
  1962   return true;
  1965 struct NavigatorNameEnumeratorClosure
  1967   NavigatorNameEnumeratorClosure(JSContext* aCx, JSObject* aWrapper,
  1968                                  nsTArray<nsString>& aNames)
  1969     : mCx(aCx),
  1970       mWrapper(aCx, aWrapper),
  1971       mNames(aNames)
  1975   JSContext* mCx;
  1976   JS::Rooted<JSObject*> mWrapper;
  1977   nsTArray<nsString>& mNames;
  1978 };
  1980 static PLDHashOperator
  1981 SaveNavigatorName(const nsAString& aName,
  1982                   const nsGlobalNameStruct& aNameStruct,
  1983                   void* aClosure)
  1985   NavigatorNameEnumeratorClosure* closure =
  1986     static_cast<NavigatorNameEnumeratorClosure*>(aClosure);
  1987   if (!aNameStruct.mConstructorEnabled ||
  1988       aNameStruct.mConstructorEnabled(closure->mCx, closure->mWrapper)) {
  1989     closure->mNames.AppendElement(aName);
  1991   return PL_DHASH_NEXT;
  1994 void
  1995 Navigator::GetOwnPropertyNames(JSContext* aCx, nsTArray<nsString>& aNames,
  1996                                ErrorResult& aRv)
  1998   nsScriptNameSpaceManager *nameSpaceManager = GetNameSpaceManager();
  1999   if (!nameSpaceManager) {
  2000     NS_ERROR("Can't get namespace manager.");
  2001     aRv.Throw(NS_ERROR_UNEXPECTED);
  2002     return;
  2005   NavigatorNameEnumeratorClosure closure(aCx, GetWrapper(), aNames);
  2006   nameSpaceManager->EnumerateNavigatorNames(SaveNavigatorName, &closure);
  2009 JSObject*
  2010 Navigator::WrapObject(JSContext* cx)
  2012   return NavigatorBinding::Wrap(cx, this);
  2015 /* static */
  2016 bool
  2017 Navigator::HasBatterySupport(JSContext* /* unused*/, JSObject* /*unused */)
  2019   return battery::BatteryManager::HasSupport();
  2022 /* static */
  2023 bool
  2024 Navigator::HasPowerSupport(JSContext* /* unused */, JSObject* aGlobal)
  2026   nsCOMPtr<nsPIDOMWindow> win = GetWindowFromGlobal(aGlobal);
  2027   return win && PowerManager::CheckPermission(win);
  2030 /* static */
  2031 bool
  2032 Navigator::HasPhoneNumberSupport(JSContext* /* unused */, JSObject* aGlobal)
  2034   nsCOMPtr<nsPIDOMWindow> win = GetWindowFromGlobal(aGlobal);
  2035   return CheckPermission(win, "phonenumberservice");
  2038 /* static */
  2039 bool
  2040 Navigator::HasIdleSupport(JSContext*  /* unused */, JSObject* aGlobal)
  2042   if (!nsContentUtils::IsIdleObserverAPIEnabled()) {
  2043     return false;
  2046   nsCOMPtr<nsPIDOMWindow> win = GetWindowFromGlobal(aGlobal);
  2047   return CheckPermission(win, "idle");
  2050 /* static */
  2051 bool
  2052 Navigator::HasWakeLockSupport(JSContext* /* unused*/, JSObject* /*unused */)
  2054   nsCOMPtr<nsIPowerManagerService> pmService =
  2055     do_GetService(POWERMANAGERSERVICE_CONTRACTID);
  2056   // No service means no wake lock support
  2057   return !!pmService;
  2060 /* static */
  2061 bool
  2062 Navigator::HasMobileMessageSupport(JSContext* /* unused */, JSObject* aGlobal)
  2064   nsCOMPtr<nsPIDOMWindow> win = GetWindowFromGlobal(aGlobal);
  2066 #ifndef MOZ_WEBSMS_BACKEND
  2067   return false;
  2068 #endif
  2070   // First of all, the general pref has to be turned on.
  2071   bool enabled = false;
  2072   Preferences::GetBool("dom.sms.enabled", &enabled);
  2073   if (!enabled) {
  2074     return false;
  2077   NS_ENSURE_TRUE(win, false);
  2078   NS_ENSURE_TRUE(win->GetDocShell(), false);
  2080   if (!CheckPermission(win, "sms")) {
  2081     return false;
  2084   return true;
  2087 /* static */
  2088 bool
  2089 Navigator::HasTelephonySupport(JSContext* cx, JSObject* aGlobal)
  2091   JS::Rooted<JSObject*> global(cx, aGlobal);
  2093   // First of all, the general pref has to be turned on.
  2094   bool enabled = false;
  2095   Preferences::GetBool("dom.telephony.enabled", &enabled);
  2096   if (!enabled) {
  2097     return false;
  2100   nsCOMPtr<nsPIDOMWindow> win = GetWindowFromGlobal(global);
  2101   return win && CheckPermission(win, "telephony");
  2104 /* static */
  2105 bool
  2106 Navigator::HasCameraSupport(JSContext* /* unused */, JSObject* aGlobal)
  2108   nsCOMPtr<nsPIDOMWindow> win = GetWindowFromGlobal(aGlobal);
  2109   return win && nsDOMCameraManager::CheckPermission(win);
  2112 #ifdef MOZ_B2G_RIL
  2113 /* static */
  2114 bool
  2115 Navigator::HasMobileConnectionSupport(JSContext* /* unused */,
  2116                                       JSObject* aGlobal)
  2118   // First of all, the general pref has to be turned on.
  2119   bool enabled = false;
  2120   Preferences::GetBool("dom.mobileconnection.enabled", &enabled);
  2121   NS_ENSURE_TRUE(enabled, false);
  2123   nsCOMPtr<nsPIDOMWindow> win = GetWindowFromGlobal(aGlobal);
  2124   return win && (CheckPermission(win, "mobileconnection") ||
  2125                  CheckPermission(win, "mobilenetwork"));
  2128 /* static */
  2129 bool
  2130 Navigator::HasCellBroadcastSupport(JSContext* /* unused */,
  2131                                    JSObject* aGlobal)
  2133   // First of all, the general pref has to be turned on.
  2134   bool enabled = false;
  2135   Preferences::GetBool("dom.cellbroadcast.enabled", &enabled);
  2136   NS_ENSURE_TRUE(enabled, false);
  2138   nsCOMPtr<nsPIDOMWindow> win = GetWindowFromGlobal(aGlobal);
  2139   return win && CheckPermission(win, "cellbroadcast");
  2142 /* static */
  2143 bool
  2144 Navigator::HasVoicemailSupport(JSContext* /* unused */,
  2145                                JSObject* aGlobal)
  2147   // First of all, the general pref has to be turned on.
  2148   bool enabled = false;
  2149   Preferences::GetBool("dom.voicemail.enabled", &enabled);
  2150   NS_ENSURE_TRUE(enabled, false);
  2152   nsCOMPtr<nsPIDOMWindow> win = GetWindowFromGlobal(aGlobal);
  2153   return win && CheckPermission(win, "voicemail");
  2156 /* static */
  2157 bool
  2158 Navigator::HasIccManagerSupport(JSContext* /* unused */,
  2159                                 JSObject* aGlobal)
  2161   // First of all, the general pref has to be turned on.
  2162   bool enabled = false;
  2163   Preferences::GetBool("dom.icc.enabled", &enabled);
  2164   NS_ENSURE_TRUE(enabled, false);
  2166   nsCOMPtr<nsPIDOMWindow> win = GetWindowFromGlobal(aGlobal);
  2167   return win && CheckPermission(win, "mobileconnection");
  2169 #endif // MOZ_B2G_RIL
  2171 /* static */
  2172 bool
  2173 Navigator::HasWifiManagerSupport(JSContext* /* unused */,
  2174                                  JSObject* aGlobal)
  2176   // On XBL scope, the global object is NOT |window|. So we have
  2177   // to use nsContentUtils::GetObjectPrincipal to get the principal
  2178   // and test directly with permission manager.
  2180   nsIPrincipal* principal = nsContentUtils::GetObjectPrincipal(aGlobal);
  2182   nsCOMPtr<nsIPermissionManager> permMgr =
  2183     do_GetService(NS_PERMISSIONMANAGER_CONTRACTID);
  2184   NS_ENSURE_TRUE(permMgr, false);
  2186   uint32_t permission = nsIPermissionManager::DENY_ACTION;
  2187   permMgr->TestPermissionFromPrincipal(principal, "wifi-manage", &permission);
  2188   return nsIPermissionManager::ALLOW_ACTION == permission;
  2191 #ifdef MOZ_B2G_BT
  2192 /* static */
  2193 bool
  2194 Navigator::HasBluetoothSupport(JSContext* /* unused */, JSObject* aGlobal)
  2196   nsCOMPtr<nsPIDOMWindow> win = GetWindowFromGlobal(aGlobal);
  2197   return win && bluetooth::BluetoothManager::CheckPermission(win);
  2199 #endif // MOZ_B2G_BT
  2201 #ifdef MOZ_B2G_FM
  2202 /* static */
  2203 bool
  2204 Navigator::HasFMRadioSupport(JSContext* /* unused */, JSObject* aGlobal)
  2206   nsCOMPtr<nsPIDOMWindow> win = GetWindowFromGlobal(aGlobal);
  2207   return win && CheckPermission(win, "fmradio");
  2209 #endif // MOZ_B2G_FM
  2211 #ifdef MOZ_NFC
  2212 /* static */
  2213 bool
  2214 Navigator::HasNfcSupport(JSContext* /* unused */, JSObject* aGlobal)
  2216   // Do not support NFC if NFC content helper does not exist.
  2217   nsCOMPtr<nsISupports> contentHelper = do_GetService("@mozilla.org/nfc/content-helper;1");
  2218   if (!contentHelper) {
  2219     return false;
  2222   nsCOMPtr<nsPIDOMWindow> win = GetWindowFromGlobal(aGlobal);
  2223   return win && (CheckPermission(win, "nfc-read") ||
  2224                  CheckPermission(win, "nfc-write"));
  2227 /* static */
  2228 bool
  2229 Navigator::HasNfcPeerSupport(JSContext* /* unused */, JSObject* aGlobal)
  2231   nsCOMPtr<nsPIDOMWindow> win = GetWindowFromGlobal(aGlobal);
  2232   return win && CheckPermission(win, "nfc-write");
  2235 /* static */
  2236 bool
  2237 Navigator::HasNfcManagerSupport(JSContext* /* unused */, JSObject* aGlobal)
  2239   nsCOMPtr<nsPIDOMWindow> win = GetWindowFromGlobal(aGlobal);
  2240   return win && CheckPermission(win, "nfc-manager");
  2242 #endif // MOZ_NFC
  2244 #ifdef MOZ_TIME_MANAGER
  2245 /* static */
  2246 bool
  2247 Navigator::HasTimeSupport(JSContext* /* unused */, JSObject* aGlobal)
  2249   nsCOMPtr<nsPIDOMWindow> win = GetWindowFromGlobal(aGlobal);
  2250   return win && CheckPermission(win, "time");
  2252 #endif // MOZ_TIME_MANAGER
  2254 #ifdef MOZ_MEDIA_NAVIGATOR
  2255 /* static */
  2256 bool
  2257 Navigator::HasUserMediaSupport(JSContext* /* unused */,
  2258                                JSObject* /* unused */)
  2260   // Make enabling peerconnection enable getUserMedia() as well
  2261   return Preferences::GetBool("media.navigator.enabled", false) ||
  2262          Preferences::GetBool("media.peerconnection.enabled", false);
  2264 #endif // MOZ_MEDIA_NAVIGATOR
  2266 /* static */
  2267 bool
  2268 Navigator::HasPushNotificationsSupport(JSContext* /* unused */,
  2269                                        JSObject* aGlobal)
  2271   nsCOMPtr<nsPIDOMWindow> win = GetWindowFromGlobal(aGlobal);
  2272   return Preferences::GetBool("services.push.enabled", false) &&
  2273          win && CheckPermission(win, "push");
  2276 /* static */
  2277 bool
  2278 Navigator::HasInputMethodSupport(JSContext* /* unused */,
  2279                                  JSObject* aGlobal)
  2281   nsCOMPtr<nsPIDOMWindow> win = GetWindowFromGlobal(aGlobal);
  2282   if (!win || !Preferences::GetBool("dom.mozInputMethod.enabled", false)) {
  2283     return false;
  2286   if (Preferences::GetBool("dom.mozInputMethod.testing", false)) {
  2287     return true;
  2290   return CheckPermission(win, "input") ||
  2291          CheckPermission(win, "input-manage");
  2294 /* static */
  2295 bool
  2296 Navigator::HasDataStoreSupport(JSContext* cx, JSObject* aGlobal)
  2298   JS::Rooted<JSObject*> global(cx, aGlobal);
  2300   // First of all, the general pref has to be turned on.
  2301   bool enabled = false;
  2302   Preferences::GetBool("dom.datastore.enabled", &enabled);
  2303   if (!enabled) {
  2304     return false;
  2307   // Just for testing, we can enable DataStore for any kind of app.
  2308   if (Preferences::GetBool("dom.testing.datastore_enabled_for_hosted_apps", false)) {
  2309     return true;
  2312   nsCOMPtr<nsPIDOMWindow> win = GetWindowFromGlobal(global);
  2313   if (!win) {
  2314     return false;
  2317   nsIDocument* doc = win->GetExtantDoc();
  2318   if (!doc || !doc->NodePrincipal()) {
  2319     return false;
  2322   uint16_t status;
  2323   if (NS_FAILED(doc->NodePrincipal()->GetAppStatus(&status))) {
  2324     return false;
  2327   return status == nsIPrincipal::APP_STATUS_CERTIFIED;
  2330 /* static */
  2331 bool
  2332 Navigator::HasDownloadsSupport(JSContext* aCx, JSObject* aGlobal)
  2334   nsCOMPtr<nsPIDOMWindow> win = GetWindowFromGlobal(aGlobal);
  2336   return win &&
  2337          CheckPermission(win, "downloads")  &&
  2338          Preferences::GetBool("dom.mozDownloads.enabled");
  2341 /* static */
  2342 bool
  2343 Navigator::HasPermissionSettingsSupport(JSContext* /* unused */, JSObject* aGlobal)
  2345   nsCOMPtr<nsPIDOMWindow> win = GetWindowFromGlobal(aGlobal);
  2346   return CheckPermission(win, "permissions");
  2349 /* static */
  2350 already_AddRefed<nsPIDOMWindow>
  2351 Navigator::GetWindowFromGlobal(JSObject* aGlobal)
  2353   nsCOMPtr<nsPIDOMWindow> win =
  2354     do_QueryInterface(nsJSUtils::GetStaticScriptGlobal(aGlobal));
  2355   MOZ_ASSERT(!win || win->IsInnerWindow());
  2356   return win.forget();
  2359 nsresult
  2360 Navigator::GetPlatform(nsAString& aPlatform, bool aUsePrefOverriddenValue)
  2362   MOZ_ASSERT(NS_IsMainThread());
  2364   if (aUsePrefOverriddenValue && !nsContentUtils::IsCallerChrome()) {
  2365     const nsAdoptingString& override =
  2366       mozilla::Preferences::GetString("general.platform.override");
  2368     if (override) {
  2369       aPlatform = override;
  2370       return NS_OK;
  2374   nsresult rv;
  2376   nsCOMPtr<nsIHttpProtocolHandler>
  2377     service(do_GetService(NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX "http", &rv));
  2378   NS_ENSURE_SUCCESS(rv, rv);
  2380   // Sorry for the #if platform ugliness, but Communicator is likewise
  2381   // hardcoded and we are seeking backward compatibility here (bug 47080).
  2382 #if defined(_WIN64)
  2383   aPlatform.AssignLiteral("Win64");
  2384 #elif defined(WIN32)
  2385   aPlatform.AssignLiteral("Win32");
  2386 #elif defined(XP_MACOSX) && defined(__ppc__)
  2387   aPlatform.AssignLiteral("MacPPC");
  2388 #elif defined(XP_MACOSX) && defined(__i386__)
  2389   aPlatform.AssignLiteral("MacIntel");
  2390 #elif defined(XP_MACOSX) && defined(__x86_64__)
  2391   aPlatform.AssignLiteral("MacIntel");
  2392 #else
  2393   // XXX Communicator uses compiled-in build-time string defines
  2394   // to indicate the platform it was compiled *for*, not what it is
  2395   // currently running *on* which is what this does.
  2396   nsAutoCString plat;
  2397   rv = service->GetOscpu(plat);
  2398   CopyASCIItoUTF16(plat, aPlatform);
  2399 #endif
  2401   return rv;
  2404 /* static */ nsresult
  2405 Navigator::GetAppVersion(nsAString& aAppVersion, bool aUsePrefOverriddenValue)
  2407   if (aUsePrefOverriddenValue && !nsContentUtils::IsCallerChrome()) {
  2408     const nsAdoptingString& override =
  2409       mozilla::Preferences::GetString("general.appversion.override");
  2411     if (override) {
  2412       aAppVersion = override;
  2413       return NS_OK;
  2417   nsresult rv;
  2419   nsCOMPtr<nsIHttpProtocolHandler>
  2420     service(do_GetService(NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX "http", &rv));
  2421   NS_ENSURE_SUCCESS(rv, rv);
  2423   nsAutoCString str;
  2424   rv = service->GetAppVersion(str);
  2425   CopyASCIItoUTF16(str, aAppVersion);
  2426   NS_ENSURE_SUCCESS(rv, rv);
  2428   aAppVersion.AppendLiteral(" (");
  2430   rv = service->GetPlatform(str);
  2431   NS_ENSURE_SUCCESS(rv, rv);
  2433   AppendASCIItoUTF16(str, aAppVersion);
  2434   aAppVersion.Append(char16_t(')'));
  2436   return rv;
  2439 /* static */ void
  2440 Navigator::AppName(nsAString& aAppName, bool aUsePrefOverriddenValue)
  2442   if (aUsePrefOverriddenValue && !nsContentUtils::IsCallerChrome()) {
  2443     const nsAdoptingString& override =
  2444       mozilla::Preferences::GetString("general.appname.override");
  2446     if (override) {
  2447       aAppName = override;
  2448       return;
  2452   aAppName.AssignLiteral("Netscape");
  2455 } // namespace dom
  2456 } // namespace mozilla
  2458 nsresult
  2459 NS_GetNavigatorUserAgent(nsAString& aUserAgent)
  2461   nsresult rv;
  2463   nsCOMPtr<nsIHttpProtocolHandler>
  2464     service(do_GetService(NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX "http", &rv));
  2465   NS_ENSURE_SUCCESS(rv, rv);
  2467   nsAutoCString ua;
  2468   rv = service->GetUserAgent(ua);
  2469   CopyASCIItoUTF16(ua, aUserAgent);
  2471   return rv;

mercurial