Sat, 03 Jan 2015 20:18:00 +0100
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 | } |