Coverage Report

Created: 2018-09-25 14:53

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