1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/dom/base/Navigator.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,2472 @@ 1.4 +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 1.5 +/* vim: set sw=2 ts=2 et tw=78: */ 1.6 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.7 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.8 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.9 + 1.10 +// Needs to be first. 1.11 +#include "base/basictypes.h" 1.12 + 1.13 +#include "Navigator.h" 1.14 +#include "nsIXULAppInfo.h" 1.15 +#include "nsPluginArray.h" 1.16 +#include "nsMimeTypeArray.h" 1.17 +#include "mozilla/MemoryReporting.h" 1.18 +#include "mozilla/dom/DesktopNotification.h" 1.19 +#include "nsGeolocation.h" 1.20 +#include "nsIHttpProtocolHandler.h" 1.21 +#include "nsIContentPolicy.h" 1.22 +#include "nsIContentSecurityPolicy.h" 1.23 +#include "nsContentPolicyUtils.h" 1.24 +#include "nsCrossSiteListenerProxy.h" 1.25 +#include "nsISupportsPriority.h" 1.26 +#include "nsICachingChannel.h" 1.27 +#include "nsIWebContentHandlerRegistrar.h" 1.28 +#include "nsICookiePermission.h" 1.29 +#include "nsIScriptSecurityManager.h" 1.30 +#include "nsCharSeparatedTokenizer.h" 1.31 +#include "nsContentUtils.h" 1.32 +#include "nsUnicharUtils.h" 1.33 +#include "mozilla/Preferences.h" 1.34 +#include "mozilla/Telemetry.h" 1.35 +#include "BatteryManager.h" 1.36 +#include "mozilla/dom/PowerManager.h" 1.37 +#include "mozilla/dom/WakeLock.h" 1.38 +#include "mozilla/dom/power/PowerManagerService.h" 1.39 +#include "mozilla/dom/MobileMessageManager.h" 1.40 +#include "mozilla/dom/Telephony.h" 1.41 +#include "mozilla/Hal.h" 1.42 +#include "nsISiteSpecificUserAgent.h" 1.43 +#include "mozilla/ClearOnShutdown.h" 1.44 +#include "mozilla/StaticPtr.h" 1.45 +#include "Connection.h" 1.46 +#include "mozilla/dom/Event.h" // for nsIDOMEvent::InternalDOMEvent() 1.47 +#include "nsGlobalWindow.h" 1.48 +#ifdef MOZ_B2G_RIL 1.49 +#include "mozilla/dom/IccManager.h" 1.50 +#include "mozilla/dom/CellBroadcast.h" 1.51 +#include "mozilla/dom/MobileConnectionArray.h" 1.52 +#include "mozilla/dom/Voicemail.h" 1.53 +#endif 1.54 +#include "nsIIdleObserver.h" 1.55 +#include "nsIPermissionManager.h" 1.56 +#include "nsMimeTypes.h" 1.57 +#include "nsNetUtil.h" 1.58 +#include "nsIHttpChannel.h" 1.59 +#include "nsIHttpChannelInternal.h" 1.60 +#include "TimeManager.h" 1.61 +#include "DeviceStorage.h" 1.62 +#include "nsIDOMNavigatorSystemMessages.h" 1.63 +#include "nsStreamUtils.h" 1.64 +#include "nsIAppsService.h" 1.65 +#include "mozIApplication.h" 1.66 +#include "WidgetUtils.h" 1.67 +#include "mozIThirdPartyUtil.h" 1.68 +#include "nsChannelPolicy.h" 1.69 + 1.70 +#ifdef MOZ_MEDIA_NAVIGATOR 1.71 +#include "MediaManager.h" 1.72 +#endif 1.73 +#ifdef MOZ_B2G_BT 1.74 +#include "BluetoothManager.h" 1.75 +#endif 1.76 +#include "DOMCameraManager.h" 1.77 + 1.78 +#ifdef MOZ_AUDIO_CHANNEL_MANAGER 1.79 +#include "AudioChannelManager.h" 1.80 +#endif 1.81 + 1.82 +#ifdef MOZ_B2G_FM 1.83 +#include "mozilla/dom/FMRadio.h" 1.84 +#endif 1.85 + 1.86 +#include "nsIDOMGlobalPropertyInitializer.h" 1.87 +#include "nsIDataStoreService.h" 1.88 +#include "nsJSUtils.h" 1.89 + 1.90 +#include "nsScriptNameSpaceManager.h" 1.91 + 1.92 +#include "mozilla/dom/NavigatorBinding.h" 1.93 +#include "mozilla/dom/Promise.h" 1.94 + 1.95 +#include "nsIUploadChannel2.h" 1.96 +#include "nsFormData.h" 1.97 +#include "nsIPrivateBrowsingChannel.h" 1.98 +#include "nsIDocShell.h" 1.99 + 1.100 +namespace mozilla { 1.101 +namespace dom { 1.102 + 1.103 +static bool sDoNotTrackEnabled = false; 1.104 +static bool sVibratorEnabled = false; 1.105 +static uint32_t sMaxVibrateMS = 0; 1.106 +static uint32_t sMaxVibrateListLen = 0; 1.107 + 1.108 +/* static */ 1.109 +void 1.110 +Navigator::Init() 1.111 +{ 1.112 + Preferences::AddBoolVarCache(&sDoNotTrackEnabled, 1.113 + "privacy.donottrackheader.enabled", 1.114 + false); 1.115 + Preferences::AddBoolVarCache(&sVibratorEnabled, 1.116 + "dom.vibrator.enabled", true); 1.117 + Preferences::AddUintVarCache(&sMaxVibrateMS, 1.118 + "dom.vibrator.max_vibrate_ms", 10000); 1.119 + Preferences::AddUintVarCache(&sMaxVibrateListLen, 1.120 + "dom.vibrator.max_vibrate_list_len", 128); 1.121 +} 1.122 + 1.123 +Navigator::Navigator(nsPIDOMWindow* aWindow) 1.124 + : mWindow(aWindow) 1.125 +{ 1.126 + MOZ_ASSERT(aWindow->IsInnerWindow(), "Navigator must get an inner window!"); 1.127 + SetIsDOMBinding(); 1.128 +} 1.129 + 1.130 +Navigator::~Navigator() 1.131 +{ 1.132 + Invalidate(); 1.133 +} 1.134 + 1.135 +NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(Navigator) 1.136 + NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY 1.137 + NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDOMNavigator) 1.138 + NS_INTERFACE_MAP_ENTRY(nsIDOMNavigator) 1.139 + NS_INTERFACE_MAP_ENTRY(nsIMozNavigatorNetwork) 1.140 +NS_INTERFACE_MAP_END 1.141 + 1.142 +NS_IMPL_CYCLE_COLLECTING_ADDREF(Navigator) 1.143 +NS_IMPL_CYCLE_COLLECTING_RELEASE(Navigator) 1.144 + 1.145 +NS_IMPL_CYCLE_COLLECTION_CLASS(Navigator) 1.146 + 1.147 +NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(Navigator) 1.148 + tmp->Invalidate(); 1.149 + NS_IMPL_CYCLE_COLLECTION_UNLINK(mWindow) 1.150 + NS_IMPL_CYCLE_COLLECTION_UNLINK(mCachedResolveResults) 1.151 + NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER 1.152 +NS_IMPL_CYCLE_COLLECTION_UNLINK_END 1.153 + 1.154 +NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(Navigator) 1.155 + NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPlugins) 1.156 + NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mMimeTypes) 1.157 + NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mGeolocation) 1.158 + NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mNotification) 1.159 + NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mBatteryManager) 1.160 + NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPowerManager) 1.161 + NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mMobileMessageManager) 1.162 + NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mTelephony) 1.163 + NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mConnection) 1.164 +#ifdef MOZ_B2G_RIL 1.165 + NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mMobileConnections) 1.166 + NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mCellBroadcast) 1.167 + NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mIccManager) 1.168 + NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mVoicemail) 1.169 +#endif 1.170 +#ifdef MOZ_B2G_BT 1.171 + NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mBluetooth) 1.172 +#endif 1.173 +#ifdef MOZ_AUDIO_CHANNEL_MANAGER 1.174 + NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mAudioChannelManager) 1.175 +#endif 1.176 + NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mCameraManager) 1.177 + NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mMessagesManager) 1.178 + NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDeviceStorageStores) 1.179 + NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mTimeManager) 1.180 + 1.181 + NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mWindow) 1.182 + NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mCachedResolveResults) 1.183 + NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS 1.184 +NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END 1.185 + 1.186 +NS_IMPL_CYCLE_COLLECTION_TRACE_WRAPPERCACHE(Navigator) 1.187 + 1.188 +void 1.189 +Navigator::Invalidate() 1.190 +{ 1.191 + // Don't clear mWindow here so we know we've got a non-null mWindow 1.192 + // until we're unlinked. 1.193 + 1.194 + if (mPlugins) { 1.195 + mPlugins->Invalidate(); 1.196 + mPlugins = nullptr; 1.197 + } 1.198 + 1.199 + mMimeTypes = nullptr; 1.200 + 1.201 + // If there is a page transition, make sure delete the geolocation object. 1.202 + if (mGeolocation) { 1.203 + mGeolocation->Shutdown(); 1.204 + mGeolocation = nullptr; 1.205 + } 1.206 + 1.207 + if (mNotification) { 1.208 + mNotification->Shutdown(); 1.209 + mNotification = nullptr; 1.210 + } 1.211 + 1.212 + if (mBatteryManager) { 1.213 + mBatteryManager->Shutdown(); 1.214 + mBatteryManager = nullptr; 1.215 + } 1.216 + 1.217 +#ifdef MOZ_B2G_FM 1.218 + if (mFMRadio) { 1.219 + mFMRadio->Shutdown(); 1.220 + mFMRadio = nullptr; 1.221 + } 1.222 +#endif 1.223 + 1.224 + if (mPowerManager) { 1.225 + mPowerManager->Shutdown(); 1.226 + mPowerManager = nullptr; 1.227 + } 1.228 + 1.229 + if (mMobileMessageManager) { 1.230 + mMobileMessageManager->Shutdown(); 1.231 + mMobileMessageManager = nullptr; 1.232 + } 1.233 + 1.234 + if (mTelephony) { 1.235 + mTelephony = nullptr; 1.236 + } 1.237 + 1.238 + if (mConnection) { 1.239 + mConnection->Shutdown(); 1.240 + mConnection = nullptr; 1.241 + } 1.242 + 1.243 +#ifdef MOZ_B2G_RIL 1.244 + if (mMobileConnections) { 1.245 + mMobileConnections = nullptr; 1.246 + } 1.247 + 1.248 + if (mCellBroadcast) { 1.249 + mCellBroadcast = nullptr; 1.250 + } 1.251 + 1.252 + if (mIccManager) { 1.253 + mIccManager->Shutdown(); 1.254 + mIccManager = nullptr; 1.255 + } 1.256 + 1.257 + if (mVoicemail) { 1.258 + mVoicemail = nullptr; 1.259 + } 1.260 +#endif 1.261 + 1.262 +#ifdef MOZ_B2G_BT 1.263 + if (mBluetooth) { 1.264 + mBluetooth = nullptr; 1.265 + } 1.266 +#endif 1.267 + 1.268 + mCameraManager = nullptr; 1.269 + 1.270 + if (mMessagesManager) { 1.271 + mMessagesManager = nullptr; 1.272 + } 1.273 + 1.274 +#ifdef MOZ_AUDIO_CHANNEL_MANAGER 1.275 + if (mAudioChannelManager) { 1.276 + mAudioChannelManager = nullptr; 1.277 + } 1.278 +#endif 1.279 + 1.280 + uint32_t len = mDeviceStorageStores.Length(); 1.281 + for (uint32_t i = 0; i < len; ++i) { 1.282 + mDeviceStorageStores[i]->Shutdown(); 1.283 + } 1.284 + mDeviceStorageStores.Clear(); 1.285 + 1.286 + if (mTimeManager) { 1.287 + mTimeManager = nullptr; 1.288 + } 1.289 +} 1.290 + 1.291 +//***************************************************************************** 1.292 +// Navigator::nsIDOMNavigator 1.293 +//***************************************************************************** 1.294 + 1.295 +NS_IMETHODIMP 1.296 +Navigator::GetUserAgent(nsAString& aUserAgent) 1.297 +{ 1.298 + nsresult rv = NS_GetNavigatorUserAgent(aUserAgent); 1.299 + NS_ENSURE_SUCCESS(rv, rv); 1.300 + 1.301 + if (!mWindow || !mWindow->GetDocShell()) { 1.302 + return NS_OK; 1.303 + } 1.304 + 1.305 + nsIDocument* doc = mWindow->GetExtantDoc(); 1.306 + if (!doc) { 1.307 + return NS_OK; 1.308 + } 1.309 + 1.310 + nsCOMPtr<nsIURI> codebaseURI; 1.311 + doc->NodePrincipal()->GetURI(getter_AddRefs(codebaseURI)); 1.312 + if (!codebaseURI) { 1.313 + return NS_OK; 1.314 + } 1.315 + 1.316 + nsCOMPtr<nsISiteSpecificUserAgent> siteSpecificUA = 1.317 + do_GetService("@mozilla.org/dom/site-specific-user-agent;1"); 1.318 + NS_ENSURE_TRUE(siteSpecificUA, NS_OK); 1.319 + 1.320 + return siteSpecificUA->GetUserAgentForURIAndWindow(codebaseURI, mWindow, 1.321 + aUserAgent); 1.322 +} 1.323 + 1.324 +NS_IMETHODIMP 1.325 +Navigator::GetAppCodeName(nsAString& aAppCodeName) 1.326 +{ 1.327 + nsresult rv; 1.328 + 1.329 + nsCOMPtr<nsIHttpProtocolHandler> 1.330 + service(do_GetService(NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX "http", &rv)); 1.331 + NS_ENSURE_SUCCESS(rv, rv); 1.332 + 1.333 + nsAutoCString appName; 1.334 + rv = service->GetAppName(appName); 1.335 + CopyASCIItoUTF16(appName, aAppCodeName); 1.336 + 1.337 + return rv; 1.338 +} 1.339 + 1.340 +NS_IMETHODIMP 1.341 +Navigator::GetAppVersion(nsAString& aAppVersion) 1.342 +{ 1.343 + return GetAppVersion(aAppVersion, /* aUsePrefOverriddenValue */ true); 1.344 +} 1.345 + 1.346 +NS_IMETHODIMP 1.347 +Navigator::GetAppName(nsAString& aAppName) 1.348 +{ 1.349 + AppName(aAppName, /* aUsePrefOverriddenValue */ true); 1.350 + return NS_OK; 1.351 +} 1.352 + 1.353 +/** 1.354 + * JS property navigator.language, exposed to web content. 1.355 + * Take first value from Accept-Languages (HTTP header), which is 1.356 + * the "content language" freely set by the user in the Pref window. 1.357 + * 1.358 + * Do not use UI language (chosen app locale) here. 1.359 + * See RFC 2616, Section 15.1.4 "Privacy Issues Connected to Accept Headers" 1.360 + * 1.361 + * "en", "en-US" and "i-cherokee" and "" are valid. 1.362 + * Fallback in case of invalid pref should be "" (empty string), to 1.363 + * let site do fallback, e.g. to site's local language. 1.364 + */ 1.365 +NS_IMETHODIMP 1.366 +Navigator::GetLanguage(nsAString& aLanguage) 1.367 +{ 1.368 + // E.g. "de-de, en-us,en". 1.369 + const nsAdoptingString& acceptLang = 1.370 + Preferences::GetLocalizedString("intl.accept_languages"); 1.371 + 1.372 + // Take everything before the first "," or ";", without trailing space. 1.373 + nsCharSeparatedTokenizer langTokenizer(acceptLang, ','); 1.374 + const nsSubstring &firstLangPart = langTokenizer.nextToken(); 1.375 + nsCharSeparatedTokenizer qTokenizer(firstLangPart, ';'); 1.376 + aLanguage.Assign(qTokenizer.nextToken()); 1.377 + 1.378 + // Checks and fixups: 1.379 + // replace "_" with "-" to avoid POSIX/Windows "en_US" notation. 1.380 + if (aLanguage.Length() > 2 && aLanguage[2] == char16_t('_')) { 1.381 + aLanguage.Replace(2, 1, char16_t('-')); // TODO replace all 1.382 + } 1.383 + 1.384 + // Use uppercase for country part, e.g. "en-US", not "en-us", see BCP47 1.385 + // only uppercase 2-letter country codes, not "zh-Hant", "de-DE-x-goethe". 1.386 + if (aLanguage.Length() <= 2) { 1.387 + return NS_OK; 1.388 + } 1.389 + 1.390 + nsCharSeparatedTokenizer localeTokenizer(aLanguage, '-'); 1.391 + int32_t pos = 0; 1.392 + bool first = true; 1.393 + while (localeTokenizer.hasMoreTokens()) { 1.394 + const nsSubstring& code = localeTokenizer.nextToken(); 1.395 + 1.396 + if (code.Length() == 2 && !first) { 1.397 + nsAutoString upper(code); 1.398 + ToUpperCase(upper); 1.399 + aLanguage.Replace(pos, code.Length(), upper); 1.400 + } 1.401 + 1.402 + pos += code.Length() + 1; // 1 is the separator 1.403 + first = false; 1.404 + } 1.405 + 1.406 + return NS_OK; 1.407 +} 1.408 + 1.409 +NS_IMETHODIMP 1.410 +Navigator::GetPlatform(nsAString& aPlatform) 1.411 +{ 1.412 + return GetPlatform(aPlatform, /* aUsePrefOverriddenValue */ true); 1.413 +} 1.414 + 1.415 +NS_IMETHODIMP 1.416 +Navigator::GetOscpu(nsAString& aOSCPU) 1.417 +{ 1.418 + if (!nsContentUtils::IsCallerChrome()) { 1.419 + const nsAdoptingString& override = 1.420 + Preferences::GetString("general.oscpu.override"); 1.421 + 1.422 + if (override) { 1.423 + aOSCPU = override; 1.424 + return NS_OK; 1.425 + } 1.426 + } 1.427 + 1.428 + nsresult rv; 1.429 + 1.430 + nsCOMPtr<nsIHttpProtocolHandler> 1.431 + service(do_GetService(NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX "http", &rv)); 1.432 + NS_ENSURE_SUCCESS(rv, rv); 1.433 + 1.434 + nsAutoCString oscpu; 1.435 + rv = service->GetOscpu(oscpu); 1.436 + CopyASCIItoUTF16(oscpu, aOSCPU); 1.437 + 1.438 + return rv; 1.439 +} 1.440 + 1.441 +NS_IMETHODIMP 1.442 +Navigator::GetVendor(nsAString& aVendor) 1.443 +{ 1.444 + aVendor.Truncate(); 1.445 + return NS_OK; 1.446 +} 1.447 + 1.448 +NS_IMETHODIMP 1.449 +Navigator::GetVendorSub(nsAString& aVendorSub) 1.450 +{ 1.451 + aVendorSub.Truncate(); 1.452 + return NS_OK; 1.453 +} 1.454 + 1.455 +NS_IMETHODIMP 1.456 +Navigator::GetProduct(nsAString& aProduct) 1.457 +{ 1.458 + aProduct.AssignLiteral("Gecko"); 1.459 + return NS_OK; 1.460 +} 1.461 + 1.462 +NS_IMETHODIMP 1.463 +Navigator::GetProductSub(nsAString& aProductSub) 1.464 +{ 1.465 + // Legacy build ID hardcoded for backward compatibility (bug 776376) 1.466 + aProductSub.AssignLiteral("20100101"); 1.467 + return NS_OK; 1.468 +} 1.469 + 1.470 +nsMimeTypeArray* 1.471 +Navigator::GetMimeTypes(ErrorResult& aRv) 1.472 +{ 1.473 + if (!mMimeTypes) { 1.474 + if (!mWindow) { 1.475 + aRv.Throw(NS_ERROR_UNEXPECTED); 1.476 + return nullptr; 1.477 + } 1.478 + mMimeTypes = new nsMimeTypeArray(mWindow); 1.479 + } 1.480 + 1.481 + return mMimeTypes; 1.482 +} 1.483 + 1.484 +nsPluginArray* 1.485 +Navigator::GetPlugins(ErrorResult& aRv) 1.486 +{ 1.487 + if (!mPlugins) { 1.488 + if (!mWindow) { 1.489 + aRv.Throw(NS_ERROR_UNEXPECTED); 1.490 + return nullptr; 1.491 + } 1.492 + mPlugins = new nsPluginArray(mWindow); 1.493 + mPlugins->Init(); 1.494 + } 1.495 + 1.496 + return mPlugins; 1.497 +} 1.498 + 1.499 +// Values for the network.cookie.cookieBehavior pref are documented in 1.500 +// nsCookieService.cpp. 1.501 +#define COOKIE_BEHAVIOR_REJECT 2 1.502 + 1.503 +bool 1.504 +Navigator::CookieEnabled() 1.505 +{ 1.506 + bool cookieEnabled = 1.507 + (Preferences::GetInt("network.cookie.cookieBehavior", 1.508 + COOKIE_BEHAVIOR_REJECT) != COOKIE_BEHAVIOR_REJECT); 1.509 + 1.510 + // Check whether an exception overrides the global cookie behavior 1.511 + // Note that the code for getting the URI here matches that in 1.512 + // nsHTMLDocument::SetCookie. 1.513 + if (!mWindow || !mWindow->GetDocShell()) { 1.514 + return cookieEnabled; 1.515 + } 1.516 + 1.517 + nsCOMPtr<nsIDocument> doc = mWindow->GetExtantDoc(); 1.518 + if (!doc) { 1.519 + return cookieEnabled; 1.520 + } 1.521 + 1.522 + nsCOMPtr<nsIURI> codebaseURI; 1.523 + doc->NodePrincipal()->GetURI(getter_AddRefs(codebaseURI)); 1.524 + 1.525 + if (!codebaseURI) { 1.526 + // Not a codebase, so technically can't set cookies, but let's 1.527 + // just return the default value. 1.528 + return cookieEnabled; 1.529 + } 1.530 + 1.531 + nsCOMPtr<nsICookiePermission> permMgr = 1.532 + do_GetService(NS_COOKIEPERMISSION_CONTRACTID); 1.533 + NS_ENSURE_TRUE(permMgr, cookieEnabled); 1.534 + 1.535 + // Pass null for the channel, just like the cookie service does. 1.536 + nsCookieAccess access; 1.537 + nsresult rv = permMgr->CanAccess(codebaseURI, nullptr, &access); 1.538 + NS_ENSURE_SUCCESS(rv, cookieEnabled); 1.539 + 1.540 + if (access != nsICookiePermission::ACCESS_DEFAULT) { 1.541 + cookieEnabled = access != nsICookiePermission::ACCESS_DENY; 1.542 + } 1.543 + 1.544 + return cookieEnabled; 1.545 +} 1.546 + 1.547 +bool 1.548 +Navigator::OnLine() 1.549 +{ 1.550 + return !NS_IsOffline(); 1.551 +} 1.552 + 1.553 +NS_IMETHODIMP 1.554 +Navigator::GetBuildID(nsAString& aBuildID) 1.555 +{ 1.556 + if (!nsContentUtils::IsCallerChrome()) { 1.557 + const nsAdoptingString& override = 1.558 + Preferences::GetString("general.buildID.override"); 1.559 + 1.560 + if (override) { 1.561 + aBuildID = override; 1.562 + return NS_OK; 1.563 + } 1.564 + } 1.565 + 1.566 + nsCOMPtr<nsIXULAppInfo> appInfo = 1.567 + do_GetService("@mozilla.org/xre/app-info;1"); 1.568 + if (!appInfo) { 1.569 + return NS_ERROR_NOT_IMPLEMENTED; 1.570 + } 1.571 + 1.572 + nsAutoCString buildID; 1.573 + nsresult rv = appInfo->GetAppBuildID(buildID); 1.574 + if (NS_FAILED(rv)) { 1.575 + return rv; 1.576 + } 1.577 + 1.578 + aBuildID.Truncate(); 1.579 + AppendASCIItoUTF16(buildID, aBuildID); 1.580 + return NS_OK; 1.581 +} 1.582 + 1.583 +NS_IMETHODIMP 1.584 +Navigator::GetDoNotTrack(nsAString &aResult) 1.585 +{ 1.586 + if (sDoNotTrackEnabled) { 1.587 + aResult.AssignLiteral("yes"); 1.588 + } else { 1.589 + aResult.AssignLiteral("unspecified"); 1.590 + } 1.591 + 1.592 + return NS_OK; 1.593 +} 1.594 + 1.595 +bool 1.596 +Navigator::JavaEnabled(ErrorResult& aRv) 1.597 +{ 1.598 + Telemetry::AutoTimer<Telemetry::CHECK_JAVA_ENABLED> telemetryTimer; 1.599 + 1.600 + // Return true if we have a handler for the java mime 1.601 + nsAdoptingString javaMIME = Preferences::GetString("plugin.java.mime"); 1.602 + NS_ENSURE_TRUE(!javaMIME.IsEmpty(), false); 1.603 + 1.604 + if (!mMimeTypes) { 1.605 + if (!mWindow) { 1.606 + aRv.Throw(NS_ERROR_UNEXPECTED); 1.607 + return false; 1.608 + } 1.609 + mMimeTypes = new nsMimeTypeArray(mWindow); 1.610 + } 1.611 + 1.612 + RefreshMIMEArray(); 1.613 + 1.614 + nsMimeType *mimeType = mMimeTypes->NamedItem(javaMIME); 1.615 + 1.616 + return mimeType && mimeType->GetEnabledPlugin(); 1.617 +} 1.618 + 1.619 +void 1.620 +Navigator::RefreshMIMEArray() 1.621 +{ 1.622 + if (mMimeTypes) { 1.623 + mMimeTypes->Refresh(); 1.624 + } 1.625 +} 1.626 + 1.627 +bool 1.628 +Navigator::HasDesktopNotificationSupport() 1.629 +{ 1.630 + return Preferences::GetBool("notification.feature.enabled", false); 1.631 +} 1.632 + 1.633 +namespace { 1.634 + 1.635 +class VibrateWindowListener : public nsIDOMEventListener 1.636 +{ 1.637 +public: 1.638 + VibrateWindowListener(nsIDOMWindow* aWindow, nsIDocument* aDocument) 1.639 + { 1.640 + mWindow = do_GetWeakReference(aWindow); 1.641 + mDocument = do_GetWeakReference(aDocument); 1.642 + 1.643 + NS_NAMED_LITERAL_STRING(visibilitychange, "visibilitychange"); 1.644 + aDocument->AddSystemEventListener(visibilitychange, 1.645 + this, /* listener */ 1.646 + true, /* use capture */ 1.647 + false /* wants untrusted */); 1.648 + } 1.649 + 1.650 + virtual ~VibrateWindowListener() 1.651 + { 1.652 + } 1.653 + 1.654 + void RemoveListener(); 1.655 + 1.656 + NS_DECL_ISUPPORTS 1.657 + NS_DECL_NSIDOMEVENTLISTENER 1.658 + 1.659 +private: 1.660 + nsWeakPtr mWindow; 1.661 + nsWeakPtr mDocument; 1.662 +}; 1.663 + 1.664 +NS_IMPL_ISUPPORTS(VibrateWindowListener, nsIDOMEventListener) 1.665 + 1.666 +StaticRefPtr<VibrateWindowListener> gVibrateWindowListener; 1.667 + 1.668 +NS_IMETHODIMP 1.669 +VibrateWindowListener::HandleEvent(nsIDOMEvent* aEvent) 1.670 +{ 1.671 + nsCOMPtr<nsIDocument> doc = 1.672 + do_QueryInterface(aEvent->InternalDOMEvent()->GetTarget()); 1.673 + 1.674 + if (!doc || doc->Hidden()) { 1.675 + // It's important that we call CancelVibrate(), not Vibrate() with an 1.676 + // empty list, because Vibrate() will fail if we're no longer focused, but 1.677 + // CancelVibrate() will succeed, so long as nobody else has started a new 1.678 + // vibration pattern. 1.679 + nsCOMPtr<nsIDOMWindow> window = do_QueryReferent(mWindow); 1.680 + hal::CancelVibrate(window); 1.681 + RemoveListener(); 1.682 + gVibrateWindowListener = nullptr; 1.683 + // Careful: The line above might have deleted |this|! 1.684 + } 1.685 + 1.686 + return NS_OK; 1.687 +} 1.688 + 1.689 +void 1.690 +VibrateWindowListener::RemoveListener() 1.691 +{ 1.692 + nsCOMPtr<EventTarget> target = do_QueryReferent(mDocument); 1.693 + if (!target) { 1.694 + return; 1.695 + } 1.696 + NS_NAMED_LITERAL_STRING(visibilitychange, "visibilitychange"); 1.697 + target->RemoveSystemEventListener(visibilitychange, this, 1.698 + true /* use capture */); 1.699 +} 1.700 + 1.701 +} // anonymous namespace 1.702 + 1.703 +void 1.704 +Navigator::AddIdleObserver(MozIdleObserver& aIdleObserver, ErrorResult& aRv) 1.705 +{ 1.706 + if (!mWindow) { 1.707 + aRv.Throw(NS_ERROR_UNEXPECTED); 1.708 + return; 1.709 + } 1.710 + CallbackObjectHolder<MozIdleObserver, nsIIdleObserver> holder(&aIdleObserver); 1.711 + nsCOMPtr<nsIIdleObserver> obs = holder.ToXPCOMCallback(); 1.712 + if (NS_FAILED(mWindow->RegisterIdleObserver(obs))) { 1.713 + NS_WARNING("Failed to add idle observer."); 1.714 + } 1.715 +} 1.716 + 1.717 +void 1.718 +Navigator::RemoveIdleObserver(MozIdleObserver& aIdleObserver, ErrorResult& aRv) 1.719 +{ 1.720 + if (!mWindow) { 1.721 + aRv.Throw(NS_ERROR_UNEXPECTED); 1.722 + return; 1.723 + } 1.724 + CallbackObjectHolder<MozIdleObserver, nsIIdleObserver> holder(&aIdleObserver); 1.725 + nsCOMPtr<nsIIdleObserver> obs = holder.ToXPCOMCallback(); 1.726 + if (NS_FAILED(mWindow->UnregisterIdleObserver(obs))) { 1.727 + NS_WARNING("Failed to remove idle observer."); 1.728 + } 1.729 +} 1.730 + 1.731 +bool 1.732 +Navigator::Vibrate(uint32_t aDuration) 1.733 +{ 1.734 + nsAutoTArray<uint32_t, 1> pattern; 1.735 + pattern.AppendElement(aDuration); 1.736 + return Vibrate(pattern); 1.737 +} 1.738 + 1.739 +bool 1.740 +Navigator::Vibrate(const nsTArray<uint32_t>& aPattern) 1.741 +{ 1.742 + if (!mWindow) { 1.743 + return false; 1.744 + } 1.745 + 1.746 + nsCOMPtr<nsIDocument> doc = mWindow->GetExtantDoc(); 1.747 + if (!doc) { 1.748 + return false; 1.749 + } 1.750 + 1.751 + if (doc->Hidden()) { 1.752 + // Hidden documents cannot start or stop a vibration. 1.753 + return false; 1.754 + } 1.755 + 1.756 + if (aPattern.Length() > sMaxVibrateListLen) { 1.757 + return false; 1.758 + } 1.759 + 1.760 + for (size_t i = 0; i < aPattern.Length(); ++i) { 1.761 + if (aPattern[i] > sMaxVibrateMS) { 1.762 + return false; 1.763 + } 1.764 + } 1.765 + 1.766 + // The spec says we check sVibratorEnabled after we've done the sanity 1.767 + // checking on the pattern. 1.768 + if (aPattern.IsEmpty() || !sVibratorEnabled) { 1.769 + return true; 1.770 + } 1.771 + 1.772 + // Add a listener to cancel the vibration if the document becomes hidden, 1.773 + // and remove the old visibility listener, if there was one. 1.774 + 1.775 + if (!gVibrateWindowListener) { 1.776 + // If gVibrateWindowListener is null, this is the first time we've vibrated, 1.777 + // and we need to register a listener to clear gVibrateWindowListener on 1.778 + // shutdown. 1.779 + ClearOnShutdown(&gVibrateWindowListener); 1.780 + } 1.781 + else { 1.782 + gVibrateWindowListener->RemoveListener(); 1.783 + } 1.784 + gVibrateWindowListener = new VibrateWindowListener(mWindow, doc); 1.785 + 1.786 + hal::Vibrate(aPattern, mWindow); 1.787 + return true; 1.788 +} 1.789 + 1.790 +//***************************************************************************** 1.791 +// Pointer Events interface 1.792 +//***************************************************************************** 1.793 + 1.794 +uint32_t 1.795 +Navigator::MaxTouchPoints() 1.796 +{ 1.797 + nsCOMPtr<nsIWidget> widget = widget::WidgetUtils::DOMWindowToWidget(mWindow); 1.798 + 1.799 + NS_ENSURE_TRUE(widget, 0); 1.800 + return widget->GetMaxTouchPoints(); 1.801 +} 1.802 + 1.803 +//***************************************************************************** 1.804 +// Navigator::nsIDOMClientInformation 1.805 +//***************************************************************************** 1.806 + 1.807 +void 1.808 +Navigator::RegisterContentHandler(const nsAString& aMIMEType, 1.809 + const nsAString& aURI, 1.810 + const nsAString& aTitle, 1.811 + ErrorResult& aRv) 1.812 +{ 1.813 + if (!mWindow || !mWindow->GetOuterWindow() || !mWindow->GetDocShell()) { 1.814 + return; 1.815 + } 1.816 + 1.817 + nsCOMPtr<nsIWebContentHandlerRegistrar> registrar = 1.818 + do_GetService(NS_WEBCONTENTHANDLERREGISTRAR_CONTRACTID); 1.819 + if (!registrar) { 1.820 + return; 1.821 + } 1.822 + 1.823 + aRv = registrar->RegisterContentHandler(aMIMEType, aURI, aTitle, 1.824 + mWindow->GetOuterWindow()); 1.825 +} 1.826 + 1.827 +void 1.828 +Navigator::RegisterProtocolHandler(const nsAString& aProtocol, 1.829 + const nsAString& aURI, 1.830 + const nsAString& aTitle, 1.831 + ErrorResult& aRv) 1.832 +{ 1.833 + if (!mWindow || !mWindow->GetOuterWindow() || !mWindow->GetDocShell()) { 1.834 + return; 1.835 + } 1.836 + 1.837 + nsCOMPtr<nsIWebContentHandlerRegistrar> registrar = 1.838 + do_GetService(NS_WEBCONTENTHANDLERREGISTRAR_CONTRACTID); 1.839 + if (!registrar) { 1.840 + return; 1.841 + } 1.842 + 1.843 + aRv = registrar->RegisterProtocolHandler(aProtocol, aURI, aTitle, 1.844 + mWindow->GetOuterWindow()); 1.845 +} 1.846 + 1.847 +bool 1.848 +Navigator::MozIsLocallyAvailable(const nsAString &aURI, 1.849 + bool aWhenOffline, 1.850 + ErrorResult& aRv) 1.851 +{ 1.852 + nsCOMPtr<nsIURI> uri; 1.853 + nsresult rv = NS_NewURI(getter_AddRefs(uri), aURI); 1.854 + if (NS_FAILED(rv)) { 1.855 + aRv.Throw(rv); 1.856 + return false; 1.857 + } 1.858 + 1.859 + // This method of checking the cache will only work for http/https urls. 1.860 + bool match; 1.861 + rv = uri->SchemeIs("http", &match); 1.862 + if (NS_FAILED(rv)) { 1.863 + aRv.Throw(rv); 1.864 + return false; 1.865 + } 1.866 + 1.867 + if (!match) { 1.868 + rv = uri->SchemeIs("https", &match); 1.869 + if (NS_FAILED(rv)) { 1.870 + aRv.Throw(rv); 1.871 + return false; 1.872 + } 1.873 + if (!match) { 1.874 + aRv.Throw(NS_ERROR_DOM_BAD_URI); 1.875 + return false; 1.876 + } 1.877 + } 1.878 + 1.879 + // Same origin check. 1.880 + JSContext *cx = nsContentUtils::GetCurrentJSContext(); 1.881 + if (!cx) { 1.882 + aRv.Throw(NS_ERROR_FAILURE); 1.883 + return false; 1.884 + } 1.885 + 1.886 + rv = nsContentUtils::GetSecurityManager()->CheckSameOrigin(cx, uri); 1.887 + if (NS_FAILED(rv)) { 1.888 + aRv.Throw(rv); 1.889 + return false; 1.890 + } 1.891 + 1.892 + // These load flags cause an error to be thrown if there is no 1.893 + // valid cache entry, and skip the load if there is. 1.894 + // If the cache is busy, assume that it is not yet available rather 1.895 + // than waiting for it to become available. 1.896 + uint32_t loadFlags = nsIChannel::INHIBIT_CACHING | 1.897 + nsICachingChannel::LOAD_NO_NETWORK_IO | 1.898 + nsICachingChannel::LOAD_ONLY_IF_MODIFIED | 1.899 + nsICachingChannel::LOAD_BYPASS_LOCAL_CACHE_IF_BUSY; 1.900 + 1.901 + if (aWhenOffline) { 1.902 + loadFlags |= nsICachingChannel::LOAD_CHECK_OFFLINE_CACHE | 1.903 + nsICachingChannel::LOAD_ONLY_FROM_CACHE | 1.904 + nsIRequest::LOAD_FROM_CACHE; 1.905 + } 1.906 + 1.907 + if (!mWindow) { 1.908 + aRv.Throw(NS_ERROR_UNEXPECTED); 1.909 + return false; 1.910 + } 1.911 + 1.912 + nsCOMPtr<nsILoadGroup> loadGroup; 1.913 + nsCOMPtr<nsIDocument> doc = mWindow->GetDoc(); 1.914 + if (doc) { 1.915 + loadGroup = doc->GetDocumentLoadGroup(); 1.916 + } 1.917 + 1.918 + nsCOMPtr<nsIChannel> channel; 1.919 + rv = NS_NewChannel(getter_AddRefs(channel), uri, 1.920 + nullptr, loadGroup, nullptr, loadFlags); 1.921 + if (NS_FAILED(rv)) { 1.922 + aRv.Throw(rv); 1.923 + return false; 1.924 + } 1.925 + 1.926 + nsCOMPtr<nsIInputStream> stream; 1.927 + rv = channel->Open(getter_AddRefs(stream)); 1.928 + if (NS_FAILED(rv)) { 1.929 + aRv.Throw(rv); 1.930 + return false; 1.931 + } 1.932 + 1.933 + stream->Close(); 1.934 + 1.935 + nsresult status; 1.936 + rv = channel->GetStatus(&status); 1.937 + if (NS_FAILED(rv)) { 1.938 + aRv.Throw(rv); 1.939 + return false; 1.940 + } 1.941 + 1.942 + if (NS_FAILED(status)) { 1.943 + return false; 1.944 + } 1.945 + 1.946 + nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(channel); 1.947 + bool isAvailable; 1.948 + rv = httpChannel->GetRequestSucceeded(&isAvailable); 1.949 + if (NS_FAILED(rv)) { 1.950 + aRv.Throw(rv); 1.951 + return false; 1.952 + } 1.953 + return isAvailable; 1.954 +} 1.955 + 1.956 +nsDOMDeviceStorage* 1.957 +Navigator::GetDeviceStorage(const nsAString& aType, ErrorResult& aRv) 1.958 +{ 1.959 + if (!mWindow || !mWindow->GetOuterWindow() || !mWindow->GetDocShell()) { 1.960 + aRv.Throw(NS_ERROR_FAILURE); 1.961 + return nullptr; 1.962 + } 1.963 + 1.964 + nsRefPtr<nsDOMDeviceStorage> storage; 1.965 + nsDOMDeviceStorage::CreateDeviceStorageFor(mWindow, aType, 1.966 + getter_AddRefs(storage)); 1.967 + 1.968 + if (!storage) { 1.969 + return nullptr; 1.970 + } 1.971 + 1.972 + mDeviceStorageStores.AppendElement(storage); 1.973 + return storage; 1.974 +} 1.975 + 1.976 +void 1.977 +Navigator::GetDeviceStorages(const nsAString& aType, 1.978 + nsTArray<nsRefPtr<nsDOMDeviceStorage> >& aStores, 1.979 + ErrorResult& aRv) 1.980 +{ 1.981 + if (!mWindow || !mWindow->GetOuterWindow() || !mWindow->GetDocShell()) { 1.982 + aRv.Throw(NS_ERROR_FAILURE); 1.983 + return; 1.984 + } 1.985 + 1.986 + nsDOMDeviceStorage::CreateDeviceStoragesFor(mWindow, aType, aStores); 1.987 + 1.988 + mDeviceStorageStores.AppendElements(aStores); 1.989 +} 1.990 + 1.991 +Geolocation* 1.992 +Navigator::GetGeolocation(ErrorResult& aRv) 1.993 +{ 1.994 + if (mGeolocation) { 1.995 + return mGeolocation; 1.996 + } 1.997 + 1.998 + if (!mWindow || !mWindow->GetOuterWindow() || !mWindow->GetDocShell()) { 1.999 + aRv.Throw(NS_ERROR_FAILURE); 1.1000 + return nullptr; 1.1001 + } 1.1002 + 1.1003 + mGeolocation = new Geolocation(); 1.1004 + if (NS_FAILED(mGeolocation->Init(mWindow->GetOuterWindow()))) { 1.1005 + mGeolocation = nullptr; 1.1006 + aRv.Throw(NS_ERROR_FAILURE); 1.1007 + return nullptr; 1.1008 + } 1.1009 + 1.1010 + return mGeolocation; 1.1011 +} 1.1012 + 1.1013 +class BeaconStreamListener MOZ_FINAL : public nsIStreamListener 1.1014 +{ 1.1015 + public: 1.1016 + BeaconStreamListener() {} 1.1017 + 1.1018 + NS_DECL_ISUPPORTS 1.1019 + NS_DECL_NSISTREAMLISTENER 1.1020 + NS_DECL_NSIREQUESTOBSERVER 1.1021 +}; 1.1022 + 1.1023 +NS_IMPL_ISUPPORTS(BeaconStreamListener, 1.1024 + nsIStreamListener, 1.1025 + nsIRequestObserver) 1.1026 + 1.1027 + 1.1028 +NS_IMETHODIMP 1.1029 +BeaconStreamListener::OnStartRequest(nsIRequest *aRequest, 1.1030 + nsISupports *aContext) 1.1031 +{ 1.1032 + aRequest->Cancel(NS_ERROR_NET_INTERRUPT); 1.1033 + return NS_BINDING_ABORTED; 1.1034 +} 1.1035 + 1.1036 +NS_IMETHODIMP 1.1037 +BeaconStreamListener::OnStopRequest(nsIRequest *aRequest, 1.1038 + nsISupports *aContext, 1.1039 + nsresult aStatus) 1.1040 +{ 1.1041 + return NS_OK; 1.1042 +} 1.1043 + 1.1044 +NS_IMETHODIMP 1.1045 +BeaconStreamListener::OnDataAvailable(nsIRequest *aRequest, 1.1046 + nsISupports *ctxt, 1.1047 + nsIInputStream *inStr, 1.1048 + uint64_t sourceOffset, 1.1049 + uint32_t count) 1.1050 +{ 1.1051 + MOZ_ASSERT(false); 1.1052 + return NS_OK; 1.1053 +} 1.1054 + 1.1055 +bool 1.1056 +Navigator::SendBeacon(const nsAString& aUrl, 1.1057 + const Nullable<ArrayBufferViewOrBlobOrStringOrFormData>& aData, 1.1058 + ErrorResult& aRv) 1.1059 +{ 1.1060 + if (!mWindow) { 1.1061 + aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR); 1.1062 + return false; 1.1063 + } 1.1064 + 1.1065 + nsCOMPtr<nsIDocument> doc = mWindow->GetDoc(); 1.1066 + if (!doc) { 1.1067 + aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR); 1.1068 + return false; 1.1069 + } 1.1070 + 1.1071 + nsIURI* documentURI = doc->GetDocumentURI(); 1.1072 + if (!documentURI) { 1.1073 + aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR); 1.1074 + return false; 1.1075 + } 1.1076 + 1.1077 + nsCOMPtr<nsIURI> uri; 1.1078 + nsresult rv = nsContentUtils::NewURIWithDocumentCharset( 1.1079 + getter_AddRefs(uri), 1.1080 + aUrl, 1.1081 + doc, 1.1082 + doc->GetDocBaseURI()); 1.1083 + if (NS_FAILED(rv)) { 1.1084 + aRv.Throw(NS_ERROR_DOM_URL_MISMATCH_ERR); 1.1085 + return false; 1.1086 + } 1.1087 + 1.1088 + // Check whether this is a sane URI to load 1.1089 + // Explicitly disallow things like chrome:, javascript:, and data: URIs 1.1090 + nsCOMPtr<nsIPrincipal> principal = doc->NodePrincipal(); 1.1091 + nsCOMPtr<nsIScriptSecurityManager> secMan = nsContentUtils::GetSecurityManager(); 1.1092 + uint32_t flags = nsIScriptSecurityManager::DISALLOW_INHERIT_PRINCIPAL 1.1093 + & nsIScriptSecurityManager::DISALLOW_SCRIPT; 1.1094 + rv = secMan->CheckLoadURIWithPrincipal(principal, 1.1095 + uri, 1.1096 + flags); 1.1097 + if (NS_FAILED(rv)) { 1.1098 + // Bad URI 1.1099 + aRv.Throw(rv); 1.1100 + return false; 1.1101 + } 1.1102 + 1.1103 + // Check whether the CSP allows us to load 1.1104 + int16_t shouldLoad = nsIContentPolicy::ACCEPT; 1.1105 + rv = NS_CheckContentLoadPolicy(nsIContentPolicy::TYPE_BEACON, 1.1106 + uri, 1.1107 + principal, 1.1108 + doc, 1.1109 + EmptyCString(), //mime guess 1.1110 + nullptr, //extra 1.1111 + &shouldLoad, 1.1112 + nsContentUtils::GetContentPolicy(), 1.1113 + nsContentUtils::GetSecurityManager()); 1.1114 + if (NS_FAILED(rv) || NS_CP_REJECTED(shouldLoad)) { 1.1115 + // Disallowed by content policy 1.1116 + aRv.Throw(NS_ERROR_CONTENT_BLOCKED); 1.1117 + return false; 1.1118 + } 1.1119 + 1.1120 + nsCOMPtr<nsIChannel> channel; 1.1121 + nsCOMPtr<nsIChannelPolicy> channelPolicy; 1.1122 + nsCOMPtr<nsIContentSecurityPolicy> csp; 1.1123 + rv = principal->GetCsp(getter_AddRefs(csp)); 1.1124 + if (NS_FAILED(rv)) { 1.1125 + aRv.Throw(NS_ERROR_FAILURE); 1.1126 + return false; 1.1127 + } 1.1128 + 1.1129 + if (csp) { 1.1130 + channelPolicy = do_CreateInstance(NSCHANNELPOLICY_CONTRACTID); 1.1131 + channelPolicy->SetContentSecurityPolicy(csp); 1.1132 + channelPolicy->SetLoadType(nsIContentPolicy::TYPE_BEACON); 1.1133 + } 1.1134 + rv = NS_NewChannel(getter_AddRefs(channel), 1.1135 + uri, 1.1136 + nullptr, 1.1137 + nullptr, 1.1138 + nullptr, 1.1139 + nsIRequest::LOAD_NORMAL, 1.1140 + channelPolicy); 1.1141 + if (NS_FAILED(rv)) { 1.1142 + aRv.Throw(rv); 1.1143 + return false; 1.1144 + } 1.1145 + 1.1146 + nsCOMPtr<nsIPrivateBrowsingChannel> pbChannel = do_QueryInterface(channel); 1.1147 + if (pbChannel) { 1.1148 + nsIDocShell* docShell = mWindow->GetDocShell(); 1.1149 + nsCOMPtr<nsILoadContext> loadContext = do_QueryInterface(docShell); 1.1150 + if (loadContext) { 1.1151 + rv = pbChannel->SetPrivate(loadContext->UsePrivateBrowsing()); 1.1152 + if (NS_FAILED(rv)) { 1.1153 + NS_WARNING("Setting the privacy status on the beacon channel failed"); 1.1154 + } 1.1155 + } 1.1156 + } 1.1157 + 1.1158 + nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(channel); 1.1159 + if (!httpChannel) { 1.1160 + // Beacon spec only supports HTTP requests at this time 1.1161 + aRv.Throw(NS_ERROR_DOM_BAD_URI); 1.1162 + return false; 1.1163 + } 1.1164 + httpChannel->SetReferrer(documentURI); 1.1165 + 1.1166 + // Anything that will need to refer to the window during the request 1.1167 + // will need to be done now. For example, detection of whether any 1.1168 + // cookies set by this request are foreign. Note that ThirdPartyUtil 1.1169 + // (nsIThirdPartyUtil.isThirdPartyChannel) does a secondary check between 1.1170 + // the channel URI and the cookie URI even when forceAllowThirdPartyCookie 1.1171 + // is set, so this is safe with regard to redirects. 1.1172 + nsCOMPtr<nsIHttpChannelInternal> httpChannelInternal(do_QueryInterface(channel)); 1.1173 + nsCOMPtr<mozIThirdPartyUtil> thirdPartyUtil = do_GetService(THIRDPARTYUTIL_CONTRACTID); 1.1174 + if (!httpChannelInternal) { 1.1175 + aRv.Throw(NS_ERROR_DOM_BAD_URI); 1.1176 + return false; 1.1177 + } 1.1178 + bool isForeign = true; 1.1179 + thirdPartyUtil->IsThirdPartyWindow(mWindow, uri, &isForeign); 1.1180 + httpChannelInternal->SetForceAllowThirdPartyCookie(!isForeign); 1.1181 + 1.1182 + nsCString mimeType; 1.1183 + if (!aData.IsNull()) { 1.1184 + nsCOMPtr<nsIInputStream> in; 1.1185 + 1.1186 + if (aData.Value().IsString()) { 1.1187 + nsCString stringData = NS_ConvertUTF16toUTF8(aData.Value().GetAsString()); 1.1188 + nsCOMPtr<nsIStringInputStream> strStream = do_CreateInstance(NS_STRINGINPUTSTREAM_CONTRACTID, &rv); 1.1189 + if (NS_FAILED(rv)) { 1.1190 + aRv.Throw(NS_ERROR_FAILURE); 1.1191 + return false; 1.1192 + } 1.1193 + rv = strStream->SetData(stringData.BeginReading(), stringData.Length()); 1.1194 + if (NS_FAILED(rv)) { 1.1195 + aRv.Throw(NS_ERROR_FAILURE); 1.1196 + return false; 1.1197 + } 1.1198 + mimeType.AssignLiteral("text/plain;charset=UTF-8"); 1.1199 + in = strStream; 1.1200 + 1.1201 + } else if (aData.Value().IsArrayBufferView()) { 1.1202 + 1.1203 + nsCOMPtr<nsIStringInputStream> strStream = do_CreateInstance(NS_STRINGINPUTSTREAM_CONTRACTID, &rv); 1.1204 + if (NS_FAILED(rv)) { 1.1205 + aRv.Throw(NS_ERROR_FAILURE); 1.1206 + return false; 1.1207 + } 1.1208 + 1.1209 + ArrayBufferView& view = aData.Value().GetAsArrayBufferView(); 1.1210 + view.ComputeLengthAndData(); 1.1211 + rv = strStream->SetData(reinterpret_cast<char*>(view.Data()), 1.1212 + view.Length()); 1.1213 + 1.1214 + if (NS_FAILED(rv)) { 1.1215 + aRv.Throw(NS_ERROR_FAILURE); 1.1216 + return false; 1.1217 + } 1.1218 + mimeType.AssignLiteral("application/octet-stream"); 1.1219 + in = strStream; 1.1220 + 1.1221 + } else if (aData.Value().IsBlob()) { 1.1222 + nsCOMPtr<nsIDOMBlob> blob = aData.Value().GetAsBlob(); 1.1223 + rv = blob->GetInternalStream(getter_AddRefs(in)); 1.1224 + if (NS_FAILED(rv)) { 1.1225 + aRv.Throw(NS_ERROR_FAILURE); 1.1226 + return false; 1.1227 + } 1.1228 + nsAutoString type; 1.1229 + rv = blob->GetType(type); 1.1230 + if (NS_FAILED(rv)) { 1.1231 + aRv.Throw(NS_ERROR_FAILURE); 1.1232 + return false; 1.1233 + } 1.1234 + mimeType = NS_ConvertUTF16toUTF8(type); 1.1235 + 1.1236 + } else if (aData.Value().IsFormData()) { 1.1237 + nsFormData& form = aData.Value().GetAsFormData(); 1.1238 + uint64_t len; 1.1239 + nsAutoCString charset; 1.1240 + form.GetSendInfo(getter_AddRefs(in), 1.1241 + &len, 1.1242 + mimeType, 1.1243 + charset); 1.1244 + } else { 1.1245 + MOZ_ASSERT(false, "switch statements not in sync"); 1.1246 + aRv.Throw(NS_ERROR_FAILURE); 1.1247 + return false; 1.1248 + } 1.1249 + 1.1250 + nsCOMPtr<nsIUploadChannel2> uploadChannel = do_QueryInterface(channel); 1.1251 + if (!uploadChannel) { 1.1252 + aRv.Throw(NS_ERROR_FAILURE); 1.1253 + return false; 1.1254 + } 1.1255 + uploadChannel->ExplicitSetUploadStream(in, mimeType, -1, 1.1256 + NS_LITERAL_CSTRING("POST"), 1.1257 + false); 1.1258 + } else { 1.1259 + httpChannel->SetRequestMethod(NS_LITERAL_CSTRING("POST")); 1.1260 + } 1.1261 + 1.1262 + nsCOMPtr<nsISupportsPriority> p = do_QueryInterface(channel); 1.1263 + if (p) { 1.1264 + p->SetPriority(nsISupportsPriority::PRIORITY_LOWEST); 1.1265 + } 1.1266 + 1.1267 + nsRefPtr<nsCORSListenerProxy> cors = new nsCORSListenerProxy(new BeaconStreamListener(), 1.1268 + principal, 1.1269 + true); 1.1270 + 1.1271 + // Start a preflight if cross-origin and content type is not whitelisted 1.1272 + rv = secMan->CheckSameOriginURI(documentURI, uri, false); 1.1273 + bool crossOrigin = NS_FAILED(rv); 1.1274 + nsAutoCString contentType, parsedCharset; 1.1275 + rv = NS_ParseContentType(mimeType, contentType, parsedCharset); 1.1276 + if (crossOrigin && 1.1277 + contentType.Length() > 0 && 1.1278 + !contentType.Equals(APPLICATION_WWW_FORM_URLENCODED) && 1.1279 + !contentType.Equals(MULTIPART_FORM_DATA) && 1.1280 + !contentType.Equals(TEXT_PLAIN)) { 1.1281 + nsCOMPtr<nsIChannel> preflightChannel; 1.1282 + nsTArray<nsCString> unsafeHeaders; 1.1283 + unsafeHeaders.AppendElement(NS_LITERAL_CSTRING("Content-Type")); 1.1284 + rv = NS_StartCORSPreflight(channel, 1.1285 + cors, 1.1286 + principal, 1.1287 + true, 1.1288 + unsafeHeaders, 1.1289 + getter_AddRefs(preflightChannel)); 1.1290 + } else { 1.1291 + rv = channel->AsyncOpen(cors, nullptr); 1.1292 + } 1.1293 + if (NS_FAILED(rv)) { 1.1294 + aRv.Throw(rv); 1.1295 + return false; 1.1296 + } 1.1297 + return true; 1.1298 +} 1.1299 + 1.1300 +#ifdef MOZ_MEDIA_NAVIGATOR 1.1301 +void 1.1302 +Navigator::MozGetUserMedia(const MediaStreamConstraints& aConstraints, 1.1303 + NavigatorUserMediaSuccessCallback& aOnSuccess, 1.1304 + NavigatorUserMediaErrorCallback& aOnError, 1.1305 + ErrorResult& aRv) 1.1306 +{ 1.1307 + CallbackObjectHolder<NavigatorUserMediaSuccessCallback, 1.1308 + nsIDOMGetUserMediaSuccessCallback> holder1(&aOnSuccess); 1.1309 + nsCOMPtr<nsIDOMGetUserMediaSuccessCallback> onsuccess = 1.1310 + holder1.ToXPCOMCallback(); 1.1311 + 1.1312 + CallbackObjectHolder<NavigatorUserMediaErrorCallback, 1.1313 + nsIDOMGetUserMediaErrorCallback> holder2(&aOnError); 1.1314 + nsCOMPtr<nsIDOMGetUserMediaErrorCallback> onerror = holder2.ToXPCOMCallback(); 1.1315 + 1.1316 + if (!mWindow || !mWindow->GetOuterWindow() || 1.1317 + mWindow->GetOuterWindow()->GetCurrentInnerWindow() != mWindow) { 1.1318 + aRv.Throw(NS_ERROR_NOT_AVAILABLE); 1.1319 + return; 1.1320 + } 1.1321 + 1.1322 + bool privileged = nsContentUtils::IsChromeDoc(mWindow->GetExtantDoc()); 1.1323 + 1.1324 + MediaManager* manager = MediaManager::Get(); 1.1325 + aRv = manager->GetUserMedia(privileged, mWindow, aConstraints, 1.1326 + onsuccess, onerror); 1.1327 +} 1.1328 + 1.1329 +void 1.1330 +Navigator::MozGetUserMediaDevices(const MediaStreamConstraints& aConstraints, 1.1331 + MozGetUserMediaDevicesSuccessCallback& aOnSuccess, 1.1332 + NavigatorUserMediaErrorCallback& aOnError, 1.1333 + uint64_t aInnerWindowID, 1.1334 + ErrorResult& aRv) 1.1335 +{ 1.1336 + CallbackObjectHolder<MozGetUserMediaDevicesSuccessCallback, 1.1337 + nsIGetUserMediaDevicesSuccessCallback> holder1(&aOnSuccess); 1.1338 + nsCOMPtr<nsIGetUserMediaDevicesSuccessCallback> onsuccess = 1.1339 + holder1.ToXPCOMCallback(); 1.1340 + 1.1341 + CallbackObjectHolder<NavigatorUserMediaErrorCallback, 1.1342 + nsIDOMGetUserMediaErrorCallback> holder2(&aOnError); 1.1343 + nsCOMPtr<nsIDOMGetUserMediaErrorCallback> onerror = holder2.ToXPCOMCallback(); 1.1344 + 1.1345 + if (!mWindow || !mWindow->GetOuterWindow() || 1.1346 + mWindow->GetOuterWindow()->GetCurrentInnerWindow() != mWindow) { 1.1347 + aRv.Throw(NS_ERROR_NOT_AVAILABLE); 1.1348 + return; 1.1349 + } 1.1350 + 1.1351 + MediaManager* manager = MediaManager::Get(); 1.1352 + aRv = manager->GetUserMediaDevices(mWindow, aConstraints, onsuccess, onerror, 1.1353 + aInnerWindowID); 1.1354 +} 1.1355 +#endif 1.1356 + 1.1357 +DesktopNotificationCenter* 1.1358 +Navigator::GetMozNotification(ErrorResult& aRv) 1.1359 +{ 1.1360 + if (mNotification) { 1.1361 + return mNotification; 1.1362 + } 1.1363 + 1.1364 + if (!mWindow || !mWindow->GetDocShell()) { 1.1365 + aRv.Throw(NS_ERROR_FAILURE); 1.1366 + return nullptr; 1.1367 + } 1.1368 + 1.1369 + mNotification = new DesktopNotificationCenter(mWindow); 1.1370 + return mNotification; 1.1371 +} 1.1372 + 1.1373 +#ifdef MOZ_B2G_FM 1.1374 + 1.1375 +using mozilla::dom::FMRadio; 1.1376 + 1.1377 +FMRadio* 1.1378 +Navigator::GetMozFMRadio(ErrorResult& aRv) 1.1379 +{ 1.1380 + if (!mFMRadio) { 1.1381 + if (!mWindow) { 1.1382 + aRv.Throw(NS_ERROR_UNEXPECTED); 1.1383 + return nullptr; 1.1384 + } 1.1385 + 1.1386 + NS_ENSURE_TRUE(mWindow->GetDocShell(), nullptr); 1.1387 + 1.1388 + mFMRadio = new FMRadio(); 1.1389 + mFMRadio->Init(mWindow); 1.1390 + } 1.1391 + 1.1392 + return mFMRadio; 1.1393 +} 1.1394 + 1.1395 +#endif // MOZ_B2G_FM 1.1396 + 1.1397 +//***************************************************************************** 1.1398 +// Navigator::nsINavigatorBattery 1.1399 +//***************************************************************************** 1.1400 + 1.1401 +battery::BatteryManager* 1.1402 +Navigator::GetBattery(ErrorResult& aRv) 1.1403 +{ 1.1404 + if (!mBatteryManager) { 1.1405 + if (!mWindow) { 1.1406 + aRv.Throw(NS_ERROR_UNEXPECTED); 1.1407 + return nullptr; 1.1408 + } 1.1409 + NS_ENSURE_TRUE(mWindow->GetDocShell(), nullptr); 1.1410 + 1.1411 + mBatteryManager = new battery::BatteryManager(mWindow); 1.1412 + mBatteryManager->Init(); 1.1413 + } 1.1414 + 1.1415 + return mBatteryManager; 1.1416 +} 1.1417 + 1.1418 +already_AddRefed<Promise> 1.1419 +Navigator::GetDataStores(const nsAString& aName, ErrorResult& aRv) 1.1420 +{ 1.1421 + if (!mWindow || !mWindow->GetDocShell()) { 1.1422 + aRv.Throw(NS_ERROR_UNEXPECTED); 1.1423 + return nullptr; 1.1424 + } 1.1425 + 1.1426 + nsCOMPtr<nsIDataStoreService> service = 1.1427 + do_GetService("@mozilla.org/datastore-service;1"); 1.1428 + if (!service) { 1.1429 + aRv.Throw(NS_ERROR_FAILURE); 1.1430 + return nullptr; 1.1431 + } 1.1432 + 1.1433 + nsCOMPtr<nsISupports> promise; 1.1434 + aRv = service->GetDataStores(mWindow, aName, getter_AddRefs(promise)); 1.1435 + 1.1436 + nsRefPtr<Promise> p = static_cast<Promise*>(promise.get()); 1.1437 + return p.forget(); 1.1438 +} 1.1439 + 1.1440 +PowerManager* 1.1441 +Navigator::GetMozPower(ErrorResult& aRv) 1.1442 +{ 1.1443 + if (!mPowerManager) { 1.1444 + if (!mWindow) { 1.1445 + aRv.Throw(NS_ERROR_UNEXPECTED); 1.1446 + return nullptr; 1.1447 + } 1.1448 + mPowerManager = PowerManager::CreateInstance(mWindow); 1.1449 + if (!mPowerManager) { 1.1450 + // We failed to get the power manager service? 1.1451 + aRv.Throw(NS_ERROR_UNEXPECTED); 1.1452 + } 1.1453 + } 1.1454 + 1.1455 + return mPowerManager; 1.1456 +} 1.1457 + 1.1458 +already_AddRefed<WakeLock> 1.1459 +Navigator::RequestWakeLock(const nsAString &aTopic, ErrorResult& aRv) 1.1460 +{ 1.1461 + if (!mWindow) { 1.1462 + aRv.Throw(NS_ERROR_UNEXPECTED); 1.1463 + return nullptr; 1.1464 + } 1.1465 + 1.1466 + nsRefPtr<power::PowerManagerService> pmService = 1.1467 + power::PowerManagerService::GetInstance(); 1.1468 + // Maybe it went away for some reason... Or maybe we're just called 1.1469 + // from our XPCOM method. 1.1470 + if (!pmService) { 1.1471 + aRv.Throw(NS_ERROR_UNEXPECTED); 1.1472 + return nullptr; 1.1473 + } 1.1474 + 1.1475 + return pmService->NewWakeLock(aTopic, mWindow, aRv); 1.1476 +} 1.1477 + 1.1478 +nsIDOMMozMobileMessageManager* 1.1479 +Navigator::GetMozMobileMessage() 1.1480 +{ 1.1481 + if (!mMobileMessageManager) { 1.1482 + // Check that our window has not gone away 1.1483 + NS_ENSURE_TRUE(mWindow, nullptr); 1.1484 + NS_ENSURE_TRUE(mWindow->GetDocShell(), nullptr); 1.1485 + 1.1486 + mMobileMessageManager = new MobileMessageManager(); 1.1487 + mMobileMessageManager->Init(mWindow); 1.1488 + } 1.1489 + 1.1490 + return mMobileMessageManager; 1.1491 +} 1.1492 + 1.1493 +Telephony* 1.1494 +Navigator::GetMozTelephony(ErrorResult& aRv) 1.1495 +{ 1.1496 + if (!mTelephony) { 1.1497 + if (!mWindow) { 1.1498 + aRv.Throw(NS_ERROR_UNEXPECTED); 1.1499 + return nullptr; 1.1500 + } 1.1501 + mTelephony = Telephony::Create(mWindow, aRv); 1.1502 + } 1.1503 + 1.1504 + return mTelephony; 1.1505 +} 1.1506 + 1.1507 +#ifdef MOZ_B2G_RIL 1.1508 + 1.1509 +MobileConnectionArray* 1.1510 +Navigator::GetMozMobileConnections(ErrorResult& aRv) 1.1511 +{ 1.1512 + if (!mMobileConnections) { 1.1513 + if (!mWindow) { 1.1514 + aRv.Throw(NS_ERROR_UNEXPECTED); 1.1515 + return nullptr; 1.1516 + } 1.1517 + mMobileConnections = new MobileConnectionArray(mWindow); 1.1518 + } 1.1519 + 1.1520 + return mMobileConnections; 1.1521 +} 1.1522 + 1.1523 +CellBroadcast* 1.1524 +Navigator::GetMozCellBroadcast(ErrorResult& aRv) 1.1525 +{ 1.1526 + if (!mCellBroadcast) { 1.1527 + if (!mWindow) { 1.1528 + aRv.Throw(NS_ERROR_UNEXPECTED); 1.1529 + return nullptr; 1.1530 + } 1.1531 + mCellBroadcast = CellBroadcast::Create(mWindow, aRv); 1.1532 + } 1.1533 + 1.1534 + return mCellBroadcast; 1.1535 +} 1.1536 + 1.1537 +Voicemail* 1.1538 +Navigator::GetMozVoicemail(ErrorResult& aRv) 1.1539 +{ 1.1540 + if (!mVoicemail) { 1.1541 + if (!mWindow) { 1.1542 + aRv.Throw(NS_ERROR_UNEXPECTED); 1.1543 + return nullptr; 1.1544 + } 1.1545 + 1.1546 + aRv = NS_NewVoicemail(mWindow, getter_AddRefs(mVoicemail)); 1.1547 + if (aRv.Failed()) { 1.1548 + return nullptr; 1.1549 + } 1.1550 + } 1.1551 + 1.1552 + return mVoicemail; 1.1553 +} 1.1554 + 1.1555 +IccManager* 1.1556 +Navigator::GetMozIccManager(ErrorResult& aRv) 1.1557 +{ 1.1558 + if (!mIccManager) { 1.1559 + if (!mWindow) { 1.1560 + aRv.Throw(NS_ERROR_UNEXPECTED); 1.1561 + return nullptr; 1.1562 + } 1.1563 + NS_ENSURE_TRUE(mWindow->GetDocShell(), nullptr); 1.1564 + 1.1565 + mIccManager = new IccManager(mWindow); 1.1566 + } 1.1567 + 1.1568 + return mIccManager; 1.1569 +} 1.1570 + 1.1571 +#endif // MOZ_B2G_RIL 1.1572 + 1.1573 +#ifdef MOZ_GAMEPAD 1.1574 +void 1.1575 +Navigator::GetGamepads(nsTArray<nsRefPtr<Gamepad> >& aGamepads, 1.1576 + ErrorResult& aRv) 1.1577 +{ 1.1578 + if (!mWindow) { 1.1579 + aRv.Throw(NS_ERROR_UNEXPECTED); 1.1580 + return; 1.1581 + } 1.1582 + NS_ENSURE_TRUE_VOID(mWindow->GetDocShell()); 1.1583 + nsGlobalWindow* win = static_cast<nsGlobalWindow*>(mWindow.get()); 1.1584 + win->SetHasGamepadEventListener(true); 1.1585 + win->GetGamepads(aGamepads); 1.1586 +} 1.1587 +#endif 1.1588 + 1.1589 +//***************************************************************************** 1.1590 +// Navigator::nsIMozNavigatorNetwork 1.1591 +//***************************************************************************** 1.1592 + 1.1593 +NS_IMETHODIMP 1.1594 +Navigator::GetProperties(nsINetworkProperties** aProperties) 1.1595 +{ 1.1596 + ErrorResult rv; 1.1597 + NS_IF_ADDREF(*aProperties = GetConnection(rv)); 1.1598 + return NS_OK; 1.1599 +} 1.1600 + 1.1601 +network::Connection* 1.1602 +Navigator::GetConnection(ErrorResult& aRv) 1.1603 +{ 1.1604 + if (!mConnection) { 1.1605 + if (!mWindow) { 1.1606 + aRv.Throw(NS_ERROR_UNEXPECTED); 1.1607 + return nullptr; 1.1608 + } 1.1609 + mConnection = new network::Connection(); 1.1610 + mConnection->Init(mWindow); 1.1611 + } 1.1612 + 1.1613 + return mConnection; 1.1614 +} 1.1615 + 1.1616 +#ifdef MOZ_B2G_BT 1.1617 +bluetooth::BluetoothManager* 1.1618 +Navigator::GetMozBluetooth(ErrorResult& aRv) 1.1619 +{ 1.1620 + if (!mBluetooth) { 1.1621 + if (!mWindow) { 1.1622 + aRv.Throw(NS_ERROR_UNEXPECTED); 1.1623 + return nullptr; 1.1624 + } 1.1625 + mBluetooth = bluetooth::BluetoothManager::Create(mWindow); 1.1626 + } 1.1627 + 1.1628 + return mBluetooth; 1.1629 +} 1.1630 +#endif //MOZ_B2G_BT 1.1631 + 1.1632 +nsresult 1.1633 +Navigator::EnsureMessagesManager() 1.1634 +{ 1.1635 + if (mMessagesManager) { 1.1636 + return NS_OK; 1.1637 + } 1.1638 + 1.1639 + NS_ENSURE_STATE(mWindow); 1.1640 + 1.1641 + nsresult rv; 1.1642 + nsCOMPtr<nsIDOMNavigatorSystemMessages> messageManager = 1.1643 + do_CreateInstance("@mozilla.org/system-message-manager;1", &rv); 1.1644 + 1.1645 + nsCOMPtr<nsIDOMGlobalPropertyInitializer> gpi = 1.1646 + do_QueryInterface(messageManager); 1.1647 + NS_ENSURE_TRUE(gpi, NS_ERROR_FAILURE); 1.1648 + 1.1649 + // We don't do anything with the return value. 1.1650 + AutoJSContext cx; 1.1651 + JS::Rooted<JS::Value> prop_val(cx); 1.1652 + rv = gpi->Init(mWindow, &prop_val); 1.1653 + NS_ENSURE_SUCCESS(rv, rv); 1.1654 + 1.1655 + mMessagesManager = messageManager.forget(); 1.1656 + 1.1657 + return NS_OK; 1.1658 +} 1.1659 + 1.1660 +bool 1.1661 +Navigator::MozHasPendingMessage(const nsAString& aType, ErrorResult& aRv) 1.1662 +{ 1.1663 + // The WebIDL binding is responsible for the pref check here. 1.1664 + nsresult rv = EnsureMessagesManager(); 1.1665 + if (NS_FAILED(rv)) { 1.1666 + aRv.Throw(rv); 1.1667 + return false; 1.1668 + } 1.1669 + 1.1670 + bool result = false; 1.1671 + rv = mMessagesManager->MozHasPendingMessage(aType, &result); 1.1672 + if (NS_FAILED(rv)) { 1.1673 + aRv.Throw(rv); 1.1674 + return false; 1.1675 + } 1.1676 + return result; 1.1677 +} 1.1678 + 1.1679 +void 1.1680 +Navigator::MozSetMessageHandler(const nsAString& aType, 1.1681 + systemMessageCallback* aCallback, 1.1682 + ErrorResult& aRv) 1.1683 +{ 1.1684 + // The WebIDL binding is responsible for the pref check here. 1.1685 + nsresult rv = EnsureMessagesManager(); 1.1686 + if (NS_FAILED(rv)) { 1.1687 + aRv.Throw(rv); 1.1688 + return; 1.1689 + } 1.1690 + 1.1691 + CallbackObjectHolder<systemMessageCallback, nsIDOMSystemMessageCallback> 1.1692 + holder(aCallback); 1.1693 + nsCOMPtr<nsIDOMSystemMessageCallback> callback = holder.ToXPCOMCallback(); 1.1694 + 1.1695 + rv = mMessagesManager->MozSetMessageHandler(aType, callback); 1.1696 + if (NS_FAILED(rv)) { 1.1697 + aRv.Throw(rv); 1.1698 + } 1.1699 +} 1.1700 + 1.1701 +#ifdef MOZ_TIME_MANAGER 1.1702 +time::TimeManager* 1.1703 +Navigator::GetMozTime(ErrorResult& aRv) 1.1704 +{ 1.1705 + if (!mWindow) { 1.1706 + aRv.Throw(NS_ERROR_UNEXPECTED); 1.1707 + return nullptr; 1.1708 + } 1.1709 + 1.1710 + if (!mTimeManager) { 1.1711 + mTimeManager = new time::TimeManager(mWindow); 1.1712 + } 1.1713 + 1.1714 + return mTimeManager; 1.1715 +} 1.1716 +#endif 1.1717 + 1.1718 +nsDOMCameraManager* 1.1719 +Navigator::GetMozCameras(ErrorResult& aRv) 1.1720 +{ 1.1721 + if (!mCameraManager) { 1.1722 + if (!mWindow || 1.1723 + !mWindow->GetOuterWindow() || 1.1724 + mWindow->GetOuterWindow()->GetCurrentInnerWindow() != mWindow) { 1.1725 + aRv.Throw(NS_ERROR_NOT_AVAILABLE); 1.1726 + return nullptr; 1.1727 + } 1.1728 + 1.1729 + mCameraManager = nsDOMCameraManager::CreateInstance(mWindow); 1.1730 + } 1.1731 + 1.1732 + return mCameraManager; 1.1733 +} 1.1734 + 1.1735 +size_t 1.1736 +Navigator::SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const 1.1737 +{ 1.1738 + size_t n = aMallocSizeOf(this); 1.1739 + 1.1740 + // TODO: add SizeOfIncludingThis() to nsMimeTypeArray, bug 674113. 1.1741 + // TODO: add SizeOfIncludingThis() to nsPluginArray, bug 674114. 1.1742 + // TODO: add SizeOfIncludingThis() to Geolocation, bug 674115. 1.1743 + // TODO: add SizeOfIncludingThis() to DesktopNotificationCenter, bug 674116. 1.1744 + 1.1745 + return n; 1.1746 +} 1.1747 + 1.1748 +void 1.1749 +Navigator::SetWindow(nsPIDOMWindow *aInnerWindow) 1.1750 +{ 1.1751 + NS_ASSERTION(aInnerWindow->IsInnerWindow(), 1.1752 + "Navigator must get an inner window!"); 1.1753 + mWindow = aInnerWindow; 1.1754 +} 1.1755 + 1.1756 +void 1.1757 +Navigator::OnNavigation() 1.1758 +{ 1.1759 + if (!mWindow) { 1.1760 + return; 1.1761 + } 1.1762 + 1.1763 +#ifdef MOZ_MEDIA_NAVIGATOR 1.1764 + // Inform MediaManager in case there are live streams or pending callbacks. 1.1765 + MediaManager *manager = MediaManager::Get(); 1.1766 + if (manager) { 1.1767 + manager->OnNavigation(mWindow->WindowID()); 1.1768 + } 1.1769 +#endif 1.1770 + if (mCameraManager) { 1.1771 + mCameraManager->OnNavigation(mWindow->WindowID()); 1.1772 + } 1.1773 +} 1.1774 + 1.1775 +bool 1.1776 +Navigator::CheckPermission(const char* type) 1.1777 +{ 1.1778 + return CheckPermission(mWindow, type); 1.1779 +} 1.1780 + 1.1781 +/* static */ 1.1782 +bool 1.1783 +Navigator::CheckPermission(nsPIDOMWindow* aWindow, const char* aType) 1.1784 +{ 1.1785 + if (!aWindow) { 1.1786 + return false; 1.1787 + } 1.1788 + 1.1789 + nsCOMPtr<nsIPermissionManager> permMgr = 1.1790 + do_GetService(NS_PERMISSIONMANAGER_CONTRACTID); 1.1791 + NS_ENSURE_TRUE(permMgr, false); 1.1792 + 1.1793 + uint32_t permission = nsIPermissionManager::DENY_ACTION; 1.1794 + permMgr->TestPermissionFromWindow(aWindow, aType, &permission); 1.1795 + return permission == nsIPermissionManager::ALLOW_ACTION; 1.1796 +} 1.1797 + 1.1798 +#ifdef MOZ_AUDIO_CHANNEL_MANAGER 1.1799 +system::AudioChannelManager* 1.1800 +Navigator::GetMozAudioChannelManager(ErrorResult& aRv) 1.1801 +{ 1.1802 + if (!mAudioChannelManager) { 1.1803 + if (!mWindow) { 1.1804 + aRv.Throw(NS_ERROR_UNEXPECTED); 1.1805 + return nullptr; 1.1806 + } 1.1807 + mAudioChannelManager = new system::AudioChannelManager(); 1.1808 + mAudioChannelManager->Init(mWindow); 1.1809 + } 1.1810 + 1.1811 + return mAudioChannelManager; 1.1812 +} 1.1813 +#endif 1.1814 + 1.1815 +bool 1.1816 +Navigator::DoNewResolve(JSContext* aCx, JS::Handle<JSObject*> aObject, 1.1817 + JS::Handle<jsid> aId, 1.1818 + JS::MutableHandle<JSPropertyDescriptor> aDesc) 1.1819 +{ 1.1820 + if (!JSID_IS_STRING(aId)) { 1.1821 + return true; 1.1822 + } 1.1823 + 1.1824 + nsScriptNameSpaceManager* nameSpaceManager = GetNameSpaceManager(); 1.1825 + if (!nameSpaceManager) { 1.1826 + return Throw(aCx, NS_ERROR_NOT_INITIALIZED); 1.1827 + } 1.1828 + 1.1829 + nsDependentJSString name(aId); 1.1830 + 1.1831 + const nsGlobalNameStruct* name_struct = 1.1832 + nameSpaceManager->LookupNavigatorName(name); 1.1833 + if (!name_struct) { 1.1834 + return true; 1.1835 + } 1.1836 + 1.1837 + JS::Rooted<JSObject*> naviObj(aCx, 1.1838 + js::CheckedUnwrap(aObject, 1.1839 + /* stopAtOuter = */ false)); 1.1840 + if (!naviObj) { 1.1841 + return Throw(aCx, NS_ERROR_DOM_SECURITY_ERR); 1.1842 + } 1.1843 + 1.1844 + if (name_struct->mType == nsGlobalNameStruct::eTypeNewDOMBinding) { 1.1845 + ConstructNavigatorProperty construct = name_struct->mConstructNavigatorProperty; 1.1846 + MOZ_ASSERT(construct); 1.1847 + 1.1848 + JS::Rooted<JSObject*> domObject(aCx); 1.1849 + { 1.1850 + // Make sure to do the creation of our object in the compartment 1.1851 + // of naviObj, especially since we plan to cache that object. 1.1852 + JSAutoCompartment ac(aCx, naviObj); 1.1853 + 1.1854 + // Check whether our constructor is enabled after we unwrap Xrays, since 1.1855 + // we don't want to define an interface on the Xray if it's disabled in 1.1856 + // the target global, even if it's enabled in the Xray's global. 1.1857 + if (name_struct->mConstructorEnabled && 1.1858 + !(*name_struct->mConstructorEnabled)(aCx, naviObj)) { 1.1859 + return true; 1.1860 + } 1.1861 + 1.1862 + if (name.EqualsLiteral("mozSettings")) { 1.1863 + bool hasPermission = CheckPermission("settings-read") || 1.1864 + CheckPermission("settings-write"); 1.1865 + if (!hasPermission) { 1.1866 + FillPropertyDescriptor(aDesc, aObject, JS::NullValue(), false); 1.1867 + return true; 1.1868 + } 1.1869 + } 1.1870 + 1.1871 + if (name.EqualsLiteral("mozDownloadManager")) { 1.1872 + if (!CheckPermission("downloads")) { 1.1873 + FillPropertyDescriptor(aDesc, aObject, JS::NullValue(), false); 1.1874 + return true; 1.1875 + } 1.1876 + } 1.1877 + 1.1878 + nsISupports* existingObject = mCachedResolveResults.GetWeak(name); 1.1879 + if (existingObject) { 1.1880 + // We know all of our WebIDL objects here are wrappercached, so just go 1.1881 + // ahead and WrapObject() them. We can't use WrapNewBindingObject, 1.1882 + // because we don't have the concrete type. 1.1883 + JS::Rooted<JS::Value> wrapped(aCx); 1.1884 + if (!dom::WrapObject(aCx, existingObject, &wrapped)) { 1.1885 + return false; 1.1886 + } 1.1887 + domObject = &wrapped.toObject(); 1.1888 + } else { 1.1889 + domObject = construct(aCx, naviObj); 1.1890 + if (!domObject) { 1.1891 + return Throw(aCx, NS_ERROR_FAILURE); 1.1892 + } 1.1893 + 1.1894 + // Store the value in our cache 1.1895 + nsISupports* native = UnwrapDOMObjectToISupports(domObject); 1.1896 + MOZ_ASSERT(native); 1.1897 + mCachedResolveResults.Put(name, native); 1.1898 + } 1.1899 + } 1.1900 + 1.1901 + if (!JS_WrapObject(aCx, &domObject)) { 1.1902 + return false; 1.1903 + } 1.1904 + 1.1905 + FillPropertyDescriptor(aDesc, aObject, JS::ObjectValue(*domObject), false); 1.1906 + return true; 1.1907 + } 1.1908 + 1.1909 + NS_ASSERTION(name_struct->mType == nsGlobalNameStruct::eTypeNavigatorProperty, 1.1910 + "unexpected type"); 1.1911 + 1.1912 + nsresult rv = NS_OK; 1.1913 + 1.1914 + nsCOMPtr<nsISupports> native; 1.1915 + bool hadCachedNative = mCachedResolveResults.Get(name, getter_AddRefs(native)); 1.1916 + bool okToUseNative; 1.1917 + JS::Rooted<JS::Value> prop_val(aCx); 1.1918 + if (hadCachedNative) { 1.1919 + okToUseNative = true; 1.1920 + } else { 1.1921 + native = do_CreateInstance(name_struct->mCID, &rv); 1.1922 + if (NS_FAILED(rv)) { 1.1923 + return Throw(aCx, rv); 1.1924 + } 1.1925 + 1.1926 + nsCOMPtr<nsIDOMGlobalPropertyInitializer> gpi(do_QueryInterface(native)); 1.1927 + 1.1928 + if (gpi) { 1.1929 + if (!mWindow) { 1.1930 + return Throw(aCx, NS_ERROR_UNEXPECTED); 1.1931 + } 1.1932 + 1.1933 + rv = gpi->Init(mWindow, &prop_val); 1.1934 + if (NS_FAILED(rv)) { 1.1935 + return Throw(aCx, rv); 1.1936 + } 1.1937 + } 1.1938 + 1.1939 + okToUseNative = !prop_val.isObjectOrNull(); 1.1940 + } 1.1941 + 1.1942 + if (okToUseNative) { 1.1943 + // Make sure to do the creation of our object in the compartment 1.1944 + // of naviObj, especially since we plan to cache that object. 1.1945 + JSAutoCompartment ac(aCx, naviObj); 1.1946 + 1.1947 + rv = nsContentUtils::WrapNative(aCx, native, &prop_val); 1.1948 + 1.1949 + if (NS_FAILED(rv)) { 1.1950 + return Throw(aCx, rv); 1.1951 + } 1.1952 + 1.1953 + // Now that we know we managed to wrap this thing properly, go ahead and 1.1954 + // cache it as needed. 1.1955 + if (!hadCachedNative) { 1.1956 + mCachedResolveResults.Put(name, native); 1.1957 + } 1.1958 + } 1.1959 + 1.1960 + if (!JS_WrapValue(aCx, &prop_val)) { 1.1961 + return Throw(aCx, NS_ERROR_UNEXPECTED); 1.1962 + } 1.1963 + 1.1964 + FillPropertyDescriptor(aDesc, aObject, prop_val, false); 1.1965 + return true; 1.1966 +} 1.1967 + 1.1968 +struct NavigatorNameEnumeratorClosure 1.1969 +{ 1.1970 + NavigatorNameEnumeratorClosure(JSContext* aCx, JSObject* aWrapper, 1.1971 + nsTArray<nsString>& aNames) 1.1972 + : mCx(aCx), 1.1973 + mWrapper(aCx, aWrapper), 1.1974 + mNames(aNames) 1.1975 + { 1.1976 + } 1.1977 + 1.1978 + JSContext* mCx; 1.1979 + JS::Rooted<JSObject*> mWrapper; 1.1980 + nsTArray<nsString>& mNames; 1.1981 +}; 1.1982 + 1.1983 +static PLDHashOperator 1.1984 +SaveNavigatorName(const nsAString& aName, 1.1985 + const nsGlobalNameStruct& aNameStruct, 1.1986 + void* aClosure) 1.1987 +{ 1.1988 + NavigatorNameEnumeratorClosure* closure = 1.1989 + static_cast<NavigatorNameEnumeratorClosure*>(aClosure); 1.1990 + if (!aNameStruct.mConstructorEnabled || 1.1991 + aNameStruct.mConstructorEnabled(closure->mCx, closure->mWrapper)) { 1.1992 + closure->mNames.AppendElement(aName); 1.1993 + } 1.1994 + return PL_DHASH_NEXT; 1.1995 +} 1.1996 + 1.1997 +void 1.1998 +Navigator::GetOwnPropertyNames(JSContext* aCx, nsTArray<nsString>& aNames, 1.1999 + ErrorResult& aRv) 1.2000 +{ 1.2001 + nsScriptNameSpaceManager *nameSpaceManager = GetNameSpaceManager(); 1.2002 + if (!nameSpaceManager) { 1.2003 + NS_ERROR("Can't get namespace manager."); 1.2004 + aRv.Throw(NS_ERROR_UNEXPECTED); 1.2005 + return; 1.2006 + } 1.2007 + 1.2008 + NavigatorNameEnumeratorClosure closure(aCx, GetWrapper(), aNames); 1.2009 + nameSpaceManager->EnumerateNavigatorNames(SaveNavigatorName, &closure); 1.2010 +} 1.2011 + 1.2012 +JSObject* 1.2013 +Navigator::WrapObject(JSContext* cx) 1.2014 +{ 1.2015 + return NavigatorBinding::Wrap(cx, this); 1.2016 +} 1.2017 + 1.2018 +/* static */ 1.2019 +bool 1.2020 +Navigator::HasBatterySupport(JSContext* /* unused*/, JSObject* /*unused */) 1.2021 +{ 1.2022 + return battery::BatteryManager::HasSupport(); 1.2023 +} 1.2024 + 1.2025 +/* static */ 1.2026 +bool 1.2027 +Navigator::HasPowerSupport(JSContext* /* unused */, JSObject* aGlobal) 1.2028 +{ 1.2029 + nsCOMPtr<nsPIDOMWindow> win = GetWindowFromGlobal(aGlobal); 1.2030 + return win && PowerManager::CheckPermission(win); 1.2031 +} 1.2032 + 1.2033 +/* static */ 1.2034 +bool 1.2035 +Navigator::HasPhoneNumberSupport(JSContext* /* unused */, JSObject* aGlobal) 1.2036 +{ 1.2037 + nsCOMPtr<nsPIDOMWindow> win = GetWindowFromGlobal(aGlobal); 1.2038 + return CheckPermission(win, "phonenumberservice"); 1.2039 +} 1.2040 + 1.2041 +/* static */ 1.2042 +bool 1.2043 +Navigator::HasIdleSupport(JSContext* /* unused */, JSObject* aGlobal) 1.2044 +{ 1.2045 + if (!nsContentUtils::IsIdleObserverAPIEnabled()) { 1.2046 + return false; 1.2047 + } 1.2048 + 1.2049 + nsCOMPtr<nsPIDOMWindow> win = GetWindowFromGlobal(aGlobal); 1.2050 + return CheckPermission(win, "idle"); 1.2051 +} 1.2052 + 1.2053 +/* static */ 1.2054 +bool 1.2055 +Navigator::HasWakeLockSupport(JSContext* /* unused*/, JSObject* /*unused */) 1.2056 +{ 1.2057 + nsCOMPtr<nsIPowerManagerService> pmService = 1.2058 + do_GetService(POWERMANAGERSERVICE_CONTRACTID); 1.2059 + // No service means no wake lock support 1.2060 + return !!pmService; 1.2061 +} 1.2062 + 1.2063 +/* static */ 1.2064 +bool 1.2065 +Navigator::HasMobileMessageSupport(JSContext* /* unused */, JSObject* aGlobal) 1.2066 +{ 1.2067 + nsCOMPtr<nsPIDOMWindow> win = GetWindowFromGlobal(aGlobal); 1.2068 + 1.2069 +#ifndef MOZ_WEBSMS_BACKEND 1.2070 + return false; 1.2071 +#endif 1.2072 + 1.2073 + // First of all, the general pref has to be turned on. 1.2074 + bool enabled = false; 1.2075 + Preferences::GetBool("dom.sms.enabled", &enabled); 1.2076 + if (!enabled) { 1.2077 + return false; 1.2078 + } 1.2079 + 1.2080 + NS_ENSURE_TRUE(win, false); 1.2081 + NS_ENSURE_TRUE(win->GetDocShell(), false); 1.2082 + 1.2083 + if (!CheckPermission(win, "sms")) { 1.2084 + return false; 1.2085 + } 1.2086 + 1.2087 + return true; 1.2088 +} 1.2089 + 1.2090 +/* static */ 1.2091 +bool 1.2092 +Navigator::HasTelephonySupport(JSContext* cx, JSObject* aGlobal) 1.2093 +{ 1.2094 + JS::Rooted<JSObject*> global(cx, aGlobal); 1.2095 + 1.2096 + // First of all, the general pref has to be turned on. 1.2097 + bool enabled = false; 1.2098 + Preferences::GetBool("dom.telephony.enabled", &enabled); 1.2099 + if (!enabled) { 1.2100 + return false; 1.2101 + } 1.2102 + 1.2103 + nsCOMPtr<nsPIDOMWindow> win = GetWindowFromGlobal(global); 1.2104 + return win && CheckPermission(win, "telephony"); 1.2105 +} 1.2106 + 1.2107 +/* static */ 1.2108 +bool 1.2109 +Navigator::HasCameraSupport(JSContext* /* unused */, JSObject* aGlobal) 1.2110 +{ 1.2111 + nsCOMPtr<nsPIDOMWindow> win = GetWindowFromGlobal(aGlobal); 1.2112 + return win && nsDOMCameraManager::CheckPermission(win); 1.2113 +} 1.2114 + 1.2115 +#ifdef MOZ_B2G_RIL 1.2116 +/* static */ 1.2117 +bool 1.2118 +Navigator::HasMobileConnectionSupport(JSContext* /* unused */, 1.2119 + JSObject* aGlobal) 1.2120 +{ 1.2121 + // First of all, the general pref has to be turned on. 1.2122 + bool enabled = false; 1.2123 + Preferences::GetBool("dom.mobileconnection.enabled", &enabled); 1.2124 + NS_ENSURE_TRUE(enabled, false); 1.2125 + 1.2126 + nsCOMPtr<nsPIDOMWindow> win = GetWindowFromGlobal(aGlobal); 1.2127 + return win && (CheckPermission(win, "mobileconnection") || 1.2128 + CheckPermission(win, "mobilenetwork")); 1.2129 +} 1.2130 + 1.2131 +/* static */ 1.2132 +bool 1.2133 +Navigator::HasCellBroadcastSupport(JSContext* /* unused */, 1.2134 + JSObject* aGlobal) 1.2135 +{ 1.2136 + // First of all, the general pref has to be turned on. 1.2137 + bool enabled = false; 1.2138 + Preferences::GetBool("dom.cellbroadcast.enabled", &enabled); 1.2139 + NS_ENSURE_TRUE(enabled, false); 1.2140 + 1.2141 + nsCOMPtr<nsPIDOMWindow> win = GetWindowFromGlobal(aGlobal); 1.2142 + return win && CheckPermission(win, "cellbroadcast"); 1.2143 +} 1.2144 + 1.2145 +/* static */ 1.2146 +bool 1.2147 +Navigator::HasVoicemailSupport(JSContext* /* unused */, 1.2148 + JSObject* aGlobal) 1.2149 +{ 1.2150 + // First of all, the general pref has to be turned on. 1.2151 + bool enabled = false; 1.2152 + Preferences::GetBool("dom.voicemail.enabled", &enabled); 1.2153 + NS_ENSURE_TRUE(enabled, false); 1.2154 + 1.2155 + nsCOMPtr<nsPIDOMWindow> win = GetWindowFromGlobal(aGlobal); 1.2156 + return win && CheckPermission(win, "voicemail"); 1.2157 +} 1.2158 + 1.2159 +/* static */ 1.2160 +bool 1.2161 +Navigator::HasIccManagerSupport(JSContext* /* unused */, 1.2162 + JSObject* aGlobal) 1.2163 +{ 1.2164 + // First of all, the general pref has to be turned on. 1.2165 + bool enabled = false; 1.2166 + Preferences::GetBool("dom.icc.enabled", &enabled); 1.2167 + NS_ENSURE_TRUE(enabled, false); 1.2168 + 1.2169 + nsCOMPtr<nsPIDOMWindow> win = GetWindowFromGlobal(aGlobal); 1.2170 + return win && CheckPermission(win, "mobileconnection"); 1.2171 +} 1.2172 +#endif // MOZ_B2G_RIL 1.2173 + 1.2174 +/* static */ 1.2175 +bool 1.2176 +Navigator::HasWifiManagerSupport(JSContext* /* unused */, 1.2177 + JSObject* aGlobal) 1.2178 +{ 1.2179 + // On XBL scope, the global object is NOT |window|. So we have 1.2180 + // to use nsContentUtils::GetObjectPrincipal to get the principal 1.2181 + // and test directly with permission manager. 1.2182 + 1.2183 + nsIPrincipal* principal = nsContentUtils::GetObjectPrincipal(aGlobal); 1.2184 + 1.2185 + nsCOMPtr<nsIPermissionManager> permMgr = 1.2186 + do_GetService(NS_PERMISSIONMANAGER_CONTRACTID); 1.2187 + NS_ENSURE_TRUE(permMgr, false); 1.2188 + 1.2189 + uint32_t permission = nsIPermissionManager::DENY_ACTION; 1.2190 + permMgr->TestPermissionFromPrincipal(principal, "wifi-manage", &permission); 1.2191 + return nsIPermissionManager::ALLOW_ACTION == permission; 1.2192 +} 1.2193 + 1.2194 +#ifdef MOZ_B2G_BT 1.2195 +/* static */ 1.2196 +bool 1.2197 +Navigator::HasBluetoothSupport(JSContext* /* unused */, JSObject* aGlobal) 1.2198 +{ 1.2199 + nsCOMPtr<nsPIDOMWindow> win = GetWindowFromGlobal(aGlobal); 1.2200 + return win && bluetooth::BluetoothManager::CheckPermission(win); 1.2201 +} 1.2202 +#endif // MOZ_B2G_BT 1.2203 + 1.2204 +#ifdef MOZ_B2G_FM 1.2205 +/* static */ 1.2206 +bool 1.2207 +Navigator::HasFMRadioSupport(JSContext* /* unused */, JSObject* aGlobal) 1.2208 +{ 1.2209 + nsCOMPtr<nsPIDOMWindow> win = GetWindowFromGlobal(aGlobal); 1.2210 + return win && CheckPermission(win, "fmradio"); 1.2211 +} 1.2212 +#endif // MOZ_B2G_FM 1.2213 + 1.2214 +#ifdef MOZ_NFC 1.2215 +/* static */ 1.2216 +bool 1.2217 +Navigator::HasNfcSupport(JSContext* /* unused */, JSObject* aGlobal) 1.2218 +{ 1.2219 + // Do not support NFC if NFC content helper does not exist. 1.2220 + nsCOMPtr<nsISupports> contentHelper = do_GetService("@mozilla.org/nfc/content-helper;1"); 1.2221 + if (!contentHelper) { 1.2222 + return false; 1.2223 + } 1.2224 + 1.2225 + nsCOMPtr<nsPIDOMWindow> win = GetWindowFromGlobal(aGlobal); 1.2226 + return win && (CheckPermission(win, "nfc-read") || 1.2227 + CheckPermission(win, "nfc-write")); 1.2228 +} 1.2229 + 1.2230 +/* static */ 1.2231 +bool 1.2232 +Navigator::HasNfcPeerSupport(JSContext* /* unused */, JSObject* aGlobal) 1.2233 +{ 1.2234 + nsCOMPtr<nsPIDOMWindow> win = GetWindowFromGlobal(aGlobal); 1.2235 + return win && CheckPermission(win, "nfc-write"); 1.2236 +} 1.2237 + 1.2238 +/* static */ 1.2239 +bool 1.2240 +Navigator::HasNfcManagerSupport(JSContext* /* unused */, JSObject* aGlobal) 1.2241 +{ 1.2242 + nsCOMPtr<nsPIDOMWindow> win = GetWindowFromGlobal(aGlobal); 1.2243 + return win && CheckPermission(win, "nfc-manager"); 1.2244 +} 1.2245 +#endif // MOZ_NFC 1.2246 + 1.2247 +#ifdef MOZ_TIME_MANAGER 1.2248 +/* static */ 1.2249 +bool 1.2250 +Navigator::HasTimeSupport(JSContext* /* unused */, JSObject* aGlobal) 1.2251 +{ 1.2252 + nsCOMPtr<nsPIDOMWindow> win = GetWindowFromGlobal(aGlobal); 1.2253 + return win && CheckPermission(win, "time"); 1.2254 +} 1.2255 +#endif // MOZ_TIME_MANAGER 1.2256 + 1.2257 +#ifdef MOZ_MEDIA_NAVIGATOR 1.2258 +/* static */ 1.2259 +bool 1.2260 +Navigator::HasUserMediaSupport(JSContext* /* unused */, 1.2261 + JSObject* /* unused */) 1.2262 +{ 1.2263 + // Make enabling peerconnection enable getUserMedia() as well 1.2264 + return Preferences::GetBool("media.navigator.enabled", false) || 1.2265 + Preferences::GetBool("media.peerconnection.enabled", false); 1.2266 +} 1.2267 +#endif // MOZ_MEDIA_NAVIGATOR 1.2268 + 1.2269 +/* static */ 1.2270 +bool 1.2271 +Navigator::HasPushNotificationsSupport(JSContext* /* unused */, 1.2272 + JSObject* aGlobal) 1.2273 +{ 1.2274 + nsCOMPtr<nsPIDOMWindow> win = GetWindowFromGlobal(aGlobal); 1.2275 + return Preferences::GetBool("services.push.enabled", false) && 1.2276 + win && CheckPermission(win, "push"); 1.2277 +} 1.2278 + 1.2279 +/* static */ 1.2280 +bool 1.2281 +Navigator::HasInputMethodSupport(JSContext* /* unused */, 1.2282 + JSObject* aGlobal) 1.2283 +{ 1.2284 + nsCOMPtr<nsPIDOMWindow> win = GetWindowFromGlobal(aGlobal); 1.2285 + if (!win || !Preferences::GetBool("dom.mozInputMethod.enabled", false)) { 1.2286 + return false; 1.2287 + } 1.2288 + 1.2289 + if (Preferences::GetBool("dom.mozInputMethod.testing", false)) { 1.2290 + return true; 1.2291 + } 1.2292 + 1.2293 + return CheckPermission(win, "input") || 1.2294 + CheckPermission(win, "input-manage"); 1.2295 +} 1.2296 + 1.2297 +/* static */ 1.2298 +bool 1.2299 +Navigator::HasDataStoreSupport(JSContext* cx, JSObject* aGlobal) 1.2300 +{ 1.2301 + JS::Rooted<JSObject*> global(cx, aGlobal); 1.2302 + 1.2303 + // First of all, the general pref has to be turned on. 1.2304 + bool enabled = false; 1.2305 + Preferences::GetBool("dom.datastore.enabled", &enabled); 1.2306 + if (!enabled) { 1.2307 + return false; 1.2308 + } 1.2309 + 1.2310 + // Just for testing, we can enable DataStore for any kind of app. 1.2311 + if (Preferences::GetBool("dom.testing.datastore_enabled_for_hosted_apps", false)) { 1.2312 + return true; 1.2313 + } 1.2314 + 1.2315 + nsCOMPtr<nsPIDOMWindow> win = GetWindowFromGlobal(global); 1.2316 + if (!win) { 1.2317 + return false; 1.2318 + } 1.2319 + 1.2320 + nsIDocument* doc = win->GetExtantDoc(); 1.2321 + if (!doc || !doc->NodePrincipal()) { 1.2322 + return false; 1.2323 + } 1.2324 + 1.2325 + uint16_t status; 1.2326 + if (NS_FAILED(doc->NodePrincipal()->GetAppStatus(&status))) { 1.2327 + return false; 1.2328 + } 1.2329 + 1.2330 + return status == nsIPrincipal::APP_STATUS_CERTIFIED; 1.2331 +} 1.2332 + 1.2333 +/* static */ 1.2334 +bool 1.2335 +Navigator::HasDownloadsSupport(JSContext* aCx, JSObject* aGlobal) 1.2336 +{ 1.2337 + nsCOMPtr<nsPIDOMWindow> win = GetWindowFromGlobal(aGlobal); 1.2338 + 1.2339 + return win && 1.2340 + CheckPermission(win, "downloads") && 1.2341 + Preferences::GetBool("dom.mozDownloads.enabled"); 1.2342 +} 1.2343 + 1.2344 +/* static */ 1.2345 +bool 1.2346 +Navigator::HasPermissionSettingsSupport(JSContext* /* unused */, JSObject* aGlobal) 1.2347 +{ 1.2348 + nsCOMPtr<nsPIDOMWindow> win = GetWindowFromGlobal(aGlobal); 1.2349 + return CheckPermission(win, "permissions"); 1.2350 +} 1.2351 + 1.2352 +/* static */ 1.2353 +already_AddRefed<nsPIDOMWindow> 1.2354 +Navigator::GetWindowFromGlobal(JSObject* aGlobal) 1.2355 +{ 1.2356 + nsCOMPtr<nsPIDOMWindow> win = 1.2357 + do_QueryInterface(nsJSUtils::GetStaticScriptGlobal(aGlobal)); 1.2358 + MOZ_ASSERT(!win || win->IsInnerWindow()); 1.2359 + return win.forget(); 1.2360 +} 1.2361 + 1.2362 +nsresult 1.2363 +Navigator::GetPlatform(nsAString& aPlatform, bool aUsePrefOverriddenValue) 1.2364 +{ 1.2365 + MOZ_ASSERT(NS_IsMainThread()); 1.2366 + 1.2367 + if (aUsePrefOverriddenValue && !nsContentUtils::IsCallerChrome()) { 1.2368 + const nsAdoptingString& override = 1.2369 + mozilla::Preferences::GetString("general.platform.override"); 1.2370 + 1.2371 + if (override) { 1.2372 + aPlatform = override; 1.2373 + return NS_OK; 1.2374 + } 1.2375 + } 1.2376 + 1.2377 + nsresult rv; 1.2378 + 1.2379 + nsCOMPtr<nsIHttpProtocolHandler> 1.2380 + service(do_GetService(NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX "http", &rv)); 1.2381 + NS_ENSURE_SUCCESS(rv, rv); 1.2382 + 1.2383 + // Sorry for the #if platform ugliness, but Communicator is likewise 1.2384 + // hardcoded and we are seeking backward compatibility here (bug 47080). 1.2385 +#if defined(_WIN64) 1.2386 + aPlatform.AssignLiteral("Win64"); 1.2387 +#elif defined(WIN32) 1.2388 + aPlatform.AssignLiteral("Win32"); 1.2389 +#elif defined(XP_MACOSX) && defined(__ppc__) 1.2390 + aPlatform.AssignLiteral("MacPPC"); 1.2391 +#elif defined(XP_MACOSX) && defined(__i386__) 1.2392 + aPlatform.AssignLiteral("MacIntel"); 1.2393 +#elif defined(XP_MACOSX) && defined(__x86_64__) 1.2394 + aPlatform.AssignLiteral("MacIntel"); 1.2395 +#else 1.2396 + // XXX Communicator uses compiled-in build-time string defines 1.2397 + // to indicate the platform it was compiled *for*, not what it is 1.2398 + // currently running *on* which is what this does. 1.2399 + nsAutoCString plat; 1.2400 + rv = service->GetOscpu(plat); 1.2401 + CopyASCIItoUTF16(plat, aPlatform); 1.2402 +#endif 1.2403 + 1.2404 + return rv; 1.2405 +} 1.2406 + 1.2407 +/* static */ nsresult 1.2408 +Navigator::GetAppVersion(nsAString& aAppVersion, bool aUsePrefOverriddenValue) 1.2409 +{ 1.2410 + if (aUsePrefOverriddenValue && !nsContentUtils::IsCallerChrome()) { 1.2411 + const nsAdoptingString& override = 1.2412 + mozilla::Preferences::GetString("general.appversion.override"); 1.2413 + 1.2414 + if (override) { 1.2415 + aAppVersion = override; 1.2416 + return NS_OK; 1.2417 + } 1.2418 + } 1.2419 + 1.2420 + nsresult rv; 1.2421 + 1.2422 + nsCOMPtr<nsIHttpProtocolHandler> 1.2423 + service(do_GetService(NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX "http", &rv)); 1.2424 + NS_ENSURE_SUCCESS(rv, rv); 1.2425 + 1.2426 + nsAutoCString str; 1.2427 + rv = service->GetAppVersion(str); 1.2428 + CopyASCIItoUTF16(str, aAppVersion); 1.2429 + NS_ENSURE_SUCCESS(rv, rv); 1.2430 + 1.2431 + aAppVersion.AppendLiteral(" ("); 1.2432 + 1.2433 + rv = service->GetPlatform(str); 1.2434 + NS_ENSURE_SUCCESS(rv, rv); 1.2435 + 1.2436 + AppendASCIItoUTF16(str, aAppVersion); 1.2437 + aAppVersion.Append(char16_t(')')); 1.2438 + 1.2439 + return rv; 1.2440 +} 1.2441 + 1.2442 +/* static */ void 1.2443 +Navigator::AppName(nsAString& aAppName, bool aUsePrefOverriddenValue) 1.2444 +{ 1.2445 + if (aUsePrefOverriddenValue && !nsContentUtils::IsCallerChrome()) { 1.2446 + const nsAdoptingString& override = 1.2447 + mozilla::Preferences::GetString("general.appname.override"); 1.2448 + 1.2449 + if (override) { 1.2450 + aAppName = override; 1.2451 + return; 1.2452 + } 1.2453 + } 1.2454 + 1.2455 + aAppName.AssignLiteral("Netscape"); 1.2456 +} 1.2457 + 1.2458 +} // namespace dom 1.2459 +} // namespace mozilla 1.2460 + 1.2461 +nsresult 1.2462 +NS_GetNavigatorUserAgent(nsAString& aUserAgent) 1.2463 +{ 1.2464 + nsresult rv; 1.2465 + 1.2466 + nsCOMPtr<nsIHttpProtocolHandler> 1.2467 + service(do_GetService(NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX "http", &rv)); 1.2468 + NS_ENSURE_SUCCESS(rv, rv); 1.2469 + 1.2470 + nsAutoCString ua; 1.2471 + rv = service->GetUserAgent(ua); 1.2472 + CopyASCIItoUTF16(ua, aUserAgent); 1.2473 + 1.2474 + return rv; 1.2475 +}