Line data Source code
1 : /* This Source Code Form is subject to the terms of the Mozilla Public
2 : * License, v. 2.0. If a copy of the MPL was not distributed with this
3 : * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4 :
5 : #include "ScreenOrientation.h"
6 : #include "nsIDeviceSensors.h"
7 : #include "nsIDocShell.h"
8 : #include "nsIDocument.h"
9 : #include "nsGlobalWindow.h"
10 : #include "nsSandboxFlags.h"
11 : #include "nsScreen.h"
12 :
13 : #include "mozilla/DOMEventTargetHelper.h"
14 : #include "mozilla/Hal.h"
15 : #include "mozilla/Preferences.h"
16 :
17 : #include "mozilla/dom/Promise.h"
18 : #include "nsContentUtils.h"
19 :
20 : using namespace mozilla;
21 : using namespace mozilla::dom;
22 :
23 0 : NS_IMPL_CYCLE_COLLECTION_INHERITED(ScreenOrientation,
24 : DOMEventTargetHelper,
25 : mScreen);
26 :
27 1 : NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(ScreenOrientation)
28 0 : NS_INTERFACE_MAP_END_INHERITING(DOMEventTargetHelper)
29 :
30 1 : NS_IMPL_ADDREF_INHERITED(ScreenOrientation, DOMEventTargetHelper)
31 0 : NS_IMPL_RELEASE_INHERITED(ScreenOrientation, DOMEventTargetHelper)
32 :
33 : static OrientationType
34 1 : InternalOrientationToType(ScreenOrientationInternal aOrientation)
35 : {
36 1 : switch (aOrientation) {
37 : case eScreenOrientation_PortraitPrimary:
38 0 : return OrientationType::Portrait_primary;
39 : case eScreenOrientation_PortraitSecondary:
40 0 : return OrientationType::Portrait_secondary;
41 : case eScreenOrientation_LandscapePrimary:
42 1 : return OrientationType::Landscape_primary;
43 : case eScreenOrientation_LandscapeSecondary:
44 0 : return OrientationType::Landscape_secondary;
45 : default:
46 0 : MOZ_CRASH("Bad aOrientation value");
47 : }
48 : }
49 :
50 : static ScreenOrientationInternal
51 0 : OrientationTypeToInternal(OrientationType aOrientation)
52 : {
53 0 : switch (aOrientation) {
54 : case OrientationType::Portrait_primary:
55 0 : return eScreenOrientation_PortraitPrimary;
56 : case OrientationType::Portrait_secondary:
57 0 : return eScreenOrientation_PortraitSecondary;
58 : case OrientationType::Landscape_primary:
59 0 : return eScreenOrientation_LandscapePrimary;
60 : case OrientationType::Landscape_secondary:
61 0 : return eScreenOrientation_LandscapeSecondary;
62 : default:
63 0 : MOZ_CRASH("Bad aOrientation value");
64 : }
65 : }
66 :
67 1 : ScreenOrientation::ScreenOrientation(nsPIDOMWindowInner* aWindow, nsScreen* aScreen)
68 1 : : DOMEventTargetHelper(aWindow), mScreen(aScreen)
69 : {
70 1 : MOZ_ASSERT(aWindow);
71 1 : MOZ_ASSERT(aScreen);
72 :
73 1 : hal::RegisterScreenConfigurationObserver(this);
74 :
75 2 : hal::ScreenConfiguration config;
76 1 : hal::GetCurrentScreenConfiguration(&config);
77 1 : mType = InternalOrientationToType(config.orientation());
78 1 : mAngle = config.angle();
79 :
80 1 : nsIDocument* doc = GetResponsibleDocument();
81 1 : if (doc) {
82 1 : doc->SetCurrentOrientation(mType, mAngle);
83 : }
84 1 : }
85 :
86 0 : ScreenOrientation::~ScreenOrientation()
87 : {
88 0 : hal::UnregisterScreenConfigurationObserver(this);
89 0 : MOZ_ASSERT(!mFullScreenListener);
90 0 : }
91 :
92 : class ScreenOrientation::FullScreenEventListener final : public nsIDOMEventListener
93 : {
94 0 : ~FullScreenEventListener() {}
95 : public:
96 0 : FullScreenEventListener() {}
97 :
98 : NS_DECL_ISUPPORTS
99 : NS_DECL_NSIDOMEVENTLISTENER
100 : };
101 :
102 : class ScreenOrientation::VisibleEventListener final : public nsIDOMEventListener
103 : {
104 0 : ~VisibleEventListener() {}
105 : public:
106 0 : VisibleEventListener() {}
107 :
108 : NS_DECL_ISUPPORTS
109 : NS_DECL_NSIDOMEVENTLISTENER
110 : };
111 :
112 : class ScreenOrientation::LockOrientationTask final : public nsIRunnable
113 : {
114 : ~LockOrientationTask();
115 : public:
116 : NS_DECL_ISUPPORTS
117 : NS_DECL_NSIRUNNABLE
118 :
119 : LockOrientationTask(ScreenOrientation* aScreenOrientation,
120 : Promise* aPromise,
121 : ScreenOrientationInternal aOrientationLock,
122 : nsIDocument* aDocument,
123 : bool aIsFullScreen);
124 : protected:
125 : bool OrientationLockContains(OrientationType aOrientationType);
126 :
127 : RefPtr<ScreenOrientation> mScreenOrientation;
128 : RefPtr<Promise> mPromise;
129 : ScreenOrientationInternal mOrientationLock;
130 : nsCOMPtr<nsIDocument> mDocument;
131 : bool mIsFullScreen;
132 : };
133 :
134 0 : NS_IMPL_ISUPPORTS(ScreenOrientation::LockOrientationTask, nsIRunnable)
135 :
136 0 : ScreenOrientation::LockOrientationTask::LockOrientationTask(
137 : ScreenOrientation* aScreenOrientation, Promise* aPromise,
138 : ScreenOrientationInternal aOrientationLock,
139 0 : nsIDocument* aDocument, bool aIsFullScreen)
140 : : mScreenOrientation(aScreenOrientation), mPromise(aPromise),
141 : mOrientationLock(aOrientationLock), mDocument(aDocument),
142 0 : mIsFullScreen(aIsFullScreen)
143 : {
144 0 : MOZ_ASSERT(aScreenOrientation);
145 0 : MOZ_ASSERT(aPromise);
146 0 : MOZ_ASSERT(aDocument);
147 0 : }
148 :
149 0 : ScreenOrientation::LockOrientationTask::~LockOrientationTask()
150 : {
151 0 : }
152 :
153 : bool
154 0 : ScreenOrientation::LockOrientationTask::OrientationLockContains(
155 : OrientationType aOrientationType)
156 : {
157 0 : return mOrientationLock & OrientationTypeToInternal(aOrientationType);
158 : }
159 :
160 : NS_IMETHODIMP
161 0 : ScreenOrientation::LockOrientationTask::Run()
162 : {
163 : // Step to lock the orientation as defined in the spec.
164 :
165 0 : if (mDocument->GetOrientationPendingPromise() != mPromise) {
166 : // The document's pending promise is not associated with this task
167 : // to lock orientation. There has since been another request to
168 : // lock orientation, thus we don't need to do anything. Old promise
169 : // should be been rejected.
170 0 : return NS_OK;
171 : }
172 :
173 0 : if (mDocument->Hidden()) {
174 : // Active orientation lock is not the document's orientation lock.
175 0 : mPromise->MaybeResolveWithUndefined();
176 0 : mDocument->SetOrientationPendingPromise(nullptr);
177 0 : return NS_OK;
178 : }
179 :
180 0 : if (mOrientationLock == eScreenOrientation_None) {
181 0 : mScreenOrientation->UnlockDeviceOrientation();
182 0 : mPromise->MaybeResolveWithUndefined();
183 0 : mDocument->SetOrientationPendingPromise(nullptr);
184 0 : return NS_OK;
185 : }
186 :
187 0 : ErrorResult rv;
188 0 : bool result = mScreenOrientation->LockDeviceOrientation(mOrientationLock,
189 0 : mIsFullScreen, rv);
190 0 : if (NS_WARN_IF(rv.Failed())) {
191 0 : return rv.StealNSResult();
192 : }
193 :
194 0 : if (NS_WARN_IF(!result)) {
195 0 : mPromise->MaybeReject(NS_ERROR_UNEXPECTED);
196 0 : mDocument->SetOrientationPendingPromise(nullptr);
197 0 : return NS_OK;
198 : }
199 :
200 0 : if (OrientationLockContains(mDocument->CurrentOrientationType()) ||
201 0 : (mOrientationLock == eScreenOrientation_Default &&
202 0 : mDocument->CurrentOrientationAngle() == 0)) {
203 : // Orientation lock will not cause an orientation change.
204 0 : mPromise->MaybeResolveWithUndefined();
205 0 : mDocument->SetOrientationPendingPromise(nullptr);
206 : }
207 :
208 0 : return NS_OK;
209 : }
210 :
211 : already_AddRefed<Promise>
212 0 : ScreenOrientation::Lock(OrientationLockType aOrientation, ErrorResult& aRv)
213 : {
214 0 : ScreenOrientationInternal orientation = eScreenOrientation_None;
215 :
216 0 : switch (aOrientation) {
217 : case OrientationLockType::Any:
218 0 : orientation = eScreenOrientation_PortraitPrimary |
219 : eScreenOrientation_PortraitSecondary |
220 : eScreenOrientation_LandscapePrimary |
221 : eScreenOrientation_LandscapeSecondary;
222 0 : break;
223 : case OrientationLockType::Natural:
224 0 : orientation |= eScreenOrientation_Default;
225 0 : break;
226 : case OrientationLockType::Landscape:
227 0 : orientation = eScreenOrientation_LandscapePrimary |
228 : eScreenOrientation_LandscapeSecondary;
229 0 : break;
230 : case OrientationLockType::Portrait:
231 0 : orientation = eScreenOrientation_PortraitPrimary |
232 : eScreenOrientation_PortraitSecondary;
233 0 : break;
234 : case OrientationLockType::Portrait_primary:
235 0 : orientation = eScreenOrientation_PortraitPrimary;
236 0 : break;
237 : case OrientationLockType::Portrait_secondary:
238 0 : orientation = eScreenOrientation_PortraitSecondary;
239 0 : break;
240 : case OrientationLockType::Landscape_primary:
241 0 : orientation = eScreenOrientation_LandscapePrimary;
242 0 : break;
243 : case OrientationLockType::Landscape_secondary:
244 0 : orientation = eScreenOrientation_LandscapeSecondary;
245 0 : break;
246 : default:
247 0 : NS_WARNING("Unexpected orientation type");
248 0 : aRv.Throw(NS_ERROR_UNEXPECTED);
249 0 : return nullptr;
250 : }
251 :
252 0 : return LockInternal(orientation, aRv);
253 : }
254 :
255 : static inline void
256 : AbortOrientationPromises(nsIDocShell* aDocShell)
257 : {
258 : MOZ_ASSERT(aDocShell);
259 :
260 : nsIDocument* doc = aDocShell->GetDocument();
261 : if (doc) {
262 : Promise* promise = doc->GetOrientationPendingPromise();
263 : if (promise) {
264 : promise->MaybeReject(NS_ERROR_DOM_ABORT_ERR);
265 : doc->SetOrientationPendingPromise(nullptr);
266 : }
267 : }
268 :
269 : int32_t childCount;
270 : aDocShell->GetChildCount(&childCount);
271 : for (int32_t i = 0; i < childCount; i++) {
272 : nsCOMPtr<nsIDocShellTreeItem> child;
273 : if (NS_SUCCEEDED(aDocShell->GetChildAt(i, getter_AddRefs(child)))) {
274 : nsCOMPtr<nsIDocShell> childShell(do_QueryInterface(child));
275 : if (childShell) {
276 : AbortOrientationPromises(childShell);
277 : }
278 : }
279 : }
280 : }
281 :
282 : already_AddRefed<Promise>
283 0 : ScreenOrientation::LockInternal(ScreenOrientationInternal aOrientation, ErrorResult& aRv)
284 : {
285 : // Steps to apply an orientation lock as defined in spec.
286 :
287 0 : nsIDocument* doc = GetResponsibleDocument();
288 0 : if (NS_WARN_IF(!doc)) {
289 0 : aRv.Throw(NS_ERROR_UNEXPECTED);
290 0 : return nullptr;
291 : }
292 :
293 0 : nsCOMPtr<nsPIDOMWindowInner> owner = GetOwner();
294 0 : if (NS_WARN_IF(!owner)) {
295 0 : aRv.Throw(NS_ERROR_UNEXPECTED);
296 0 : return nullptr;
297 : }
298 :
299 0 : nsCOMPtr<nsIDocShell> docShell = owner->GetDocShell();
300 0 : if (NS_WARN_IF(!docShell)) {
301 0 : aRv.Throw(NS_ERROR_UNEXPECTED);
302 0 : return nullptr;
303 : }
304 :
305 0 : nsCOMPtr<nsIGlobalObject> go = do_QueryInterface(owner);
306 0 : MOZ_ASSERT(go);
307 0 : RefPtr<Promise> p = Promise::Create(go, aRv);
308 0 : if (NS_WARN_IF(aRv.Failed())) {
309 0 : return nullptr;
310 : }
311 :
312 : #if !defined(MOZ_WIDGET_ANDROID) && !defined(MOZ_WIDGET_GONK)
313 : // User agent does not support locking the screen orientation.
314 0 : p->MaybeReject(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
315 0 : return p.forget();
316 : #else
317 : LockPermission perm = GetLockOrientationPermission(true);
318 : if (perm == LOCK_DENIED) {
319 : p->MaybeReject(NS_ERROR_DOM_SECURITY_ERR);
320 : return p.forget();
321 : }
322 :
323 : nsCOMPtr<nsIDocShellTreeItem> root;
324 : docShell->GetSameTypeRootTreeItem(getter_AddRefs(root));
325 : nsCOMPtr<nsIDocShell> rootShell(do_QueryInterface(root));
326 : if (!rootShell) {
327 : aRv.Throw(NS_ERROR_UNEXPECTED);
328 : return nullptr;
329 : }
330 :
331 : rootShell->SetOrientationLock(aOrientation);
332 : AbortOrientationPromises(rootShell);
333 :
334 : doc->SetOrientationPendingPromise(p);
335 :
336 : nsCOMPtr<nsIRunnable> lockOrientationTask =
337 : new LockOrientationTask(this, p, aOrientation, doc,
338 : perm == FULLSCREEN_LOCK_ALLOWED);
339 : aRv = NS_DispatchToMainThread(lockOrientationTask);
340 : if (NS_WARN_IF(aRv.Failed())) {
341 : return nullptr;
342 : }
343 :
344 : return p.forget();
345 : #endif
346 : }
347 :
348 : bool
349 0 : ScreenOrientation::LockDeviceOrientation(ScreenOrientationInternal aOrientation,
350 : bool aIsFullScreen, ErrorResult& aRv)
351 : {
352 0 : if (!GetOwner()) {
353 0 : aRv.Throw(NS_ERROR_UNEXPECTED);
354 0 : return false;
355 : }
356 :
357 0 : nsCOMPtr<EventTarget> target = do_QueryInterface(GetOwner()->GetDoc());
358 : // We need to register a listener so we learn when we leave full-screen
359 : // and when we will have to unlock the screen.
360 : // This needs to be done before LockScreenOrientation call to make sure
361 : // the locking can be unlocked.
362 0 : if (aIsFullScreen && !target) {
363 0 : return false;
364 : }
365 :
366 0 : if (NS_WARN_IF(!hal::LockScreenOrientation(aOrientation))) {
367 0 : return false;
368 : }
369 :
370 : // We are fullscreen and lock has been accepted.
371 0 : if (aIsFullScreen) {
372 0 : if (!mFullScreenListener) {
373 0 : mFullScreenListener = new FullScreenEventListener();
374 : }
375 :
376 0 : aRv = target->AddSystemEventListener(NS_LITERAL_STRING("fullscreenchange"),
377 0 : mFullScreenListener, /* useCapture = */ true);
378 0 : if (NS_WARN_IF(aRv.Failed())) {
379 0 : return false;
380 : }
381 : }
382 :
383 0 : return true;
384 : }
385 :
386 : void
387 0 : ScreenOrientation::Unlock(ErrorResult& aRv)
388 : {
389 0 : RefPtr<Promise> p = LockInternal(eScreenOrientation_None, aRv);
390 0 : }
391 :
392 : void
393 0 : ScreenOrientation::UnlockDeviceOrientation()
394 : {
395 0 : hal::UnlockScreenOrientation();
396 :
397 0 : if (!mFullScreenListener || !GetOwner()) {
398 0 : mFullScreenListener = nullptr;
399 0 : return;
400 : }
401 :
402 : // Remove event listener in case of fullscreen lock.
403 0 : nsCOMPtr<EventTarget> target = do_QueryInterface(GetOwner()->GetDoc());
404 0 : if (target) {
405 : DebugOnly<nsresult> rv =
406 0 : target->RemoveSystemEventListener(NS_LITERAL_STRING("fullscreenchange"),
407 : mFullScreenListener,
408 0 : /* useCapture */ true);
409 0 : NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), "RemoveSystemEventListener failed");
410 : }
411 :
412 0 : mFullScreenListener = nullptr;
413 : }
414 :
415 : OrientationType
416 0 : ScreenOrientation::DeviceType(CallerType aCallerType) const
417 : {
418 0 : return nsContentUtils::ResistFingerprinting(aCallerType) ?
419 0 : OrientationType::Landscape_primary : mType;
420 : }
421 :
422 : uint16_t
423 0 : ScreenOrientation::DeviceAngle(CallerType aCallerType) const
424 : {
425 0 : return nsContentUtils::ResistFingerprinting(aCallerType) ? 0 : mAngle;
426 : }
427 :
428 : OrientationType
429 0 : ScreenOrientation::GetType(CallerType aCallerType, ErrorResult& aRv) const
430 : {
431 0 : if (nsContentUtils::ResistFingerprinting(aCallerType)) {
432 0 : return OrientationType::Landscape_primary;
433 : }
434 :
435 0 : nsIDocument* doc = GetResponsibleDocument();
436 0 : if (!doc) {
437 0 : aRv.Throw(NS_ERROR_UNEXPECTED);
438 0 : return OrientationType::Portrait_primary;
439 : }
440 :
441 0 : return doc->CurrentOrientationType();
442 : }
443 :
444 : uint16_t
445 0 : ScreenOrientation::GetAngle(CallerType aCallerType, ErrorResult& aRv) const
446 : {
447 0 : if (nsContentUtils::ResistFingerprinting(aCallerType)) {
448 0 : return 0;
449 : }
450 :
451 0 : nsIDocument* doc = GetResponsibleDocument();
452 0 : if (!doc) {
453 0 : aRv.Throw(NS_ERROR_UNEXPECTED);
454 0 : return 0;
455 : }
456 :
457 0 : return doc->CurrentOrientationAngle();
458 : }
459 :
460 : ScreenOrientation::LockPermission
461 0 : ScreenOrientation::GetLockOrientationPermission(bool aCheckSandbox) const
462 : {
463 0 : nsCOMPtr<nsPIDOMWindowInner> owner = GetOwner();
464 0 : if (!owner) {
465 0 : return LOCK_DENIED;
466 : }
467 :
468 : // Chrome can always lock the screen orientation.
469 0 : nsIDocShell* docShell = owner->GetDocShell();
470 0 : if (docShell && docShell->ItemType() == nsIDocShellTreeItem::typeChrome) {
471 0 : return LOCK_ALLOWED;
472 : }
473 :
474 0 : nsCOMPtr<nsIDocument> doc = owner->GetDoc();
475 0 : if (!doc || doc->Hidden()) {
476 0 : return LOCK_DENIED;
477 : }
478 :
479 : // Sandboxed without "allow-orientation-lock"
480 0 : if (aCheckSandbox && doc->GetSandboxFlags() & SANDBOXED_ORIENTATION_LOCK) {
481 0 : return LOCK_DENIED;
482 : }
483 :
484 0 : if (Preferences::GetBool("dom.screenorientation.testing.non_fullscreen_lock_allow",
485 : false)) {
486 0 : return LOCK_ALLOWED;
487 : }
488 :
489 : // Other content must be full-screen in order to lock orientation.
490 0 : return doc->Fullscreen() ? FULLSCREEN_LOCK_ALLOWED : LOCK_DENIED;
491 : }
492 :
493 : nsIDocument*
494 1 : ScreenOrientation::GetResponsibleDocument() const
495 : {
496 2 : nsCOMPtr<nsPIDOMWindowInner> owner = GetOwner();
497 1 : if (!owner) {
498 0 : return nullptr;
499 : }
500 :
501 1 : return owner->GetDoc();
502 : }
503 :
504 : void
505 0 : ScreenOrientation::Notify(const hal::ScreenConfiguration& aConfiguration)
506 : {
507 0 : if (ShouldResistFingerprinting()) {
508 0 : return;
509 : }
510 :
511 0 : nsIDocument* doc = GetResponsibleDocument();
512 0 : if (!doc) {
513 0 : return;
514 : }
515 :
516 0 : ScreenOrientationInternal orientation = aConfiguration.orientation();
517 0 : if (orientation != eScreenOrientation_PortraitPrimary &&
518 0 : orientation != eScreenOrientation_PortraitSecondary &&
519 0 : orientation != eScreenOrientation_LandscapePrimary &&
520 : orientation != eScreenOrientation_LandscapeSecondary) {
521 : // The platform may notify of some other values from
522 : // an orientation lock, but we only care about real
523 : // changes to screen orientation which result in one of
524 : // the values we care about.
525 0 : return;
526 : }
527 :
528 0 : OrientationType previousOrientation = mType;
529 0 : mAngle = aConfiguration.angle();
530 0 : mType = InternalOrientationToType(orientation);
531 :
532 0 : DebugOnly<nsresult> rv;
533 0 : if (mScreen && mType != previousOrientation) {
534 : // Use of mozorientationchange is deprecated.
535 0 : rv = mScreen->DispatchTrustedEvent(NS_LITERAL_STRING("mozorientationchange"));
536 0 : NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), "DispatchTrustedEvent failed");
537 : }
538 :
539 0 : if (doc->Hidden() && !mVisibleListener) {
540 0 : mVisibleListener = new VisibleEventListener();
541 0 : rv = doc->AddSystemEventListener(NS_LITERAL_STRING("visibilitychange"),
542 0 : mVisibleListener, /* useCapture = */ true);
543 0 : NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), "AddSystemEventListener failed");
544 0 : return;
545 : }
546 :
547 0 : if (mType != doc->CurrentOrientationType()) {
548 0 : doc->SetCurrentOrientation(mType, mAngle);
549 :
550 0 : Promise* pendingPromise = doc->GetOrientationPendingPromise();
551 0 : if (pendingPromise) {
552 0 : pendingPromise->MaybeResolveWithUndefined();
553 0 : doc->SetOrientationPendingPromise(nullptr);
554 : }
555 :
556 : nsCOMPtr<nsIRunnable> runnable =
557 0 : NewRunnableMethod("dom::ScreenOrientation::DispatchChangeEvent",
558 : this,
559 0 : &ScreenOrientation::DispatchChangeEvent);
560 0 : rv = NS_DispatchToMainThread(runnable);
561 0 : NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), "NS_DispatchToMainThread failed");
562 : }
563 : }
564 :
565 : void
566 0 : ScreenOrientation::UpdateActiveOrientationLock(ScreenOrientationInternal aOrientation)
567 : {
568 0 : if (aOrientation == eScreenOrientation_None) {
569 0 : hal::UnlockScreenOrientation();
570 : } else {
571 0 : DebugOnly<bool> ok = hal::LockScreenOrientation(aOrientation);
572 0 : NS_WARNING_ASSERTION(ok, "hal::LockScreenOrientation failed");
573 : }
574 0 : }
575 :
576 : void
577 0 : ScreenOrientation::DispatchChangeEvent()
578 : {
579 0 : DebugOnly<nsresult> rv = DispatchTrustedEvent(NS_LITERAL_STRING("change"));
580 0 : NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), "DispatchTrustedEvent failed");
581 0 : }
582 :
583 : JSObject*
584 0 : ScreenOrientation::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
585 : {
586 0 : return ScreenOrientationBinding::Wrap(aCx, this, aGivenProto);
587 : }
588 :
589 : bool
590 0 : ScreenOrientation::ShouldResistFingerprinting() const
591 : {
592 0 : bool resist = false;
593 0 : if (nsCOMPtr<nsPIDOMWindowInner> owner = GetOwner()) {
594 0 : resist = nsContentUtils::ShouldResistFingerprinting(owner->GetDocShell());
595 : }
596 0 : return resist;
597 : }
598 :
599 0 : NS_IMPL_ISUPPORTS(ScreenOrientation::VisibleEventListener, nsIDOMEventListener)
600 :
601 : NS_IMETHODIMP
602 0 : ScreenOrientation::VisibleEventListener::HandleEvent(nsIDOMEvent* aEvent)
603 : {
604 : // Document may have become visible, if the page is visible, run the steps
605 : // following the "now visible algorithm" as specified.
606 0 : nsCOMPtr<EventTarget> target = aEvent->InternalDOMEvent()->GetCurrentTarget();
607 0 : MOZ_ASSERT(target);
608 :
609 0 : nsCOMPtr<nsIDocument> doc = do_QueryInterface(target);
610 0 : if (!doc || doc->Hidden()) {
611 0 : return NS_OK;
612 : }
613 :
614 0 : auto* win = nsGlobalWindow::Cast(doc->GetInnerWindow());
615 0 : if (!win) {
616 0 : return NS_OK;
617 : }
618 :
619 0 : ErrorResult rv;
620 0 : nsScreen* screen = win->GetScreen(rv);
621 0 : if (NS_WARN_IF(rv.Failed())) {
622 0 : return rv.StealNSResult();
623 : }
624 :
625 0 : MOZ_ASSERT(screen);
626 0 : ScreenOrientation* orientation = screen->Orientation();
627 0 : MOZ_ASSERT(orientation);
628 :
629 0 : rv = target->RemoveSystemEventListener(NS_LITERAL_STRING("visibilitychange"),
630 0 : this, true);
631 0 : if (NS_WARN_IF(rv.Failed())) {
632 0 : return rv.StealNSResult();
633 : }
634 :
635 0 : if (doc->CurrentOrientationType() != orientation->DeviceType(CallerType::System)) {
636 0 : doc->SetCurrentOrientation(orientation->DeviceType(CallerType::System),
637 0 : orientation->DeviceAngle(CallerType::System));
638 :
639 0 : Promise* pendingPromise = doc->GetOrientationPendingPromise();
640 0 : if (pendingPromise) {
641 0 : pendingPromise->MaybeResolveWithUndefined();
642 0 : doc->SetOrientationPendingPromise(nullptr);
643 : }
644 :
645 : nsCOMPtr<nsIRunnable> runnable =
646 0 : NewRunnableMethod("dom::ScreenOrientation::DispatchChangeEvent",
647 : orientation,
648 0 : &ScreenOrientation::DispatchChangeEvent);
649 0 : rv = NS_DispatchToMainThread(runnable);
650 0 : if (NS_WARN_IF(rv.Failed())) {
651 0 : return rv.StealNSResult();
652 : }
653 : }
654 :
655 0 : return NS_OK;
656 : }
657 :
658 0 : NS_IMPL_ISUPPORTS(ScreenOrientation::FullScreenEventListener, nsIDOMEventListener)
659 :
660 : NS_IMETHODIMP
661 0 : ScreenOrientation::FullScreenEventListener::HandleEvent(nsIDOMEvent* aEvent)
662 : {
663 : #ifdef DEBUG
664 0 : nsAutoString eventType;
665 0 : aEvent->GetType(eventType);
666 :
667 0 : MOZ_ASSERT(eventType.EqualsLiteral("fullscreenchange"));
668 : #endif
669 :
670 0 : nsCOMPtr<EventTarget> target = aEvent->InternalDOMEvent()->GetCurrentTarget();
671 0 : MOZ_ASSERT(target);
672 :
673 0 : nsCOMPtr<nsIDocument> doc = do_QueryInterface(target);
674 0 : MOZ_ASSERT(doc);
675 :
676 : // We have to make sure that the event we got is the event sent when
677 : // fullscreen is disabled because we could get one when fullscreen
678 : // got enabled if the lock call is done at the same moment.
679 0 : if (doc->Fullscreen()) {
680 0 : return NS_OK;
681 : }
682 :
683 0 : hal::UnlockScreenOrientation();
684 :
685 0 : nsresult rv = target->RemoveSystemEventListener(NS_LITERAL_STRING("fullscreenchange"),
686 0 : this, true);
687 0 : NS_ENSURE_SUCCESS(rv, rv);
688 :
689 0 : return NS_OK;
690 : }
|