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