dom/base/Navigator.cpp

Sat, 03 Jan 2015 20:18:00 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Sat, 03 Jan 2015 20:18:00 +0100
branch
TOR_BUG_3246
changeset 7
129ffea94266
permissions
-rw-r--r--

Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.

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

mercurial