Line data Source code
1 : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 : /* vim: set ts=8 sts=2 et sw=2 tw=80: */
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/BodyExtractor.h"
16 : #include "mozilla/dom/DesktopNotification.h"
17 : #include "mozilla/dom/FetchBinding.h"
18 : #include "mozilla/dom/File.h"
19 : #include "nsGeolocation.h"
20 : #include "nsIClassOfService.h"
21 : #include "nsIHttpProtocolHandler.h"
22 : #include "nsIContentPolicy.h"
23 : #include "nsIContentSecurityPolicy.h"
24 : #include "nsContentPolicyUtils.h"
25 : #include "nsISupportsPriority.h"
26 : #include "nsICachingChannel.h"
27 : #include "nsIWebContentHandlerRegistrar.h"
28 : #include "nsICookiePermission.h"
29 : #include "nsIScriptSecurityManager.h"
30 : #include "nsCharSeparatedTokenizer.h"
31 : #include "nsContentUtils.h"
32 : #include "nsUnicharUtils.h"
33 : #include "mozilla/Preferences.h"
34 : #include "mozilla/Telemetry.h"
35 : #include "BatteryManager.h"
36 : #include "mozilla/dom/CredentialsContainer.h"
37 : #include "mozilla/dom/GamepadServiceTest.h"
38 : #include "mozilla/dom/PowerManager.h"
39 : #include "mozilla/dom/WakeLock.h"
40 : #include "mozilla/dom/power/PowerManagerService.h"
41 : #include "mozilla/dom/FlyWebPublishedServer.h"
42 : #include "mozilla/dom/FlyWebService.h"
43 : #include "mozilla/dom/Permissions.h"
44 : #include "mozilla/dom/Presentation.h"
45 : #include "mozilla/dom/ServiceWorkerContainer.h"
46 : #include "mozilla/dom/StorageManager.h"
47 : #include "mozilla/dom/TCPSocket.h"
48 : #include "mozilla/dom/URLSearchParams.h"
49 : #include "mozilla/dom/VRDisplay.h"
50 : #include "mozilla/dom/VRDisplayEvent.h"
51 : #include "mozilla/dom/VRServiceTest.h"
52 : #include "mozilla/dom/workers/RuntimeService.h"
53 : #include "mozilla/Hal.h"
54 : #include "mozilla/ClearOnShutdown.h"
55 : #include "mozilla/SSE.h"
56 : #include "mozilla/StaticPtr.h"
57 : #include "Connection.h"
58 : #include "mozilla/dom/Event.h" // for nsIDOMEvent::InternalDOMEvent()
59 : #include "nsGlobalWindow.h"
60 : #include "nsIIdleObserver.h"
61 : #include "nsIPermissionManager.h"
62 : #include "nsMimeTypes.h"
63 : #include "nsNetUtil.h"
64 : #include "nsRFPService.h"
65 : #include "nsStringStream.h"
66 : #include "nsComponentManagerUtils.h"
67 : #include "nsIStringStream.h"
68 : #include "nsIHttpChannel.h"
69 : #include "nsIHttpChannelInternal.h"
70 : #include "TimeManager.h"
71 : #include "nsStreamUtils.h"
72 : #include "WidgetUtils.h"
73 : #include "nsIPresentationService.h"
74 : #include "nsIScriptError.h"
75 :
76 : #include "mozilla/dom/MediaDevices.h"
77 : #include "MediaManager.h"
78 :
79 : #include "nsIDOMGlobalPropertyInitializer.h"
80 : #include "nsJSUtils.h"
81 :
82 : #include "nsScriptNameSpaceManager.h"
83 :
84 : #include "mozilla/dom/NavigatorBinding.h"
85 : #include "mozilla/dom/Promise.h"
86 :
87 : #include "nsIUploadChannel2.h"
88 : #include "mozilla/dom/FormData.h"
89 : #include "nsIDocShell.h"
90 :
91 : #include "WorkerPrivate.h"
92 : #include "WorkerRunnable.h"
93 :
94 : #if defined(XP_LINUX)
95 : #include "mozilla/Hal.h"
96 : #endif
97 : #include "mozilla/dom/ContentChild.h"
98 :
99 : #include "mozilla/EMEUtils.h"
100 : #include "mozilla/DetailedPromise.h"
101 : #include "mozilla/Unused.h"
102 :
103 : namespace mozilla {
104 : namespace dom {
105 :
106 : static bool sVibratorEnabled = false;
107 : static uint32_t sMaxVibrateMS = 0;
108 : static uint32_t sMaxVibrateListLen = 0;
109 : static const char* kVibrationPermissionType = "vibration";
110 :
111 : static void
112 0 : AddPermission(nsIPrincipal* aPrincipal, const char* aType, uint32_t aPermission,
113 : uint32_t aExpireType, int64_t aExpireTime)
114 : {
115 0 : MOZ_ASSERT(aType);
116 0 : MOZ_ASSERT(aPrincipal);
117 :
118 0 : nsCOMPtr<nsIPermissionManager> permMgr = services::GetPermissionManager();
119 0 : if (!permMgr) {
120 0 : return;
121 : }
122 0 : permMgr->AddFromPrincipal(aPrincipal, aType, aPermission, aExpireType,
123 0 : aExpireTime);
124 : }
125 :
126 : static uint32_t
127 0 : GetPermission(nsPIDOMWindowInner* aWindow, const char* aType)
128 : {
129 0 : MOZ_ASSERT(aType);
130 :
131 0 : uint32_t permission = nsIPermissionManager::UNKNOWN_ACTION;
132 :
133 0 : nsCOMPtr<nsIPermissionManager> permMgr = services::GetPermissionManager();
134 0 : if (!permMgr) {
135 0 : return permission;
136 : }
137 0 : permMgr->TestPermissionFromWindow(aWindow, aType, &permission);
138 0 : return permission;
139 : }
140 :
141 : static uint32_t
142 0 : GetPermission(nsIPrincipal* aPrincipal, const char* aType)
143 : {
144 0 : MOZ_ASSERT(aType);
145 0 : MOZ_ASSERT(aPrincipal);
146 :
147 0 : uint32_t permission = nsIPermissionManager::UNKNOWN_ACTION;
148 :
149 0 : nsCOMPtr<nsIPermissionManager> permMgr = services::GetPermissionManager();
150 0 : if (!permMgr) {
151 0 : return permission;
152 : }
153 0 : permMgr->TestPermissionFromPrincipal(aPrincipal, aType, &permission);
154 0 : return permission;
155 : }
156 :
157 : /* static */
158 : void
159 3 : Navigator::Init()
160 : {
161 : Preferences::AddBoolVarCache(&sVibratorEnabled,
162 3 : "dom.vibrator.enabled", true);
163 : Preferences::AddUintVarCache(&sMaxVibrateMS,
164 3 : "dom.vibrator.max_vibrate_ms", 10000);
165 : Preferences::AddUintVarCache(&sMaxVibrateListLen,
166 3 : "dom.vibrator.max_vibrate_list_len", 128);
167 3 : }
168 :
169 0 : Navigator::Navigator(nsPIDOMWindowInner* aWindow)
170 0 : : mWindow(aWindow)
171 : {
172 0 : MOZ_ASSERT(aWindow->IsInnerWindow(), "Navigator must get an inner window!");
173 0 : }
174 :
175 0 : Navigator::~Navigator()
176 : {
177 0 : Invalidate();
178 0 : }
179 :
180 0 : NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(Navigator)
181 0 : NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
182 0 : NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDOMNavigator)
183 0 : NS_INTERFACE_MAP_ENTRY(nsIDOMNavigator)
184 0 : NS_INTERFACE_MAP_ENTRY(nsIMozNavigatorNetwork)
185 0 : NS_INTERFACE_MAP_END
186 :
187 0 : NS_IMPL_CYCLE_COLLECTING_ADDREF(Navigator)
188 0 : NS_IMPL_CYCLE_COLLECTING_RELEASE(Navigator)
189 :
190 : NS_IMPL_CYCLE_COLLECTION_CLASS(Navigator)
191 :
192 0 : NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(Navigator)
193 0 : tmp->Invalidate();
194 0 : NS_IMPL_CYCLE_COLLECTION_UNLINK(mWindow)
195 0 : NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
196 0 : NS_IMPL_CYCLE_COLLECTION_UNLINK_END
197 :
198 0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(Navigator)
199 0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mMimeTypes)
200 0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPlugins)
201 0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPermissions)
202 0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mGeolocation)
203 0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mNotification)
204 0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mBatteryManager)
205 0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mBatteryPromise)
206 0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPowerManager)
207 0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mConnection)
208 0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mStorageManager)
209 0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mCredentials)
210 0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mMediaDevices)
211 0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mTimeManager)
212 0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mServiceWorkerContainer)
213 :
214 0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mWindow)
215 0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mMediaKeySystemAccessManager)
216 0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPresentation)
217 0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mGamepadServiceTest)
218 0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mVRGetDisplaysPromises)
219 0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mVRServiceTest)
220 0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
221 :
222 0 : NS_IMPL_CYCLE_COLLECTION_TRACE_WRAPPERCACHE(Navigator)
223 :
224 : void
225 0 : Navigator::Invalidate()
226 : {
227 : // Don't clear mWindow here so we know we've got a non-null mWindow
228 : // until we're unlinked.
229 :
230 0 : mMimeTypes = nullptr;
231 :
232 0 : if (mPlugins) {
233 0 : mPlugins->Invalidate();
234 0 : mPlugins = nullptr;
235 : }
236 :
237 0 : mPermissions = nullptr;
238 :
239 0 : mStorageManager = nullptr;
240 :
241 : // If there is a page transition, make sure delete the geolocation object.
242 0 : if (mGeolocation) {
243 0 : mGeolocation->Shutdown();
244 0 : mGeolocation = nullptr;
245 : }
246 :
247 0 : if (mNotification) {
248 0 : mNotification->Shutdown();
249 0 : mNotification = nullptr;
250 : }
251 :
252 0 : if (mBatteryManager) {
253 0 : mBatteryManager->Shutdown();
254 0 : mBatteryManager = nullptr;
255 : }
256 :
257 0 : mBatteryPromise = nullptr;
258 :
259 0 : if (mPowerManager) {
260 0 : mPowerManager->Shutdown();
261 0 : mPowerManager = nullptr;
262 : }
263 :
264 0 : if (mConnection) {
265 0 : mConnection->Shutdown();
266 0 : mConnection = nullptr;
267 : }
268 :
269 0 : mMediaDevices = nullptr;
270 :
271 0 : if (mTimeManager) {
272 0 : mTimeManager = nullptr;
273 : }
274 :
275 0 : if (mPresentation) {
276 0 : mPresentation = nullptr;
277 : }
278 :
279 0 : mServiceWorkerContainer = nullptr;
280 :
281 0 : if (mMediaKeySystemAccessManager) {
282 0 : mMediaKeySystemAccessManager->Shutdown();
283 0 : mMediaKeySystemAccessManager = nullptr;
284 : }
285 :
286 0 : if (mGamepadServiceTest) {
287 0 : mGamepadServiceTest->Shutdown();
288 0 : mGamepadServiceTest = nullptr;
289 : }
290 :
291 0 : mVRGetDisplaysPromises.Clear();
292 :
293 0 : if (mVRServiceTest) {
294 0 : mVRServiceTest->Shutdown();
295 0 : mVRServiceTest = nullptr;
296 : }
297 0 : }
298 :
299 : //*****************************************************************************
300 : // Navigator::nsIDOMNavigator
301 : //*****************************************************************************
302 :
303 : void
304 0 : Navigator::GetUserAgent(nsAString& aUserAgent, CallerType aCallerType,
305 : ErrorResult& aRv) const
306 : {
307 0 : nsCOMPtr<nsPIDOMWindowInner> window;
308 :
309 0 : if (mWindow) {
310 0 : window = mWindow;
311 0 : nsIDocShell* docshell = window->GetDocShell();
312 0 : nsString customUserAgent;
313 0 : if (docshell) {
314 0 : docshell->GetCustomUserAgent(customUserAgent);
315 :
316 0 : if (!customUserAgent.IsEmpty()) {
317 0 : aUserAgent = customUserAgent;
318 0 : return;
319 : }
320 : }
321 : }
322 :
323 0 : nsresult rv = GetUserAgent(window,
324 : aCallerType == CallerType::System,
325 0 : aUserAgent);
326 0 : if (NS_WARN_IF(NS_FAILED(rv))) {
327 0 : aRv.Throw(rv);
328 : }
329 : }
330 :
331 : NS_IMETHODIMP
332 0 : Navigator::GetAppCodeName(nsAString& aAppCodeName)
333 : {
334 : nsresult rv;
335 :
336 : nsCOMPtr<nsIHttpProtocolHandler>
337 0 : service(do_GetService(NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX "http", &rv));
338 0 : NS_ENSURE_SUCCESS(rv, rv);
339 :
340 0 : nsAutoCString appName;
341 0 : rv = service->GetAppName(appName);
342 0 : CopyASCIItoUTF16(appName, aAppCodeName);
343 :
344 0 : return rv;
345 : }
346 :
347 : void
348 0 : Navigator::GetAppVersion(nsAString& aAppVersion, CallerType aCallerType,
349 : ErrorResult& aRv) const
350 : {
351 0 : nsresult rv = GetAppVersion(aAppVersion,
352 0 : /* aUsePrefOverriddenValue = */ aCallerType != CallerType::System);
353 0 : if (NS_WARN_IF(NS_FAILED(rv))) {
354 0 : aRv.Throw(rv);
355 : }
356 0 : }
357 :
358 : void
359 0 : Navigator::GetAppName(nsAString& aAppName, CallerType aCallerType) const
360 : {
361 0 : AppName(aAppName,
362 0 : /* aUsePrefOverriddenValue = */ aCallerType != CallerType::System);
363 0 : }
364 :
365 : /**
366 : * Returns the value of Accept-Languages (HTTP header) as a nsTArray of
367 : * languages. The value is set in the preference by the user ("Content
368 : * Languages").
369 : *
370 : * "en", "en-US" and "i-cherokee" and "" are valid languages tokens.
371 : *
372 : * An empty array will be returned if there is no valid languages.
373 : */
374 : /* static */ void
375 2 : Navigator::GetAcceptLanguages(nsTArray<nsString>& aLanguages)
376 : {
377 2 : MOZ_ASSERT(NS_IsMainThread());
378 :
379 2 : aLanguages.Clear();
380 :
381 : // E.g. "de-de, en-us,en".
382 : const nsAdoptingString& acceptLang =
383 4 : Preferences::GetLocalizedString("intl.accept_languages");
384 :
385 : // Split values on commas.
386 2 : nsCharSeparatedTokenizer langTokenizer(acceptLang, ',');
387 10 : while (langTokenizer.hasMoreTokens()) {
388 8 : nsDependentSubstring lang = langTokenizer.nextToken();
389 :
390 : // Replace "_" with "-" to avoid POSIX/Windows "en_US" notation.
391 : // NOTE: we should probably rely on the pref being set correctly.
392 4 : if (lang.Length() > 2 && lang[2] == char16_t('_')) {
393 0 : lang.Replace(2, 1, char16_t('-'));
394 : }
395 :
396 : // Use uppercase for country part, e.g. "en-US", not "en-us", see BCP47
397 : // only uppercase 2-letter country codes, not "zh-Hant", "de-DE-x-goethe".
398 : // NOTE: we should probably rely on the pref being set correctly.
399 4 : if (lang.Length() > 2) {
400 2 : nsCharSeparatedTokenizer localeTokenizer(lang, '-');
401 2 : int32_t pos = 0;
402 2 : bool first = true;
403 10 : while (localeTokenizer.hasMoreTokens()) {
404 8 : const nsAString& code = localeTokenizer.nextToken();
405 :
406 4 : if (code.Length() == 2 && !first) {
407 4 : nsAutoString upper(code);
408 2 : ToUpperCase(upper);
409 2 : lang.Replace(pos, code.Length(), upper);
410 : }
411 :
412 4 : pos += code.Length() + 1; // 1 is the separator
413 4 : first = false;
414 : }
415 : }
416 :
417 4 : aLanguages.AppendElement(lang);
418 : }
419 2 : }
420 :
421 : /**
422 : * Do not use UI language (chosen app locale) here but the first value set in
423 : * the Accept Languages header, see ::GetAcceptLanguages().
424 : *
425 : * See RFC 2616, Section 15.1.4 "Privacy Issues Connected to Accept Headers" for
426 : * the reasons why.
427 : */
428 : NS_IMETHODIMP
429 0 : Navigator::GetLanguage(nsAString& aLanguage)
430 : {
431 0 : nsTArray<nsString> languages;
432 0 : GetLanguages(languages);
433 0 : if (languages.Length() >= 1) {
434 0 : aLanguage.Assign(languages[0]);
435 : } else {
436 0 : aLanguage.Truncate();
437 : }
438 :
439 0 : return NS_OK;
440 : }
441 :
442 : void
443 0 : Navigator::GetLanguages(nsTArray<nsString>& aLanguages)
444 : {
445 0 : GetAcceptLanguages(aLanguages);
446 :
447 : // The returned value is cached by the binding code. The window listen to the
448 : // accept languages change and will clear the cache when needed. It has to
449 : // take care of dispatching the DOM event already and the invalidation and the
450 : // event has to be timed correctly.
451 0 : }
452 :
453 : void
454 0 : Navigator::GetPlatform(nsAString& aPlatform, CallerType aCallerType,
455 : ErrorResult& aRv) const
456 : {
457 0 : nsresult rv = GetPlatform(aPlatform,
458 0 : /* aUsePrefOverriddenValue = */ aCallerType != CallerType::System);
459 0 : if (NS_WARN_IF(NS_FAILED(rv))) {
460 0 : aRv.Throw(rv);
461 : }
462 0 : }
463 :
464 : void
465 0 : Navigator::GetOscpu(nsAString& aOSCPU, CallerType aCallerType,
466 : ErrorResult& aRv) const
467 : {
468 0 : if (aCallerType != CallerType::System) {
469 : // If fingerprinting resistance is on, we will spoof this value. See nsRFPService.h
470 : // for details about spoofed values.
471 0 : if (nsContentUtils::ShouldResistFingerprinting()) {
472 0 : aOSCPU.AssignLiteral(SPOOFED_OSCPU);
473 0 : return;
474 : }
475 :
476 : const nsAdoptingString& override =
477 0 : Preferences::GetString("general.oscpu.override");
478 :
479 0 : if (override) {
480 0 : aOSCPU = override;
481 0 : return;
482 : }
483 : }
484 :
485 : nsresult rv;
486 : nsCOMPtr<nsIHttpProtocolHandler>
487 0 : service(do_GetService(NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX "http", &rv));
488 0 : if (NS_WARN_IF(NS_FAILED(rv))) {
489 0 : aRv.Throw(rv);
490 0 : return;
491 : }
492 :
493 0 : nsAutoCString oscpu;
494 0 : rv = service->GetOscpu(oscpu);
495 0 : if (NS_WARN_IF(NS_FAILED(rv))) {
496 0 : aRv.Throw(rv);
497 0 : return;
498 : }
499 :
500 0 : CopyASCIItoUTF16(oscpu, aOSCPU);
501 : }
502 :
503 : NS_IMETHODIMP
504 0 : Navigator::GetVendor(nsAString& aVendor)
505 : {
506 0 : aVendor.Truncate();
507 0 : return NS_OK;
508 : }
509 :
510 : NS_IMETHODIMP
511 0 : Navigator::GetVendorSub(nsAString& aVendorSub)
512 : {
513 0 : aVendorSub.Truncate();
514 0 : return NS_OK;
515 : }
516 :
517 : NS_IMETHODIMP
518 0 : Navigator::GetProduct(nsAString& aProduct)
519 : {
520 0 : aProduct.AssignLiteral("Gecko");
521 0 : return NS_OK;
522 : }
523 :
524 : NS_IMETHODIMP
525 0 : Navigator::GetProductSub(nsAString& aProductSub)
526 : {
527 : // Legacy build ID hardcoded for backward compatibility (bug 776376)
528 0 : aProductSub.AssignLiteral(LEGACY_BUILD_ID);
529 0 : return NS_OK;
530 : }
531 :
532 : nsMimeTypeArray*
533 0 : Navigator::GetMimeTypes(ErrorResult& aRv)
534 : {
535 0 : if (!mMimeTypes) {
536 0 : if (!mWindow) {
537 0 : aRv.Throw(NS_ERROR_UNEXPECTED);
538 0 : return nullptr;
539 : }
540 0 : mMimeTypes = new nsMimeTypeArray(mWindow);
541 : }
542 :
543 0 : return mMimeTypes;
544 : }
545 :
546 : nsPluginArray*
547 0 : Navigator::GetPlugins(ErrorResult& aRv)
548 : {
549 0 : if (!mPlugins) {
550 0 : if (!mWindow) {
551 0 : aRv.Throw(NS_ERROR_UNEXPECTED);
552 0 : return nullptr;
553 : }
554 0 : mPlugins = new nsPluginArray(mWindow);
555 0 : mPlugins->Init();
556 : }
557 :
558 0 : return mPlugins;
559 : }
560 :
561 : Permissions*
562 0 : Navigator::GetPermissions(ErrorResult& aRv)
563 : {
564 0 : if (!mWindow) {
565 0 : aRv.Throw(NS_ERROR_UNEXPECTED);
566 0 : return nullptr;
567 : }
568 :
569 0 : if (!mPermissions) {
570 0 : mPermissions = new Permissions(mWindow);
571 : }
572 :
573 0 : return mPermissions;
574 : }
575 :
576 : StorageManager*
577 0 : Navigator::Storage()
578 : {
579 0 : MOZ_ASSERT(mWindow);
580 :
581 0 : if(!mStorageManager) {
582 0 : nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(mWindow);
583 0 : MOZ_ASSERT(global);
584 :
585 0 : mStorageManager = new StorageManager(global);
586 : }
587 :
588 0 : return mStorageManager;
589 : }
590 :
591 : // Values for the network.cookie.cookieBehavior pref are documented in
592 : // nsCookieService.cpp.
593 : #define COOKIE_BEHAVIOR_REJECT 2
594 :
595 : bool
596 0 : Navigator::CookieEnabled()
597 : {
598 : bool cookieEnabled =
599 0 : (Preferences::GetInt("network.cookie.cookieBehavior",
600 0 : COOKIE_BEHAVIOR_REJECT) != COOKIE_BEHAVIOR_REJECT);
601 :
602 : // Check whether an exception overrides the global cookie behavior
603 : // Note that the code for getting the URI here matches that in
604 : // nsHTMLDocument::SetCookie.
605 0 : if (!mWindow || !mWindow->GetDocShell()) {
606 0 : return cookieEnabled;
607 : }
608 :
609 0 : nsCOMPtr<nsIDocument> doc = mWindow->GetExtantDoc();
610 0 : if (!doc) {
611 0 : return cookieEnabled;
612 : }
613 :
614 0 : nsCOMPtr<nsIURI> codebaseURI;
615 0 : doc->NodePrincipal()->GetURI(getter_AddRefs(codebaseURI));
616 :
617 0 : if (!codebaseURI) {
618 : // Not a codebase, so technically can't set cookies, but let's
619 : // just return the default value.
620 0 : return cookieEnabled;
621 : }
622 :
623 : nsCOMPtr<nsICookiePermission> permMgr =
624 0 : do_GetService(NS_COOKIEPERMISSION_CONTRACTID);
625 0 : NS_ENSURE_TRUE(permMgr, cookieEnabled);
626 :
627 : // Pass null for the channel, just like the cookie service does.
628 : nsCookieAccess access;
629 0 : nsresult rv = permMgr->CanAccess(codebaseURI, nullptr, &access);
630 0 : NS_ENSURE_SUCCESS(rv, cookieEnabled);
631 :
632 0 : if (access != nsICookiePermission::ACCESS_DEFAULT) {
633 0 : cookieEnabled = access != nsICookiePermission::ACCESS_DENY;
634 : }
635 :
636 0 : return cookieEnabled;
637 : }
638 :
639 : bool
640 0 : Navigator::OnLine()
641 : {
642 0 : return !NS_IsOffline();
643 : }
644 :
645 : void
646 0 : Navigator::GetBuildID(nsAString& aBuildID, CallerType aCallerType,
647 : ErrorResult& aRv) const
648 : {
649 0 : if (aCallerType != CallerType::System) {
650 : // If fingerprinting resistance is on, we will spoof this value. See nsRFPService.h
651 : // for details about spoofed values.
652 0 : if (nsContentUtils::ShouldResistFingerprinting()) {
653 0 : aBuildID.AssignLiteral(LEGACY_BUILD_ID);
654 0 : return;
655 : }
656 : const nsAdoptingString& override =
657 0 : Preferences::GetString("general.buildID.override");
658 :
659 0 : if (override) {
660 0 : aBuildID = override;
661 0 : return;
662 : }
663 : }
664 :
665 : nsCOMPtr<nsIXULAppInfo> appInfo =
666 0 : do_GetService("@mozilla.org/xre/app-info;1");
667 0 : if (!appInfo) {
668 0 : aRv.Throw(NS_ERROR_NOT_IMPLEMENTED);
669 0 : return;
670 : }
671 :
672 0 : nsAutoCString buildID;
673 0 : nsresult rv = appInfo->GetAppBuildID(buildID);
674 0 : if (NS_WARN_IF(NS_FAILED(rv))) {
675 0 : aRv.Throw(rv);
676 0 : return;
677 : }
678 :
679 0 : aBuildID.Truncate();
680 0 : AppendASCIItoUTF16(buildID, aBuildID);
681 : }
682 :
683 : NS_IMETHODIMP
684 0 : Navigator::GetDoNotTrack(nsAString &aResult)
685 : {
686 0 : bool doNotTrack = nsContentUtils::DoNotTrackEnabled();
687 0 : if (!doNotTrack) {
688 0 : nsCOMPtr<nsILoadContext> loadContext = do_GetInterface(mWindow);
689 0 : doNotTrack = loadContext && loadContext->UseTrackingProtection();
690 : }
691 :
692 0 : if (doNotTrack) {
693 0 : aResult.AssignLiteral("1");
694 : } else {
695 0 : aResult.AssignLiteral("unspecified");
696 : }
697 :
698 0 : return NS_OK;
699 : }
700 :
701 : bool
702 0 : Navigator::JavaEnabled(CallerType aCallerType, ErrorResult& aRv)
703 : {
704 0 : Telemetry::AutoTimer<Telemetry::CHECK_JAVA_ENABLED> telemetryTimer;
705 :
706 : // Return true if we have a handler for the java mime
707 0 : nsAdoptingString javaMIME = Preferences::GetString("plugin.java.mime");
708 0 : NS_ENSURE_TRUE(!javaMIME.IsEmpty(), false);
709 :
710 0 : if (!mMimeTypes) {
711 0 : if (!mWindow) {
712 0 : aRv.Throw(NS_ERROR_UNEXPECTED);
713 0 : return false;
714 : }
715 0 : mMimeTypes = new nsMimeTypeArray(mWindow);
716 : }
717 :
718 0 : RefreshMIMEArray();
719 :
720 0 : nsMimeType *mimeType = mMimeTypes->NamedItem(javaMIME, aCallerType);
721 :
722 0 : return mimeType && mimeType->GetEnabledPlugin();
723 : }
724 :
725 : uint64_t
726 0 : Navigator::HardwareConcurrency()
727 : {
728 0 : workers::RuntimeService* rts = workers::RuntimeService::GetOrCreateService();
729 0 : if (!rts) {
730 0 : return 1;
731 : }
732 :
733 0 : return rts->ClampedHardwareConcurrency();
734 : }
735 :
736 : bool
737 0 : Navigator::CpuHasSSE2()
738 : {
739 0 : return mozilla::supports_sse2();
740 : }
741 :
742 : void
743 0 : Navigator::RefreshMIMEArray()
744 : {
745 0 : if (mMimeTypes) {
746 0 : mMimeTypes->Refresh();
747 : }
748 0 : }
749 :
750 : namespace {
751 :
752 : class VibrateWindowListener : public nsIDOMEventListener
753 : {
754 : public:
755 0 : VibrateWindowListener(nsPIDOMWindowInner* aWindow, nsIDocument* aDocument)
756 0 : {
757 0 : mWindow = do_GetWeakReference(aWindow);
758 0 : mDocument = do_GetWeakReference(aDocument);
759 :
760 0 : NS_NAMED_LITERAL_STRING(visibilitychange, "visibilitychange");
761 0 : aDocument->AddSystemEventListener(visibilitychange,
762 : this, /* listener */
763 : true, /* use capture */
764 0 : false /* wants untrusted */);
765 0 : }
766 :
767 : void RemoveListener();
768 :
769 : NS_DECL_ISUPPORTS
770 : NS_DECL_NSIDOMEVENTLISTENER
771 :
772 : private:
773 0 : virtual ~VibrateWindowListener()
774 0 : {
775 0 : }
776 :
777 : nsWeakPtr mWindow;
778 : nsWeakPtr mDocument;
779 : };
780 :
781 0 : NS_IMPL_ISUPPORTS(VibrateWindowListener, nsIDOMEventListener)
782 :
783 3 : StaticRefPtr<VibrateWindowListener> gVibrateWindowListener;
784 :
785 : static bool
786 0 : MayVibrate(nsIDocument* doc) {
787 : #if MOZ_WIDGET_GONK
788 : if (XRE_IsParentProcess()) {
789 : return true; // The system app can always vibrate
790 : }
791 : #endif // MOZ_WIDGET_GONK
792 :
793 : // Hidden documents cannot start or stop a vibration.
794 0 : return (doc && !doc->Hidden());
795 : }
796 :
797 : NS_IMETHODIMP
798 0 : VibrateWindowListener::HandleEvent(nsIDOMEvent* aEvent)
799 : {
800 : nsCOMPtr<nsIDocument> doc =
801 0 : do_QueryInterface(aEvent->InternalDOMEvent()->GetTarget());
802 :
803 0 : if (!MayVibrate(doc)) {
804 : // It's important that we call CancelVibrate(), not Vibrate() with an
805 : // empty list, because Vibrate() will fail if we're no longer focused, but
806 : // CancelVibrate() will succeed, so long as nobody else has started a new
807 : // vibration pattern.
808 0 : nsCOMPtr<nsPIDOMWindowInner> window = do_QueryReferent(mWindow);
809 0 : hal::CancelVibrate(window);
810 0 : RemoveListener();
811 0 : gVibrateWindowListener = nullptr;
812 : // Careful: The line above might have deleted |this|!
813 : }
814 :
815 0 : return NS_OK;
816 : }
817 :
818 : void
819 0 : VibrateWindowListener::RemoveListener()
820 : {
821 0 : nsCOMPtr<EventTarget> target = do_QueryReferent(mDocument);
822 0 : if (!target) {
823 0 : return;
824 : }
825 0 : NS_NAMED_LITERAL_STRING(visibilitychange, "visibilitychange");
826 0 : target->RemoveSystemEventListener(visibilitychange, this,
827 0 : true /* use capture */);
828 : }
829 :
830 : } // namespace
831 :
832 : void
833 0 : Navigator::AddIdleObserver(MozIdleObserver& aIdleObserver, ErrorResult& aRv)
834 : {
835 0 : if (!mWindow) {
836 0 : aRv.Throw(NS_ERROR_UNEXPECTED);
837 0 : return;
838 : }
839 0 : CallbackObjectHolder<MozIdleObserver, nsIIdleObserver> holder(&aIdleObserver);
840 0 : nsCOMPtr<nsIIdleObserver> obs = holder.ToXPCOMCallback();
841 0 : if (NS_FAILED(mWindow->RegisterIdleObserver(obs))) {
842 0 : NS_WARNING("Failed to add idle observer.");
843 : }
844 : }
845 :
846 : void
847 0 : Navigator::RemoveIdleObserver(MozIdleObserver& aIdleObserver, ErrorResult& aRv)
848 : {
849 0 : if (!mWindow) {
850 0 : aRv.Throw(NS_ERROR_UNEXPECTED);
851 0 : return;
852 : }
853 0 : CallbackObjectHolder<MozIdleObserver, nsIIdleObserver> holder(&aIdleObserver);
854 0 : nsCOMPtr<nsIIdleObserver> obs = holder.ToXPCOMCallback();
855 0 : if (NS_FAILED(mWindow->UnregisterIdleObserver(obs))) {
856 0 : NS_WARNING("Failed to remove idle observer.");
857 : }
858 : }
859 :
860 : void
861 0 : Navigator::SetVibrationPermission(bool aPermitted, bool aPersistent)
862 : {
863 0 : MOZ_ASSERT(NS_IsMainThread());
864 :
865 0 : nsTArray<uint32_t> pattern;
866 0 : pattern.SwapElements(mRequestedVibrationPattern);
867 :
868 0 : if (!mWindow) {
869 0 : return;
870 : }
871 :
872 0 : nsCOMPtr<nsIDocument> doc = mWindow->GetExtantDoc();
873 :
874 0 : if (!MayVibrate(doc)) {
875 0 : return;
876 : }
877 :
878 0 : if (aPermitted) {
879 : // Add a listener to cancel the vibration if the document becomes hidden,
880 : // and remove the old visibility listener, if there was one.
881 0 : if (!gVibrateWindowListener) {
882 : // If gVibrateWindowListener is null, this is the first time we've vibrated,
883 : // and we need to register a listener to clear gVibrateWindowListener on
884 : // shutdown.
885 0 : ClearOnShutdown(&gVibrateWindowListener);
886 : } else {
887 0 : gVibrateWindowListener->RemoveListener();
888 : }
889 0 : gVibrateWindowListener = new VibrateWindowListener(mWindow, doc);
890 0 : hal::Vibrate(pattern, mWindow);
891 : }
892 :
893 0 : if (aPersistent) {
894 0 : AddPermission(doc->NodePrincipal(), kVibrationPermissionType,
895 : aPermitted ? nsIPermissionManager::ALLOW_ACTION :
896 : nsIPermissionManager::DENY_ACTION,
897 0 : nsIPermissionManager::EXPIRE_SESSION, 0);
898 : }
899 : }
900 :
901 : bool
902 0 : Navigator::Vibrate(uint32_t aDuration)
903 : {
904 0 : AutoTArray<uint32_t, 1> pattern;
905 0 : pattern.AppendElement(aDuration);
906 0 : return Vibrate(pattern);
907 : }
908 :
909 : bool
910 0 : Navigator::Vibrate(const nsTArray<uint32_t>& aPattern)
911 : {
912 0 : MOZ_ASSERT(NS_IsMainThread());
913 :
914 0 : if (!mWindow) {
915 0 : return false;
916 : }
917 :
918 0 : nsCOMPtr<nsIDocument> doc = mWindow->GetExtantDoc();
919 :
920 0 : if (!MayVibrate(doc)) {
921 0 : return false;
922 : }
923 :
924 0 : nsTArray<uint32_t> pattern(aPattern);
925 :
926 0 : if (pattern.Length() > sMaxVibrateListLen) {
927 0 : pattern.SetLength(sMaxVibrateListLen);
928 : }
929 :
930 0 : for (size_t i = 0; i < pattern.Length(); ++i) {
931 0 : pattern[i] = std::min(sMaxVibrateMS, pattern[i]);
932 : }
933 :
934 : // The spec says we check sVibratorEnabled after we've done the sanity
935 : // checking on the pattern.
936 0 : if (!sVibratorEnabled) {
937 0 : return true;
938 : }
939 :
940 0 : mRequestedVibrationPattern.SwapElements(pattern);
941 0 : uint32_t permission = GetPermission(mWindow, kVibrationPermissionType);
942 :
943 0 : if (permission == nsIPermissionManager::ALLOW_ACTION ||
944 0 : mRequestedVibrationPattern.IsEmpty() ||
945 0 : (mRequestedVibrationPattern.Length() == 1 &&
946 0 : mRequestedVibrationPattern[0] == 0)) {
947 : // Always allow cancelling vibration and respect session permissions.
948 0 : SetVibrationPermission(true /* permitted */, false /* persistent */);
949 0 : return true;
950 : }
951 :
952 0 : nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
953 0 : if (!obs || permission == nsIPermissionManager::DENY_ACTION) {
954 : // Abort without observer service or on denied session permission.
955 0 : SetVibrationPermission(false /* permitted */, false /* persistent */);
956 0 : return true;
957 : }
958 :
959 : // Request user permission.
960 0 : obs->NotifyObservers(ToSupports(this), "Vibration:Request", nullptr);
961 :
962 0 : return true;
963 : }
964 :
965 : //*****************************************************************************
966 : // Pointer Events interface
967 : //*****************************************************************************
968 :
969 : uint32_t
970 0 : Navigator::MaxTouchPoints()
971 : {
972 0 : nsCOMPtr<nsIWidget> widget = widget::WidgetUtils::DOMWindowToWidget(mWindow->GetOuterWindow());
973 :
974 0 : NS_ENSURE_TRUE(widget, 0);
975 0 : return widget->GetMaxTouchPoints();
976 : }
977 :
978 : //*****************************************************************************
979 : // Navigator::nsIDOMClientInformation
980 : //*****************************************************************************
981 :
982 : void
983 0 : Navigator::RegisterContentHandler(const nsAString& aMIMEType,
984 : const nsAString& aURI,
985 : const nsAString& aTitle,
986 : ErrorResult& aRv)
987 : {
988 0 : if (!mWindow || !mWindow->GetOuterWindow() || !mWindow->GetDocShell()) {
989 0 : return;
990 : }
991 :
992 : nsCOMPtr<nsIWebContentHandlerRegistrar> registrar =
993 0 : do_GetService(NS_WEBCONTENTHANDLERREGISTRAR_CONTRACTID);
994 0 : if (!registrar) {
995 0 : return;
996 : }
997 :
998 0 : aRv = registrar->RegisterContentHandler(aMIMEType, aURI, aTitle,
999 0 : mWindow->GetOuterWindow());
1000 : }
1001 :
1002 : void
1003 0 : Navigator::RegisterProtocolHandler(const nsAString& aProtocol,
1004 : const nsAString& aURI,
1005 : const nsAString& aTitle,
1006 : ErrorResult& aRv)
1007 : {
1008 0 : if (!mWindow || !mWindow->GetOuterWindow() || !mWindow->GetDocShell()) {
1009 0 : return;
1010 : }
1011 :
1012 : nsCOMPtr<nsIWebContentHandlerRegistrar> registrar =
1013 0 : do_GetService(NS_WEBCONTENTHANDLERREGISTRAR_CONTRACTID);
1014 0 : if (!registrar) {
1015 0 : return;
1016 : }
1017 :
1018 0 : aRv = registrar->RegisterProtocolHandler(aProtocol, aURI, aTitle,
1019 0 : mWindow->GetOuterWindow());
1020 : }
1021 :
1022 : Geolocation*
1023 0 : Navigator::GetGeolocation(ErrorResult& aRv)
1024 : {
1025 0 : if (mGeolocation) {
1026 0 : return mGeolocation;
1027 : }
1028 :
1029 0 : if (!mWindow || !mWindow->GetOuterWindow() || !mWindow->GetDocShell()) {
1030 0 : aRv.Throw(NS_ERROR_FAILURE);
1031 0 : return nullptr;
1032 : }
1033 :
1034 0 : mGeolocation = new Geolocation();
1035 0 : if (NS_FAILED(mGeolocation->Init(mWindow))) {
1036 0 : mGeolocation = nullptr;
1037 0 : aRv.Throw(NS_ERROR_FAILURE);
1038 0 : return nullptr;
1039 : }
1040 :
1041 0 : return mGeolocation;
1042 : }
1043 :
1044 : class BeaconStreamListener final : public nsIStreamListener
1045 : {
1046 0 : ~BeaconStreamListener() {}
1047 :
1048 : public:
1049 0 : BeaconStreamListener() : mLoadGroup(nullptr) {}
1050 :
1051 0 : void SetLoadGroup(nsILoadGroup* aLoadGroup) {
1052 0 : mLoadGroup = aLoadGroup;
1053 0 : }
1054 :
1055 : NS_DECL_ISUPPORTS
1056 : NS_DECL_NSISTREAMLISTENER
1057 : NS_DECL_NSIREQUESTOBSERVER
1058 :
1059 : private:
1060 : nsCOMPtr<nsILoadGroup> mLoadGroup;
1061 :
1062 : };
1063 :
1064 0 : NS_IMPL_ISUPPORTS(BeaconStreamListener,
1065 : nsIStreamListener,
1066 : nsIRequestObserver)
1067 :
1068 : NS_IMETHODIMP
1069 0 : BeaconStreamListener::OnStartRequest(nsIRequest *aRequest,
1070 : nsISupports *aContext)
1071 : {
1072 : // release the loadgroup first
1073 0 : mLoadGroup = nullptr;
1074 :
1075 0 : aRequest->Cancel(NS_ERROR_NET_INTERRUPT);
1076 0 : return NS_BINDING_ABORTED;
1077 : }
1078 :
1079 : NS_IMETHODIMP
1080 0 : BeaconStreamListener::OnStopRequest(nsIRequest *aRequest,
1081 : nsISupports *aContext,
1082 : nsresult aStatus)
1083 : {
1084 0 : return NS_OK;
1085 : }
1086 :
1087 : NS_IMETHODIMP
1088 0 : BeaconStreamListener::OnDataAvailable(nsIRequest *aRequest,
1089 : nsISupports *ctxt,
1090 : nsIInputStream *inStr,
1091 : uint64_t sourceOffset,
1092 : uint32_t count)
1093 : {
1094 0 : MOZ_ASSERT(false);
1095 : return NS_OK;
1096 : }
1097 :
1098 : bool
1099 0 : Navigator::SendBeacon(const nsAString& aUrl,
1100 : const Nullable<fetch::BodyInit>& aData,
1101 : ErrorResult& aRv)
1102 : {
1103 0 : if (aData.IsNull()) {
1104 0 : return SendBeaconInternal(aUrl, nullptr, eBeaconTypeOther, aRv);
1105 : }
1106 :
1107 0 : if (aData.Value().IsArrayBuffer()) {
1108 0 : BodyExtractor<const ArrayBuffer> body(&aData.Value().GetAsArrayBuffer());
1109 0 : return SendBeaconInternal(aUrl, &body, eBeaconTypeArrayBuffer, aRv);
1110 : }
1111 :
1112 0 : if (aData.Value().IsArrayBufferView()) {
1113 0 : BodyExtractor<const ArrayBufferView> body(&aData.Value().GetAsArrayBufferView());
1114 0 : return SendBeaconInternal(aUrl, &body, eBeaconTypeArrayBuffer, aRv);
1115 : }
1116 :
1117 0 : if (aData.Value().IsBlob()) {
1118 0 : BodyExtractor<nsIXHRSendable> body(&aData.Value().GetAsBlob());
1119 0 : return SendBeaconInternal(aUrl, &body, eBeaconTypeBlob, aRv);
1120 : }
1121 :
1122 0 : if (aData.Value().IsFormData()) {
1123 0 : BodyExtractor<nsIXHRSendable> body(&aData.Value().GetAsFormData());
1124 0 : return SendBeaconInternal(aUrl, &body, eBeaconTypeOther, aRv);
1125 : }
1126 :
1127 0 : if (aData.Value().IsUSVString()) {
1128 0 : BodyExtractor<const nsAString> body(&aData.Value().GetAsUSVString());
1129 0 : return SendBeaconInternal(aUrl, &body, eBeaconTypeOther, aRv);
1130 : }
1131 :
1132 0 : if (aData.Value().IsURLSearchParams()) {
1133 0 : BodyExtractor<nsIXHRSendable> body(&aData.Value().GetAsURLSearchParams());
1134 0 : return SendBeaconInternal(aUrl, &body, eBeaconTypeOther, aRv);
1135 : }
1136 :
1137 0 : MOZ_CRASH("Invalid data type.");
1138 : return false;
1139 : }
1140 :
1141 : bool
1142 0 : Navigator::SendBeaconInternal(const nsAString& aUrl,
1143 : BodyExtractorBase* aBody,
1144 : BeaconType aType,
1145 : ErrorResult& aRv)
1146 : {
1147 0 : if (!mWindow) {
1148 0 : aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
1149 0 : return false;
1150 : }
1151 :
1152 0 : nsCOMPtr<nsIDocument> doc = mWindow->GetDoc();
1153 0 : if (!doc) {
1154 0 : aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
1155 0 : return false;
1156 : }
1157 :
1158 0 : nsIURI* documentURI = doc->GetDocumentURI();
1159 0 : if (!documentURI) {
1160 0 : aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
1161 0 : return false;
1162 : }
1163 :
1164 0 : nsCOMPtr<nsIURI> uri;
1165 0 : nsresult rv = nsContentUtils::NewURIWithDocumentCharset(
1166 0 : getter_AddRefs(uri),
1167 : aUrl,
1168 : doc,
1169 0 : doc->GetDocBaseURI());
1170 0 : if (NS_FAILED(rv)) {
1171 0 : aRv.ThrowTypeError<MSG_INVALID_URL>(aUrl);
1172 0 : return false;
1173 : }
1174 :
1175 : // Spec disallows any schemes save for HTTP/HTTPs
1176 : bool isValidScheme;
1177 0 : if (!(NS_SUCCEEDED(uri->SchemeIs("http", &isValidScheme)) && isValidScheme) &&
1178 0 : !(NS_SUCCEEDED(uri->SchemeIs("https", &isValidScheme)) && isValidScheme)) {
1179 0 : aRv.ThrowTypeError<MSG_INVALID_URL_SCHEME>( NS_LITERAL_STRING("Beacon"), aUrl);
1180 0 : return false;
1181 : }
1182 :
1183 : nsLoadFlags loadFlags = nsIRequest::LOAD_NORMAL |
1184 0 : nsIChannel::LOAD_CLASSIFY_URI;
1185 :
1186 : // No need to use CORS for sendBeacon unless it's a BLOB
1187 : nsSecurityFlags securityFlags = aType == eBeaconTypeBlob
1188 0 : ? nsILoadInfo::SEC_REQUIRE_CORS_DATA_INHERITS
1189 0 : : nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_DATA_INHERITS;
1190 0 : securityFlags |= nsILoadInfo::SEC_COOKIES_INCLUDE;
1191 :
1192 0 : nsCOMPtr<nsIChannel> channel;
1193 0 : rv = NS_NewChannel(getter_AddRefs(channel),
1194 : uri,
1195 : doc,
1196 : securityFlags,
1197 : nsIContentPolicy::TYPE_BEACON,
1198 : nullptr, // aLoadGroup
1199 : nullptr, // aCallbacks
1200 0 : loadFlags);
1201 :
1202 0 : if (NS_FAILED(rv)) {
1203 0 : aRv.Throw(rv);
1204 0 : return false;
1205 : }
1206 :
1207 0 : nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(channel);
1208 0 : if (!httpChannel) {
1209 : // Beacon spec only supports HTTP requests at this time
1210 0 : aRv.Throw(NS_ERROR_DOM_BAD_URI);
1211 0 : return false;
1212 : }
1213 0 : mozilla::net::ReferrerPolicy referrerPolicy = doc->GetReferrerPolicy();
1214 0 : rv = httpChannel->SetReferrerWithPolicy(documentURI, referrerPolicy);
1215 0 : MOZ_ASSERT(NS_SUCCEEDED(rv));
1216 :
1217 0 : nsCOMPtr<nsIInputStream> in;
1218 0 : nsAutoCString contentTypeWithCharset;
1219 0 : nsAutoCString charset;
1220 0 : uint64_t length = 0;
1221 :
1222 0 : if (aBody) {
1223 0 : aRv = aBody->GetAsStream(getter_AddRefs(in), &length,
1224 0 : contentTypeWithCharset, charset);
1225 0 : if (NS_WARN_IF(aRv.Failed())) {
1226 0 : return false;
1227 : }
1228 :
1229 0 : nsCOMPtr<nsIUploadChannel2> uploadChannel = do_QueryInterface(channel);
1230 0 : if (!uploadChannel) {
1231 0 : aRv.Throw(NS_ERROR_FAILURE);
1232 0 : return false;
1233 : }
1234 :
1235 0 : uploadChannel->ExplicitSetUploadStream(in, contentTypeWithCharset, length,
1236 0 : NS_LITERAL_CSTRING("POST"),
1237 0 : false);
1238 : } else {
1239 0 : rv = httpChannel->SetRequestMethod(NS_LITERAL_CSTRING("POST"));
1240 0 : MOZ_ASSERT(NS_SUCCEEDED(rv));
1241 : }
1242 :
1243 0 : nsCOMPtr<nsISupportsPriority> p = do_QueryInterface(channel);
1244 0 : if (p) {
1245 0 : p->SetPriority(nsISupportsPriority::PRIORITY_LOWEST);
1246 : }
1247 :
1248 0 : nsCOMPtr<nsIClassOfService> cos(do_QueryInterface(channel));
1249 0 : if (cos) {
1250 0 : cos->AddClassFlags(nsIClassOfService::Background);
1251 : }
1252 :
1253 : // The channel needs to have a loadgroup associated with it, so that we can
1254 : // cancel the channel and any redirected channels it may create.
1255 0 : nsCOMPtr<nsILoadGroup> loadGroup = do_CreateInstance(NS_LOADGROUP_CONTRACTID);
1256 : nsCOMPtr<nsIInterfaceRequestor> callbacks =
1257 0 : do_QueryInterface(mWindow->GetDocShell());
1258 0 : loadGroup->SetNotificationCallbacks(callbacks);
1259 0 : channel->SetLoadGroup(loadGroup);
1260 :
1261 0 : RefPtr<BeaconStreamListener> beaconListener = new BeaconStreamListener();
1262 0 : rv = channel->AsyncOpen2(beaconListener);
1263 : // do not throw if security checks fail within asyncOpen2
1264 0 : NS_ENSURE_SUCCESS(rv, false);
1265 :
1266 : // make the beaconListener hold a strong reference to the loadgroup
1267 : // which is released in ::OnStartRequest
1268 0 : beaconListener->SetLoadGroup(loadGroup);
1269 :
1270 0 : return true;
1271 : }
1272 :
1273 : MediaDevices*
1274 0 : Navigator::GetMediaDevices(ErrorResult& aRv)
1275 : {
1276 0 : if (!mMediaDevices) {
1277 0 : if (!mWindow ||
1278 0 : !mWindow->GetOuterWindow() ||
1279 0 : mWindow->GetOuterWindow()->GetCurrentInnerWindow() != mWindow) {
1280 0 : aRv.Throw(NS_ERROR_NOT_AVAILABLE);
1281 0 : return nullptr;
1282 : }
1283 0 : mMediaDevices = new MediaDevices(mWindow);
1284 : }
1285 0 : return mMediaDevices;
1286 : }
1287 :
1288 : void
1289 0 : Navigator::MozGetUserMedia(const MediaStreamConstraints& aConstraints,
1290 : NavigatorUserMediaSuccessCallback& aOnSuccess,
1291 : NavigatorUserMediaErrorCallback& aOnError,
1292 : CallerType aCallerType,
1293 : ErrorResult& aRv)
1294 : {
1295 : CallbackObjectHolder<NavigatorUserMediaSuccessCallback,
1296 0 : nsIDOMGetUserMediaSuccessCallback> holder1(&aOnSuccess);
1297 : nsCOMPtr<nsIDOMGetUserMediaSuccessCallback> onsuccess =
1298 0 : holder1.ToXPCOMCallback();
1299 :
1300 : CallbackObjectHolder<NavigatorUserMediaErrorCallback,
1301 0 : nsIDOMGetUserMediaErrorCallback> holder2(&aOnError);
1302 0 : nsCOMPtr<nsIDOMGetUserMediaErrorCallback> onerror = holder2.ToXPCOMCallback();
1303 :
1304 0 : if (!mWindow || !mWindow->GetOuterWindow() ||
1305 0 : mWindow->GetOuterWindow()->GetCurrentInnerWindow() != mWindow) {
1306 0 : aRv.Throw(NS_ERROR_NOT_AVAILABLE);
1307 0 : return;
1308 : }
1309 :
1310 0 : MediaManager* manager = MediaManager::Get();
1311 0 : aRv = manager->GetUserMedia(mWindow, aConstraints, onsuccess, onerror,
1312 0 : aCallerType);
1313 : }
1314 :
1315 : void
1316 0 : Navigator::MozGetUserMediaDevices(const MediaStreamConstraints& aConstraints,
1317 : MozGetUserMediaDevicesSuccessCallback& aOnSuccess,
1318 : NavigatorUserMediaErrorCallback& aOnError,
1319 : uint64_t aInnerWindowID,
1320 : const nsAString& aCallID,
1321 : ErrorResult& aRv)
1322 : {
1323 : CallbackObjectHolder<MozGetUserMediaDevicesSuccessCallback,
1324 0 : nsIGetUserMediaDevicesSuccessCallback> holder1(&aOnSuccess);
1325 : nsCOMPtr<nsIGetUserMediaDevicesSuccessCallback> onsuccess =
1326 0 : holder1.ToXPCOMCallback();
1327 :
1328 : CallbackObjectHolder<NavigatorUserMediaErrorCallback,
1329 0 : nsIDOMGetUserMediaErrorCallback> holder2(&aOnError);
1330 0 : nsCOMPtr<nsIDOMGetUserMediaErrorCallback> onerror = holder2.ToXPCOMCallback();
1331 :
1332 0 : if (!mWindow || !mWindow->GetOuterWindow() ||
1333 0 : mWindow->GetOuterWindow()->GetCurrentInnerWindow() != mWindow) {
1334 0 : aRv.Throw(NS_ERROR_NOT_AVAILABLE);
1335 0 : return;
1336 : }
1337 :
1338 0 : MediaManager* manager = MediaManager::Get();
1339 0 : aRv = manager->GetUserMediaDevices(mWindow, aConstraints, onsuccess, onerror,
1340 0 : aInnerWindowID, aCallID);
1341 : }
1342 :
1343 : DesktopNotificationCenter*
1344 0 : Navigator::GetMozNotification(ErrorResult& aRv)
1345 : {
1346 0 : if (mNotification) {
1347 0 : return mNotification;
1348 : }
1349 :
1350 0 : if (!mWindow || !mWindow->GetDocShell()) {
1351 0 : aRv.Throw(NS_ERROR_FAILURE);
1352 0 : return nullptr;
1353 : }
1354 :
1355 0 : mNotification = new DesktopNotificationCenter(mWindow);
1356 0 : return mNotification;
1357 : }
1358 :
1359 : //*****************************************************************************
1360 : // Navigator::nsINavigatorBattery
1361 : //*****************************************************************************
1362 :
1363 : Promise*
1364 0 : Navigator::GetBattery(ErrorResult& aRv)
1365 : {
1366 0 : if (mBatteryPromise) {
1367 0 : return mBatteryPromise;
1368 : }
1369 :
1370 0 : if (!mWindow || !mWindow->GetDocShell()) {
1371 0 : aRv.Throw(NS_ERROR_UNEXPECTED);
1372 0 : return nullptr;
1373 : }
1374 :
1375 0 : nsCOMPtr<nsIGlobalObject> go = do_QueryInterface(mWindow);
1376 0 : RefPtr<Promise> batteryPromise = Promise::Create(go, aRv);
1377 0 : if (NS_WARN_IF(aRv.Failed())) {
1378 0 : return nullptr;
1379 : }
1380 0 : mBatteryPromise = batteryPromise;
1381 :
1382 0 : if (!mBatteryManager) {
1383 0 : mBatteryManager = new battery::BatteryManager(mWindow);
1384 0 : mBatteryManager->Init();
1385 : }
1386 :
1387 0 : mBatteryPromise->MaybeResolve(mBatteryManager);
1388 :
1389 0 : return mBatteryPromise;
1390 : }
1391 :
1392 : already_AddRefed<Promise>
1393 0 : Navigator::PublishServer(const nsAString& aName,
1394 : const FlyWebPublishOptions& aOptions,
1395 : ErrorResult& aRv)
1396 : {
1397 0 : RefPtr<FlyWebService> service = FlyWebService::GetOrCreate();
1398 0 : if (!service) {
1399 0 : aRv.Throw(NS_ERROR_FAILURE);
1400 0 : return nullptr;
1401 : }
1402 :
1403 : RefPtr<FlyWebPublishPromise> mozPromise =
1404 0 : service->PublishServer(aName, aOptions, mWindow);
1405 0 : MOZ_ASSERT(mozPromise);
1406 :
1407 0 : nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(mWindow);
1408 0 : ErrorResult result;
1409 0 : RefPtr<Promise> domPromise = Promise::Create(global, result);
1410 0 : if (result.Failed()) {
1411 0 : aRv.Throw(NS_ERROR_FAILURE);
1412 0 : return nullptr;
1413 : }
1414 :
1415 0 : mozPromise->Then(global->AbstractMainThreadFor(TaskCategory::Other),
1416 : __func__,
1417 0 : [domPromise] (FlyWebPublishedServer* aServer) {
1418 0 : domPromise->MaybeResolve(aServer);
1419 0 : },
1420 0 : [domPromise] (nsresult aStatus) {
1421 0 : domPromise->MaybeReject(aStatus);
1422 0 : });
1423 :
1424 0 : return domPromise.forget();
1425 : }
1426 :
1427 : PowerManager*
1428 0 : Navigator::GetMozPower(ErrorResult& aRv)
1429 : {
1430 0 : if (!mPowerManager) {
1431 0 : if (!mWindow) {
1432 0 : aRv.Throw(NS_ERROR_UNEXPECTED);
1433 0 : return nullptr;
1434 : }
1435 0 : mPowerManager = PowerManager::CreateInstance(mWindow);
1436 0 : if (!mPowerManager) {
1437 : // We failed to get the power manager service?
1438 0 : aRv.Throw(NS_ERROR_UNEXPECTED);
1439 : }
1440 : }
1441 :
1442 0 : return mPowerManager;
1443 : }
1444 :
1445 : already_AddRefed<WakeLock>
1446 0 : Navigator::RequestWakeLock(const nsAString &aTopic, ErrorResult& aRv)
1447 : {
1448 0 : if (!mWindow) {
1449 0 : aRv.Throw(NS_ERROR_UNEXPECTED);
1450 0 : return nullptr;
1451 : }
1452 :
1453 : RefPtr<power::PowerManagerService> pmService =
1454 0 : power::PowerManagerService::GetInstance();
1455 : // Maybe it went away for some reason... Or maybe we're just called
1456 : // from our XPCOM method.
1457 0 : if (!pmService) {
1458 0 : aRv.Throw(NS_ERROR_UNEXPECTED);
1459 0 : return nullptr;
1460 : }
1461 :
1462 0 : return pmService->NewWakeLock(aTopic, mWindow, aRv);
1463 : }
1464 :
1465 : already_AddRefed<LegacyMozTCPSocket>
1466 0 : Navigator::MozTCPSocket()
1467 : {
1468 0 : RefPtr<LegacyMozTCPSocket> socket = new LegacyMozTCPSocket(GetWindow());
1469 0 : return socket.forget();
1470 : }
1471 :
1472 : void
1473 0 : Navigator::GetGamepads(nsTArray<RefPtr<Gamepad> >& aGamepads,
1474 : ErrorResult& aRv)
1475 : {
1476 0 : if (!mWindow) {
1477 0 : aRv.Throw(NS_ERROR_UNEXPECTED);
1478 0 : return;
1479 : }
1480 0 : NS_ENSURE_TRUE_VOID(mWindow->GetDocShell());
1481 0 : nsGlobalWindow* win = nsGlobalWindow::Cast(mWindow);
1482 0 : win->SetHasGamepadEventListener(true);
1483 0 : win->GetGamepads(aGamepads);
1484 : }
1485 :
1486 : GamepadServiceTest*
1487 0 : Navigator::RequestGamepadServiceTest()
1488 : {
1489 0 : if (!mGamepadServiceTest) {
1490 0 : mGamepadServiceTest = GamepadServiceTest::CreateTestService(mWindow);
1491 : }
1492 0 : return mGamepadServiceTest;
1493 : }
1494 :
1495 : already_AddRefed<Promise>
1496 0 : Navigator::GetVRDisplays(ErrorResult& aRv)
1497 : {
1498 0 : if (!mWindow || !mWindow->GetDocShell()) {
1499 0 : aRv.Throw(NS_ERROR_UNEXPECTED);
1500 0 : return nullptr;
1501 : }
1502 :
1503 0 : nsGlobalWindow* win = nsGlobalWindow::Cast(mWindow);
1504 0 : win->NotifyVREventListenerAdded();
1505 :
1506 0 : nsCOMPtr<nsIGlobalObject> go = do_QueryInterface(mWindow);
1507 0 : RefPtr<Promise> p = Promise::Create(go, aRv);
1508 0 : if (aRv.Failed()) {
1509 0 : return nullptr;
1510 : }
1511 :
1512 : // We pass mWindow's id to RefreshVRDisplays, so NotifyVRDisplaysUpdated will
1513 : // be called asynchronously, resolving the promises in mVRGetDisplaysPromises.
1514 0 : if (!VRDisplay::RefreshVRDisplays(win->WindowID())) {
1515 0 : p->MaybeReject(NS_ERROR_FAILURE);
1516 0 : return p.forget();
1517 : }
1518 :
1519 0 : mVRGetDisplaysPromises.AppendElement(p);
1520 0 : return p.forget();
1521 : }
1522 :
1523 : void
1524 0 : Navigator::GetActiveVRDisplays(nsTArray<RefPtr<VRDisplay>>& aDisplays) const
1525 : {
1526 : /**
1527 : * Get only the active VR displays.
1528 : * Callers do not wish to VRDisplay::RefreshVRDisplays, as the enumeration may
1529 : * activate hardware that is not yet intended to be used.
1530 : */
1531 0 : if (!mWindow || !mWindow->GetDocShell()) {
1532 0 : return;
1533 : }
1534 0 : nsGlobalWindow* win = nsGlobalWindow::Cast(mWindow);
1535 0 : win->NotifyVREventListenerAdded();
1536 0 : nsTArray<RefPtr<VRDisplay>> displays;
1537 0 : if (win->UpdateVRDisplays(displays)) {
1538 0 : for (auto display : displays) {
1539 0 : if (display->IsPresenting()) {
1540 0 : aDisplays.AppendElement(display);
1541 : }
1542 : }
1543 : }
1544 : }
1545 :
1546 : void
1547 0 : Navigator::NotifyVRDisplaysUpdated()
1548 : {
1549 : // Synchronize the VR devices and resolve the promises in
1550 : // mVRGetDisplaysPromises
1551 0 : nsGlobalWindow* win = nsGlobalWindow::Cast(mWindow);
1552 :
1553 0 : nsTArray<RefPtr<VRDisplay>> vrDisplays;
1554 0 : if (win->UpdateVRDisplays(vrDisplays)) {
1555 0 : for (auto p : mVRGetDisplaysPromises) {
1556 0 : p->MaybeResolve(vrDisplays);
1557 : }
1558 : } else {
1559 0 : for (auto p : mVRGetDisplaysPromises) {
1560 0 : p->MaybeReject(NS_ERROR_FAILURE);
1561 : }
1562 : }
1563 0 : mVRGetDisplaysPromises.Clear();
1564 0 : }
1565 :
1566 : void
1567 0 : Navigator::NotifyActiveVRDisplaysChanged()
1568 : {
1569 0 : NavigatorBinding::ClearCachedActiveVRDisplaysValue(this);
1570 0 : }
1571 :
1572 : VRServiceTest*
1573 0 : Navigator::RequestVRServiceTest()
1574 : {
1575 : // Ensure that the Mock VR devices are not released prematurely
1576 0 : nsGlobalWindow* win = nsGlobalWindow::Cast(mWindow);
1577 0 : win->NotifyVREventListenerAdded();
1578 :
1579 0 : if (!mVRServiceTest) {
1580 0 : mVRServiceTest = VRServiceTest::CreateTestService(mWindow);
1581 : }
1582 0 : return mVRServiceTest;
1583 : }
1584 :
1585 : bool
1586 0 : Navigator::IsWebVRContentDetected() const
1587 : {
1588 0 : nsGlobalWindow* win = nsGlobalWindow::Cast(mWindow);
1589 0 : return win->IsVRContentDetected();
1590 : }
1591 :
1592 : bool
1593 0 : Navigator::IsWebVRContentPresenting() const
1594 : {
1595 0 : nsGlobalWindow* win = nsGlobalWindow::Cast(mWindow);
1596 0 : return win->IsVRContentPresenting();
1597 : }
1598 :
1599 : void
1600 0 : Navigator::RequestVRPresentation(VRDisplay& aDisplay)
1601 : {
1602 0 : nsGlobalWindow* win = nsGlobalWindow::Cast(mWindow);
1603 0 : win->DispatchVRDisplayActivate(aDisplay.DisplayId(), VRDisplayEventReason::Requested);
1604 0 : }
1605 :
1606 : //*****************************************************************************
1607 : // Navigator::nsIMozNavigatorNetwork
1608 : //*****************************************************************************
1609 :
1610 : NS_IMETHODIMP
1611 0 : Navigator::GetProperties(nsINetworkProperties** aProperties)
1612 : {
1613 0 : ErrorResult rv;
1614 0 : NS_IF_ADDREF(*aProperties = GetConnection(rv));
1615 0 : return NS_OK;
1616 : }
1617 :
1618 : network::Connection*
1619 0 : Navigator::GetConnection(ErrorResult& aRv)
1620 : {
1621 0 : if (!mConnection) {
1622 0 : if (!mWindow) {
1623 0 : aRv.Throw(NS_ERROR_UNEXPECTED);
1624 0 : return nullptr;
1625 : }
1626 0 : mConnection = network::Connection::CreateForWindow(mWindow);
1627 : }
1628 :
1629 0 : return mConnection;
1630 : }
1631 :
1632 : #ifdef MOZ_TIME_MANAGER
1633 : time::TimeManager*
1634 : Navigator::GetMozTime(ErrorResult& aRv)
1635 : {
1636 : if (!mWindow) {
1637 : aRv.Throw(NS_ERROR_UNEXPECTED);
1638 : return nullptr;
1639 : }
1640 :
1641 : if (!mTimeManager) {
1642 : mTimeManager = new time::TimeManager(mWindow);
1643 : }
1644 :
1645 : return mTimeManager;
1646 : }
1647 : #endif
1648 :
1649 : already_AddRefed<ServiceWorkerContainer>
1650 0 : Navigator::ServiceWorker()
1651 : {
1652 0 : MOZ_ASSERT(mWindow);
1653 :
1654 0 : if (!mServiceWorkerContainer) {
1655 0 : mServiceWorkerContainer = new ServiceWorkerContainer(mWindow);
1656 : }
1657 :
1658 0 : RefPtr<ServiceWorkerContainer> ref = mServiceWorkerContainer;
1659 0 : return ref.forget();
1660 : }
1661 :
1662 : size_t
1663 0 : Navigator::SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const
1664 : {
1665 0 : size_t n = aMallocSizeOf(this);
1666 :
1667 : // TODO: add SizeOfIncludingThis() to nsMimeTypeArray, bug 674113.
1668 : // TODO: add SizeOfIncludingThis() to nsPluginArray, bug 674114.
1669 : // TODO: add SizeOfIncludingThis() to Geolocation, bug 674115.
1670 : // TODO: add SizeOfIncludingThis() to DesktopNotificationCenter, bug 674116.
1671 :
1672 0 : return n;
1673 : }
1674 :
1675 : void
1676 0 : Navigator::SetWindow(nsPIDOMWindowInner *aInnerWindow)
1677 : {
1678 0 : NS_ASSERTION(aInnerWindow->IsInnerWindow(),
1679 : "Navigator must get an inner window!");
1680 0 : mWindow = aInnerWindow;
1681 0 : }
1682 :
1683 : void
1684 0 : Navigator::OnNavigation()
1685 : {
1686 0 : if (!mWindow) {
1687 0 : return;
1688 : }
1689 :
1690 : // If MediaManager is open let it inform any live streams or pending callbacks
1691 0 : MediaManager *manager = MediaManager::GetIfExists();
1692 0 : if (manager) {
1693 0 : manager->OnNavigation(mWindow->WindowID());
1694 : }
1695 : }
1696 :
1697 : bool
1698 0 : Navigator::CheckPermission(const char* type)
1699 : {
1700 0 : return CheckPermission(mWindow, type);
1701 : }
1702 :
1703 : /* static */
1704 : bool
1705 0 : Navigator::CheckPermission(nsPIDOMWindowInner* aWindow, const char* aType)
1706 : {
1707 0 : if (!aWindow) {
1708 0 : return false;
1709 : }
1710 :
1711 0 : uint32_t permission = GetPermission(aWindow, aType);
1712 0 : return permission == nsIPermissionManager::ALLOW_ACTION;
1713 : }
1714 :
1715 : JSObject*
1716 0 : Navigator::WrapObject(JSContext* cx, JS::Handle<JSObject*> aGivenProto)
1717 : {
1718 0 : return NavigatorBinding::Wrap(cx, this, aGivenProto);
1719 : }
1720 :
1721 : /* static */
1722 : bool
1723 0 : Navigator::HasWakeLockSupport(JSContext* /* unused*/, JSObject* /*unused */)
1724 : {
1725 : nsCOMPtr<nsIPowerManagerService> pmService =
1726 0 : do_GetService(POWERMANAGERSERVICE_CONTRACTID);
1727 : // No service means no wake lock support
1728 0 : return !!pmService;
1729 : }
1730 :
1731 : /* static */
1732 : bool
1733 0 : Navigator::HasWifiManagerSupport(JSContext* /* unused */,
1734 : JSObject* aGlobal)
1735 : {
1736 : // On XBL scope, the global object is NOT |window|. So we have
1737 : // to use nsContentUtils::GetObjectPrincipal to get the principal
1738 : // and test directly with permission manager.
1739 :
1740 0 : nsIPrincipal* principal = nsContentUtils::ObjectPrincipal(aGlobal);
1741 0 : uint32_t permission = GetPermission(principal, "wifi-manage");
1742 :
1743 0 : return permission == nsIPermissionManager::ALLOW_ACTION;
1744 : }
1745 :
1746 : /* static */
1747 : bool
1748 0 : Navigator::HasUserMediaSupport(JSContext* /* unused */,
1749 : JSObject* /* unused */)
1750 : {
1751 : // Make enabling peerconnection enable getUserMedia() as well
1752 0 : return Preferences::GetBool("media.navigator.enabled", false) ||
1753 0 : Preferences::GetBool("media.peerconnection.enabled", false);
1754 : }
1755 :
1756 : /* static */
1757 : bool
1758 0 : Navigator::IsE10sEnabled(JSContext* aCx, JSObject* aGlobal)
1759 : {
1760 0 : return XRE_IsContentProcess();
1761 : }
1762 :
1763 : bool
1764 0 : Navigator::MozE10sEnabled()
1765 : {
1766 : // This will only be called if IsE10sEnabled() is true.
1767 0 : return true;
1768 : }
1769 :
1770 : /* static */
1771 : already_AddRefed<nsPIDOMWindowInner>
1772 0 : Navigator::GetWindowFromGlobal(JSObject* aGlobal)
1773 : {
1774 : nsCOMPtr<nsPIDOMWindowInner> win =
1775 0 : do_QueryInterface(nsJSUtils::GetStaticScriptGlobal(aGlobal));
1776 0 : MOZ_ASSERT(!win || win->IsInnerWindow());
1777 0 : return win.forget();
1778 : }
1779 :
1780 : nsresult
1781 1 : Navigator::GetPlatform(nsAString& aPlatform, bool aUsePrefOverriddenValue)
1782 : {
1783 1 : MOZ_ASSERT(NS_IsMainThread());
1784 :
1785 1 : if (aUsePrefOverriddenValue) {
1786 : // If fingerprinting resistance is on, we will spoof this value. See nsRFPService.h
1787 : // for details about spoofed values.
1788 0 : if (nsContentUtils::ShouldResistFingerprinting()) {
1789 0 : aPlatform.AssignLiteral(SPOOFED_PLATFORM);
1790 0 : return NS_OK;
1791 : }
1792 : const nsAdoptingString& override =
1793 0 : mozilla::Preferences::GetString("general.platform.override");
1794 :
1795 0 : if (override) {
1796 0 : aPlatform = override;
1797 0 : return NS_OK;
1798 : }
1799 : }
1800 :
1801 : nsresult rv;
1802 :
1803 : nsCOMPtr<nsIHttpProtocolHandler>
1804 2 : service(do_GetService(NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX "http", &rv));
1805 1 : NS_ENSURE_SUCCESS(rv, rv);
1806 :
1807 : // Sorry for the #if platform ugliness, but Communicator is likewise
1808 : // hardcoded and we are seeking backward compatibility here (bug 47080).
1809 : #if defined(_WIN64)
1810 : aPlatform.AssignLiteral("Win64");
1811 : #elif defined(WIN32)
1812 : aPlatform.AssignLiteral("Win32");
1813 : #elif defined(XP_MACOSX) && defined(__ppc__)
1814 : aPlatform.AssignLiteral("MacPPC");
1815 : #elif defined(XP_MACOSX) && defined(__i386__)
1816 : aPlatform.AssignLiteral("MacIntel");
1817 : #elif defined(XP_MACOSX) && defined(__x86_64__)
1818 : aPlatform.AssignLiteral("MacIntel");
1819 : #else
1820 : // XXX Communicator uses compiled-in build-time string defines
1821 : // to indicate the platform it was compiled *for*, not what it is
1822 : // currently running *on* which is what this does.
1823 2 : nsAutoCString plat;
1824 1 : rv = service->GetOscpu(plat);
1825 1 : CopyASCIItoUTF16(plat, aPlatform);
1826 : #endif
1827 :
1828 1 : return rv;
1829 : }
1830 :
1831 : /* static */ nsresult
1832 1 : Navigator::GetAppVersion(nsAString& aAppVersion, bool aUsePrefOverriddenValue)
1833 : {
1834 1 : MOZ_ASSERT(NS_IsMainThread());
1835 :
1836 1 : if (aUsePrefOverriddenValue) {
1837 : // If fingerprinting resistance is on, we will spoof this value. See nsRFPService.h
1838 : // for details about spoofed values.
1839 0 : if (nsContentUtils::ShouldResistFingerprinting()) {
1840 0 : aAppVersion.AssignLiteral(SPOOFED_APPVERSION);
1841 0 : return NS_OK;
1842 : }
1843 : const nsAdoptingString& override =
1844 0 : mozilla::Preferences::GetString("general.appversion.override");
1845 :
1846 0 : if (override) {
1847 0 : aAppVersion = override;
1848 0 : return NS_OK;
1849 : }
1850 : }
1851 :
1852 : nsresult rv;
1853 :
1854 : nsCOMPtr<nsIHttpProtocolHandler>
1855 2 : service(do_GetService(NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX "http", &rv));
1856 1 : NS_ENSURE_SUCCESS(rv, rv);
1857 :
1858 2 : nsAutoCString str;
1859 1 : rv = service->GetAppVersion(str);
1860 1 : CopyASCIItoUTF16(str, aAppVersion);
1861 1 : NS_ENSURE_SUCCESS(rv, rv);
1862 :
1863 1 : aAppVersion.AppendLiteral(" (");
1864 :
1865 1 : rv = service->GetPlatform(str);
1866 1 : NS_ENSURE_SUCCESS(rv, rv);
1867 :
1868 1 : AppendASCIItoUTF16(str, aAppVersion);
1869 1 : aAppVersion.Append(char16_t(')'));
1870 :
1871 1 : return rv;
1872 : }
1873 :
1874 : /* static */ void
1875 1 : Navigator::AppName(nsAString& aAppName, bool aUsePrefOverriddenValue)
1876 : {
1877 1 : MOZ_ASSERT(NS_IsMainThread());
1878 :
1879 1 : if (aUsePrefOverriddenValue) {
1880 : // If fingerprinting resistance is on, we will spoof this value. See nsRFPService.h
1881 : // for details about spoofed values.
1882 0 : if (nsContentUtils::ShouldResistFingerprinting()) {
1883 0 : aAppName.AssignLiteral(SPOOFED_APPNAME);
1884 0 : return;
1885 : }
1886 :
1887 : const nsAdoptingString& override =
1888 0 : mozilla::Preferences::GetString("general.appname.override");
1889 :
1890 0 : if (override) {
1891 0 : aAppName = override;
1892 0 : return;
1893 : }
1894 : }
1895 :
1896 1 : aAppName.AssignLiteral("Netscape");
1897 : }
1898 :
1899 : void
1900 0 : Navigator::ClearUserAgentCache()
1901 : {
1902 0 : NavigatorBinding::ClearCachedUserAgentValue(this);
1903 0 : }
1904 :
1905 : nsresult
1906 0 : Navigator::GetUserAgent(nsPIDOMWindowInner* aWindow,
1907 : bool aIsCallerChrome,
1908 : nsAString& aUserAgent)
1909 : {
1910 0 : MOZ_ASSERT(NS_IsMainThread());
1911 :
1912 : // We will skip the override and pass to httpHandler to get spoofed userAgent
1913 : // when 'privacy.resistFingerprinting' is true.
1914 0 : if (!aIsCallerChrome &&
1915 0 : !nsContentUtils::ShouldResistFingerprinting()) {
1916 : const nsAdoptingString& override =
1917 0 : mozilla::Preferences::GetString("general.useragent.override");
1918 :
1919 0 : if (override) {
1920 0 : aUserAgent = override;
1921 0 : return NS_OK;
1922 : }
1923 : }
1924 :
1925 : nsresult rv;
1926 : nsCOMPtr<nsIHttpProtocolHandler>
1927 0 : service(do_GetService(NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX "http", &rv));
1928 0 : if (NS_WARN_IF(NS_FAILED(rv))) {
1929 0 : return rv;
1930 : }
1931 :
1932 0 : nsAutoCString ua;
1933 0 : rv = service->GetUserAgent(ua);
1934 0 : if (NS_WARN_IF(NS_FAILED(rv))) {
1935 0 : return rv;
1936 : }
1937 :
1938 0 : CopyASCIItoUTF16(ua, aUserAgent);
1939 :
1940 : // When the caller is content, we will always return spoofed userAgent and
1941 : // ignore the User-Agent header from the document channel when
1942 : // 'privacy.resistFingerprinting' is true.
1943 0 : if (!aWindow ||
1944 0 : (nsContentUtils::ShouldResistFingerprinting() && !aIsCallerChrome)) {
1945 0 : return NS_OK;
1946 : }
1947 :
1948 : // Copy the User-Agent header from the document channel which has already been
1949 : // subject to UA overrides.
1950 0 : nsCOMPtr<nsIDocument> doc = aWindow->GetExtantDoc();
1951 0 : if (!doc) {
1952 0 : return NS_OK;
1953 : }
1954 : nsCOMPtr<nsIHttpChannel> httpChannel =
1955 0 : do_QueryInterface(doc->GetChannel());
1956 0 : if (httpChannel) {
1957 0 : nsAutoCString userAgent;
1958 0 : rv = httpChannel->GetRequestHeader(NS_LITERAL_CSTRING("User-Agent"),
1959 0 : userAgent);
1960 0 : if (NS_WARN_IF(NS_FAILED(rv))) {
1961 0 : return rv;
1962 : }
1963 0 : CopyASCIItoUTF16(userAgent, aUserAgent);
1964 : }
1965 0 : return NS_OK;
1966 : }
1967 :
1968 : static nsCString
1969 0 : RequestKeySystemAccessLogString(
1970 : const nsAString& aKeySystem,
1971 : const Sequence<MediaKeySystemConfiguration>& aConfigs,
1972 : bool aIsSecureContext)
1973 : {
1974 0 : nsCString str;
1975 0 : str.AppendPrintf("Navigator::RequestMediaKeySystemAccess(keySystem='%s' options=",
1976 0 : NS_ConvertUTF16toUTF8(aKeySystem).get());
1977 0 : str.Append(MediaKeySystemAccess::ToCString(aConfigs));
1978 0 : str.AppendLiteral(") secureContext=");
1979 0 : str.AppendInt(aIsSecureContext);
1980 0 : return str;
1981 : }
1982 :
1983 : already_AddRefed<Promise>
1984 0 : Navigator::RequestMediaKeySystemAccess(const nsAString& aKeySystem,
1985 : const Sequence<MediaKeySystemConfiguration>& aConfigs,
1986 : ErrorResult& aRv)
1987 : {
1988 0 : EME_LOG("%s",
1989 : RequestKeySystemAccessLogString(
1990 : aKeySystem, aConfigs, mWindow->IsSecureContext())
1991 : .get());
1992 :
1993 0 : Telemetry::Accumulate(Telemetry::MEDIA_EME_SECURE_CONTEXT,
1994 0 : mWindow->IsSecureContext());
1995 :
1996 0 : if (!mWindow->IsSecureContext()) {
1997 0 : nsIDocument* doc = mWindow->GetExtantDoc();
1998 0 : nsString uri;
1999 0 : if (doc) {
2000 0 : Unused << doc->GetDocumentURI(uri);
2001 : }
2002 0 : const char16_t* params[] = { uri.get() };
2003 0 : nsContentUtils::ReportToConsole(nsIScriptError::warningFlag,
2004 0 : NS_LITERAL_CSTRING("Media"),
2005 : doc,
2006 : nsContentUtils::eDOM_PROPERTIES,
2007 : "MediaEMEInsecureContextDeprecatedWarning",
2008 : params,
2009 0 : ArrayLength(params));
2010 : }
2011 :
2012 0 : nsCOMPtr<nsIGlobalObject> go = do_QueryInterface(mWindow);
2013 : RefPtr<DetailedPromise> promise =
2014 0 : DetailedPromise::Create(go, aRv,
2015 0 : NS_LITERAL_CSTRING("navigator.requestMediaKeySystemAccess"),
2016 : Telemetry::VIDEO_EME_REQUEST_SUCCESS_LATENCY_MS,
2017 0 : Telemetry::VIDEO_EME_REQUEST_FAILURE_LATENCY_MS);
2018 0 : if (aRv.Failed()) {
2019 0 : return nullptr;
2020 : }
2021 :
2022 0 : if (!mMediaKeySystemAccessManager) {
2023 0 : mMediaKeySystemAccessManager = new MediaKeySystemAccessManager(mWindow);
2024 : }
2025 :
2026 0 : mMediaKeySystemAccessManager->Request(promise, aKeySystem, aConfigs);
2027 0 : return promise.forget();
2028 : }
2029 :
2030 : Presentation*
2031 0 : Navigator::GetPresentation(ErrorResult& aRv)
2032 : {
2033 0 : if (!mPresentation) {
2034 0 : if (!mWindow) {
2035 0 : aRv.Throw(NS_ERROR_UNEXPECTED);
2036 0 : return nullptr;
2037 : }
2038 0 : mPresentation = Presentation::Create(mWindow);
2039 : }
2040 :
2041 0 : return mPresentation;
2042 : }
2043 :
2044 : CredentialsContainer*
2045 0 : Navigator::Credentials()
2046 : {
2047 0 : if (!mCredentials) {
2048 0 : mCredentials = new CredentialsContainer(GetWindow());
2049 : }
2050 0 : return mCredentials;
2051 : }
2052 :
2053 : } // namespace dom
2054 : } // namespace mozilla
|