mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-24 05:11:16 +00:00
Bug 1131470 - Part 3: Implement ScreenOrientation interface. r=baku
--HG-- extra : rebase_source : 115753be382c7694c775915d5944ae2dabd9d0c3
This commit is contained in:
parent
6d6411c090
commit
326cceef61
628
dom/base/ScreenOrientation.cpp
Normal file
628
dom/base/ScreenOrientation.cpp
Normal file
@ -0,0 +1,628 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "ScreenOrientation.h"
|
||||
#include "nsIDeviceSensors.h"
|
||||
#include "nsScreen.h"
|
||||
|
||||
using namespace mozilla::dom;
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_INHERITED(ScreenOrientation,
|
||||
DOMEventTargetHelper,
|
||||
mScreen);
|
||||
|
||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(ScreenOrientation)
|
||||
NS_INTERFACE_MAP_END_INHERITING(DOMEventTargetHelper)
|
||||
|
||||
NS_IMPL_ADDREF_INHERITED(ScreenOrientation, DOMEventTargetHelper)
|
||||
NS_IMPL_RELEASE_INHERITED(ScreenOrientation, DOMEventTargetHelper)
|
||||
|
||||
static OrientationType
|
||||
InternalOrientationToType(ScreenOrientationInternal aOrientation)
|
||||
{
|
||||
switch (aOrientation) {
|
||||
case eScreenOrientation_PortraitPrimary:
|
||||
return OrientationType::Portrait_primary;
|
||||
case eScreenOrientation_PortraitSecondary:
|
||||
return OrientationType::Portrait_secondary;
|
||||
case eScreenOrientation_LandscapePrimary:
|
||||
return OrientationType::Landscape_primary;
|
||||
case eScreenOrientation_LandscapeSecondary:
|
||||
return OrientationType::Landscape_secondary;
|
||||
default:
|
||||
MOZ_CRASH("Bad aOrientation value");
|
||||
}
|
||||
}
|
||||
|
||||
static ScreenOrientationInternal
|
||||
OrientationTypeToInternal(OrientationType aOrientation)
|
||||
{
|
||||
switch (aOrientation) {
|
||||
case OrientationType::Portrait_primary:
|
||||
return eScreenOrientation_PortraitPrimary;
|
||||
case OrientationType::Portrait_secondary:
|
||||
return eScreenOrientation_PortraitSecondary;
|
||||
case OrientationType::Landscape_primary:
|
||||
return eScreenOrientation_LandscapePrimary;
|
||||
case OrientationType::Landscape_secondary:
|
||||
return eScreenOrientation_LandscapeSecondary;
|
||||
default:
|
||||
MOZ_CRASH("Bad aOrientation value");
|
||||
}
|
||||
}
|
||||
|
||||
ScreenOrientation::ScreenOrientation(nsPIDOMWindow* aWindow, nsScreen* aScreen)
|
||||
: DOMEventTargetHelper(aWindow), mScreen(aScreen)
|
||||
{
|
||||
MOZ_ASSERT(aWindow);
|
||||
MOZ_ASSERT(aScreen);
|
||||
|
||||
hal::RegisterScreenConfigurationObserver(this);
|
||||
|
||||
hal::ScreenConfiguration config;
|
||||
hal::GetCurrentScreenConfiguration(&config);
|
||||
mType = InternalOrientationToType(config.orientation());
|
||||
mAngle = config.angle();
|
||||
|
||||
nsIDocument* doc = GetResponsibleDocument();
|
||||
if (doc) {
|
||||
doc->SetCurrentOrientation(mType, mAngle);
|
||||
}
|
||||
}
|
||||
|
||||
ScreenOrientation::~ScreenOrientation()
|
||||
{
|
||||
hal::UnregisterScreenConfigurationObserver(this);
|
||||
MOZ_ASSERT(!mFullScreenListener);
|
||||
}
|
||||
|
||||
class ScreenOrientation::FullScreenEventListener final : public nsIDOMEventListener
|
||||
{
|
||||
~FullScreenEventListener() {}
|
||||
public:
|
||||
FullScreenEventListener() {}
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIDOMEVENTLISTENER
|
||||
};
|
||||
|
||||
class ScreenOrientation::VisibleEventListener final : public nsIDOMEventListener
|
||||
{
|
||||
~VisibleEventListener() {}
|
||||
public:
|
||||
VisibleEventListener() {}
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIDOMEVENTLISTENER
|
||||
};
|
||||
|
||||
class ScreenOrientation::LockOrientationTask final : public nsIRunnable
|
||||
{
|
||||
~LockOrientationTask();
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIRUNNABLE
|
||||
|
||||
LockOrientationTask(ScreenOrientation* aScreenOrientation,
|
||||
Promise* aPromise,
|
||||
ScreenOrientationInternal aOrientationLock,
|
||||
nsIDocument* aDocument,
|
||||
bool aIsFullScreen);
|
||||
protected:
|
||||
bool OrientationLockContains(OrientationType aOrientationType);
|
||||
|
||||
nsRefPtr<ScreenOrientation> mScreenOrientation;
|
||||
nsRefPtr<Promise> mPromise;
|
||||
ScreenOrientationInternal mOrientationLock;
|
||||
nsCOMPtr<nsIDocument> mDocument;
|
||||
bool mIsFullScreen;
|
||||
};
|
||||
|
||||
NS_IMPL_ISUPPORTS(ScreenOrientation::LockOrientationTask, nsIRunnable)
|
||||
|
||||
ScreenOrientation::LockOrientationTask::LockOrientationTask(
|
||||
ScreenOrientation* aScreenOrientation, Promise* aPromise,
|
||||
ScreenOrientationInternal aOrientationLock,
|
||||
nsIDocument* aDocument, bool aIsFullScreen)
|
||||
: mScreenOrientation(aScreenOrientation), mPromise(aPromise),
|
||||
mOrientationLock(aOrientationLock), mDocument(aDocument),
|
||||
mIsFullScreen(aIsFullScreen)
|
||||
{
|
||||
MOZ_ASSERT(aScreenOrientation);
|
||||
MOZ_ASSERT(aPromise);
|
||||
MOZ_ASSERT(aDocument);
|
||||
}
|
||||
|
||||
ScreenOrientation::LockOrientationTask::~LockOrientationTask()
|
||||
{
|
||||
}
|
||||
|
||||
bool
|
||||
ScreenOrientation::LockOrientationTask::OrientationLockContains(
|
||||
OrientationType aOrientationType)
|
||||
{
|
||||
return mOrientationLock & OrientationTypeToInternal(aOrientationType);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
ScreenOrientation::LockOrientationTask::Run()
|
||||
{
|
||||
// Step to lock the orientation as defined in the spec.
|
||||
|
||||
if (mDocument->GetOrientationPendingPromise() != mPromise) {
|
||||
// The document's pending promise is not associated with this task
|
||||
// to lock orientation. There has since been another request to
|
||||
// lock orientation, thus we don't need to do anything. Old promise
|
||||
// should be been rejected.
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (mDocument->Hidden()) {
|
||||
// Active orientation lock is not the document's orientation lock.
|
||||
mPromise->MaybeResolve(JS::UndefinedHandleValue);
|
||||
mDocument->SetOrientationPendingPromise(nullptr);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (mOrientationLock == eScreenOrientation_None) {
|
||||
mScreenOrientation->UnlockDeviceOrientation();
|
||||
mPromise->MaybeResolve(JS::UndefinedHandleValue);
|
||||
mDocument->SetOrientationPendingPromise(nullptr);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
ErrorResult rv;
|
||||
bool result = mScreenOrientation->LockDeviceOrientation(mOrientationLock,
|
||||
mIsFullScreen, rv);
|
||||
if (NS_WARN_IF(rv.Failed())) {
|
||||
return rv.StealNSResult();
|
||||
}
|
||||
|
||||
if (NS_WARN_IF(!result)) {
|
||||
mPromise->MaybeReject(NS_ERROR_UNEXPECTED);
|
||||
mDocument->SetOrientationPendingPromise(nullptr);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (OrientationLockContains(mDocument->CurrentOrientationType()) ||
|
||||
(mOrientationLock == eScreenOrientation_Default &&
|
||||
mDocument->CurrentOrientationAngle() == 0)) {
|
||||
// Orientation lock will not cause an orientation change.
|
||||
mPromise->MaybeResolve(JS::UndefinedHandleValue);
|
||||
mDocument->SetOrientationPendingPromise(nullptr);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
already_AddRefed<Promise>
|
||||
ScreenOrientation::Lock(OrientationLockType aOrientation, ErrorResult& aRv)
|
||||
{
|
||||
ScreenOrientationInternal orientation = eScreenOrientation_None;
|
||||
|
||||
switch (aOrientation) {
|
||||
case OrientationLockType::Any:
|
||||
orientation = eScreenOrientation_PortraitPrimary |
|
||||
eScreenOrientation_PortraitSecondary |
|
||||
eScreenOrientation_LandscapePrimary |
|
||||
eScreenOrientation_LandscapeSecondary;
|
||||
break;
|
||||
case OrientationLockType::Natural:
|
||||
orientation |= eScreenOrientation_Default;
|
||||
break;
|
||||
case OrientationLockType::Landscape:
|
||||
orientation = eScreenOrientation_LandscapePrimary |
|
||||
eScreenOrientation_LandscapeSecondary;
|
||||
break;
|
||||
case OrientationLockType::Portrait:
|
||||
orientation = eScreenOrientation_PortraitPrimary |
|
||||
eScreenOrientation_PortraitSecondary;
|
||||
break;
|
||||
case OrientationLockType::Portrait_primary:
|
||||
orientation = eScreenOrientation_PortraitPrimary;
|
||||
break;
|
||||
case OrientationLockType::Portrait_secondary:
|
||||
orientation = eScreenOrientation_PortraitSecondary;
|
||||
break;
|
||||
case OrientationLockType::Landscape_primary:
|
||||
orientation = eScreenOrientation_LandscapePrimary;
|
||||
break;
|
||||
case OrientationLockType::Landscape_secondary:
|
||||
orientation = eScreenOrientation_LandscapeSecondary;
|
||||
break;
|
||||
default:
|
||||
NS_WARNING("Unexpected orientation type");
|
||||
aRv.Throw(NS_ERROR_UNEXPECTED);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return LockInternal(orientation, aRv);
|
||||
}
|
||||
|
||||
static inline void
|
||||
AbortOrientationPromises(nsIDocShell* aDocShell)
|
||||
{
|
||||
MOZ_ASSERT(aDocShell);
|
||||
|
||||
nsIDocument* doc = aDocShell->GetDocument();
|
||||
if (doc) {
|
||||
Promise* promise = doc->GetOrientationPendingPromise();
|
||||
if (promise) {
|
||||
promise->MaybeReject(NS_ERROR_DOM_ABORT_ERR);
|
||||
doc->SetOrientationPendingPromise(nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
int32_t childCount;
|
||||
aDocShell->GetChildCount(&childCount);
|
||||
for (int32_t i = 0; i < childCount; i++) {
|
||||
nsCOMPtr<nsIDocShellTreeItem> child;
|
||||
if (NS_SUCCEEDED(aDocShell->GetChildAt(i, getter_AddRefs(child)))) {
|
||||
nsCOMPtr<nsIDocShell> childShell(do_QueryInterface(child));
|
||||
if (childShell) {
|
||||
AbortOrientationPromises(childShell);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
already_AddRefed<Promise>
|
||||
ScreenOrientation::LockInternal(ScreenOrientationInternal aOrientation, ErrorResult& aRv)
|
||||
{
|
||||
// Steps to apply an orientation lock as defined in spec.
|
||||
|
||||
nsIDocument* doc = GetResponsibleDocument();
|
||||
if (NS_WARN_IF(!doc)) {
|
||||
aRv.Throw(NS_ERROR_UNEXPECTED);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsPIDOMWindow> owner = GetOwner();
|
||||
if (NS_WARN_IF(!owner)) {
|
||||
aRv.Throw(NS_ERROR_UNEXPECTED);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIDocShell> docShell = owner->GetDocShell();
|
||||
if (NS_WARN_IF(!docShell)) {
|
||||
aRv.Throw(NS_ERROR_UNEXPECTED);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIGlobalObject> go = do_QueryInterface(owner);
|
||||
MOZ_ASSERT(go);
|
||||
nsRefPtr<Promise> p = Promise::Create(go, aRv);
|
||||
if (NS_WARN_IF(aRv.Failed())) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
#if !defined(MOZ_WIDGET_ANDROID) && !defined(MOZ_WIDGET_GONK)
|
||||
// User agent does not support locking the screen orientation.
|
||||
p->MaybeReject(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
|
||||
return p.forget();
|
||||
#else
|
||||
LockPermission perm = GetLockOrientationPermission();
|
||||
if (perm == LOCK_DENIED) {
|
||||
p->MaybeReject(NS_ERROR_DOM_SECURITY_ERR);
|
||||
return p.forget();
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIDocShellTreeItem> root;
|
||||
docShell->GetSameTypeRootTreeItem(getter_AddRefs(root));
|
||||
nsCOMPtr<nsIDocShell> rootShell(do_QueryInterface(root));
|
||||
if (!rootShell) {
|
||||
aRv.Throw(NS_ERROR_UNEXPECTED);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
AbortOrientationPromises(rootShell);
|
||||
|
||||
doc->SetOrientationPendingPromise(p);
|
||||
|
||||
nsCOMPtr<nsIRunnable> lockOrientationTask =
|
||||
new LockOrientationTask(this, p, aOrientation, doc,
|
||||
perm == FULLSCREEN_LOCK_ALLOWED);
|
||||
aRv = NS_DispatchToMainThread(lockOrientationTask);
|
||||
if (NS_WARN_IF(aRv.Failed())) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return p.forget();
|
||||
#endif
|
||||
}
|
||||
|
||||
bool
|
||||
ScreenOrientation::LockDeviceOrientation(ScreenOrientationInternal aOrientation,
|
||||
bool aIsFullScreen, ErrorResult& aRv)
|
||||
{
|
||||
nsCOMPtr<EventTarget> target = do_QueryInterface(GetOwner()->GetDoc());
|
||||
// We need to register a listener so we learn when we leave full-screen
|
||||
// and when we will have to unlock the screen.
|
||||
// This needs to be done before LockScreenOrientation call to make sure
|
||||
// the locking can be unlocked.
|
||||
if (aIsFullScreen && !target) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (NS_WARN_IF(!hal::LockScreenOrientation(aOrientation))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// We are fullscreen and lock has been accepted.
|
||||
if (aIsFullScreen && !mFullScreenListener) {
|
||||
mFullScreenListener = new FullScreenEventListener();
|
||||
aRv = target->AddSystemEventListener(NS_LITERAL_STRING("mozfullscreenchange"),
|
||||
mFullScreenListener, /* useCapture = */ true);
|
||||
if (NS_WARN_IF(aRv.Failed())) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
ScreenOrientation::Unlock(ErrorResult& aRv)
|
||||
{
|
||||
nsRefPtr<Promise> p = LockInternal(eScreenOrientation_None, aRv);
|
||||
}
|
||||
|
||||
void
|
||||
ScreenOrientation::UnlockDeviceOrientation()
|
||||
{
|
||||
hal::UnlockScreenOrientation();
|
||||
|
||||
if (!mFullScreenListener) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Remove event listener in case of fullscreen lock.
|
||||
nsCOMPtr<EventTarget> target = do_QueryInterface(GetOwner()->GetDoc());
|
||||
if (target) {
|
||||
nsresult rv = target->RemoveSystemEventListener(NS_LITERAL_STRING("mozfullscreenchange"),
|
||||
mFullScreenListener, /* useCapture */ true);
|
||||
NS_WARN_IF(NS_FAILED(rv));
|
||||
}
|
||||
|
||||
mFullScreenListener = nullptr;
|
||||
}
|
||||
|
||||
OrientationType
|
||||
ScreenOrientation::DeviceType() const
|
||||
{
|
||||
return mType;
|
||||
}
|
||||
|
||||
uint16_t
|
||||
ScreenOrientation::DeviceAngle() const
|
||||
{
|
||||
return mAngle;
|
||||
}
|
||||
|
||||
OrientationType
|
||||
ScreenOrientation::GetType(ErrorResult& aRv) const
|
||||
{
|
||||
nsIDocument* doc = GetResponsibleDocument();
|
||||
if (!doc) {
|
||||
aRv.Throw(NS_ERROR_UNEXPECTED);
|
||||
return OrientationType::Portrait_primary;
|
||||
}
|
||||
|
||||
return doc->CurrentOrientationType();
|
||||
}
|
||||
|
||||
uint16_t
|
||||
ScreenOrientation::GetAngle(ErrorResult& aRv) const
|
||||
{
|
||||
nsIDocument* doc = GetResponsibleDocument();
|
||||
if (!doc) {
|
||||
aRv.Throw(NS_ERROR_UNEXPECTED);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return doc->CurrentOrientationAngle();
|
||||
}
|
||||
|
||||
ScreenOrientation::LockPermission
|
||||
ScreenOrientation::GetLockOrientationPermission() const
|
||||
{
|
||||
nsCOMPtr<nsPIDOMWindow> owner = GetOwner();
|
||||
if (!owner) {
|
||||
return LOCK_DENIED;
|
||||
}
|
||||
|
||||
// Chrome can always lock the screen orientation.
|
||||
nsIDocShell* docShell = owner->GetDocShell();
|
||||
if (docShell && docShell->ItemType() == nsIDocShellTreeItem::typeChrome) {
|
||||
return LOCK_ALLOWED;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIDocument> doc = owner->GetDoc();
|
||||
if (!doc || doc->Hidden()) {
|
||||
return LOCK_DENIED;
|
||||
}
|
||||
|
||||
// Apps can always lock the screen orientation.
|
||||
if (doc->NodePrincipal()->GetAppStatus() >=
|
||||
nsIPrincipal::APP_STATUS_INSTALLED) {
|
||||
return LOCK_ALLOWED;
|
||||
}
|
||||
|
||||
if (Preferences::GetBool("dom.screenorientation.testing.non_fullscreen_lock_allow",
|
||||
false)) {
|
||||
return LOCK_ALLOWED;
|
||||
}
|
||||
|
||||
// Other content must be full-screen in order to lock orientation.
|
||||
return doc->MozFullScreen() ? FULLSCREEN_LOCK_ALLOWED : LOCK_DENIED;
|
||||
}
|
||||
|
||||
nsIDocument*
|
||||
ScreenOrientation::GetResponsibleDocument() const
|
||||
{
|
||||
nsCOMPtr<nsPIDOMWindow> owner = GetOwner();
|
||||
if (!owner) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return owner->GetDoc();
|
||||
}
|
||||
|
||||
void
|
||||
ScreenOrientation::Notify(const hal::ScreenConfiguration& aConfiguration)
|
||||
{
|
||||
nsIDocument* doc = GetResponsibleDocument();
|
||||
if (!doc) {
|
||||
return;
|
||||
}
|
||||
|
||||
ScreenOrientationInternal orientation = aConfiguration.orientation();
|
||||
if (orientation != eScreenOrientation_PortraitPrimary &&
|
||||
orientation != eScreenOrientation_PortraitSecondary &&
|
||||
orientation != eScreenOrientation_LandscapePrimary &&
|
||||
orientation != eScreenOrientation_LandscapeSecondary) {
|
||||
// The platform may notify of some other values from
|
||||
// an orientation lock, but we only care about real
|
||||
// changes to screen orientation which result in one of
|
||||
// the values we care about.
|
||||
return;
|
||||
}
|
||||
|
||||
OrientationType previousOrientation = mType;
|
||||
mAngle = aConfiguration.angle();
|
||||
mType = InternalOrientationToType(orientation);
|
||||
|
||||
nsresult rv;
|
||||
if (mScreen && mType != previousOrientation) {
|
||||
// Use of mozorientationchange is deprecated.
|
||||
rv = mScreen->DispatchTrustedEvent(NS_LITERAL_STRING("mozorientationchange"));
|
||||
NS_WARN_IF(NS_FAILED(rv));
|
||||
}
|
||||
|
||||
if (doc->Hidden() && !mVisibleListener) {
|
||||
mVisibleListener = new VisibleEventListener();
|
||||
rv = doc->AddSystemEventListener(NS_LITERAL_STRING("visibilitychange"),
|
||||
mVisibleListener, /* useCapture = */ true);
|
||||
NS_WARN_IF(NS_FAILED(rv));
|
||||
return;
|
||||
}
|
||||
|
||||
if (mType != doc->CurrentOrientationType()) {
|
||||
doc->SetCurrentOrientation(mType, mAngle);
|
||||
|
||||
Promise* pendingPromise = doc->GetOrientationPendingPromise();
|
||||
if (pendingPromise) {
|
||||
pendingPromise->MaybeResolve(JS::UndefinedHandleValue);
|
||||
doc->SetOrientationPendingPromise(nullptr);
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIRunnable> runnable = NS_NewRunnableMethod(this,
|
||||
&ScreenOrientation::DispatchChangeEvent);
|
||||
rv = NS_DispatchToMainThread(runnable);
|
||||
NS_WARN_IF(NS_FAILED(rv));
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ScreenOrientation::DispatchChangeEvent()
|
||||
{
|
||||
nsresult rv = DispatchTrustedEvent(NS_LITERAL_STRING("change"));
|
||||
NS_WARN_IF(NS_FAILED(rv));
|
||||
}
|
||||
|
||||
JSObject*
|
||||
ScreenOrientation::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
|
||||
{
|
||||
return ScreenOrientationBinding::Wrap(aCx, this, aGivenProto);
|
||||
}
|
||||
|
||||
NS_IMPL_ISUPPORTS(ScreenOrientation::VisibleEventListener, nsIDOMEventListener)
|
||||
|
||||
NS_IMETHODIMP
|
||||
ScreenOrientation::VisibleEventListener::HandleEvent(nsIDOMEvent* aEvent)
|
||||
{
|
||||
// Document may have become visible, if the page is visible, run the steps
|
||||
// following the "now visible algorithm" as specified.
|
||||
nsCOMPtr<EventTarget> target = aEvent->InternalDOMEvent()->GetCurrentTarget();
|
||||
MOZ_ASSERT(target);
|
||||
|
||||
nsCOMPtr<nsIDocument> doc = do_QueryInterface(target);
|
||||
if (!doc || doc->Hidden()) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsGlobalWindow* win = static_cast<nsGlobalWindow*>(doc->GetInnerWindow());
|
||||
if (!win) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
ErrorResult rv;
|
||||
nsScreen* screen = win->GetScreen(rv);
|
||||
if (NS_WARN_IF(rv.Failed())) {
|
||||
return rv.StealNSResult();
|
||||
}
|
||||
|
||||
MOZ_ASSERT(screen);
|
||||
ScreenOrientation* orientation = screen->Orientation();
|
||||
MOZ_ASSERT(orientation);
|
||||
|
||||
rv = target->RemoveSystemEventListener(NS_LITERAL_STRING("visibilitychange"),
|
||||
this, true);
|
||||
if (NS_WARN_IF(rv.Failed())) {
|
||||
return rv.StealNSResult();
|
||||
}
|
||||
|
||||
if (doc->CurrentOrientationType() != orientation->DeviceType()) {
|
||||
doc->SetCurrentOrientation(orientation->DeviceType(), orientation->DeviceAngle());
|
||||
|
||||
Promise* pendingPromise = doc->GetOrientationPendingPromise();
|
||||
if (pendingPromise) {
|
||||
pendingPromise->MaybeResolve(JS::UndefinedHandleValue);
|
||||
doc->SetOrientationPendingPromise(nullptr);
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIRunnable> runnable = NS_NewRunnableMethod(orientation,
|
||||
&ScreenOrientation::DispatchChangeEvent);
|
||||
rv = NS_DispatchToMainThread(runnable);
|
||||
if (NS_WARN_IF(rv.Failed())) {
|
||||
return rv.StealNSResult();
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMPL_ISUPPORTS(ScreenOrientation::FullScreenEventListener, nsIDOMEventListener)
|
||||
|
||||
NS_IMETHODIMP
|
||||
ScreenOrientation::FullScreenEventListener::HandleEvent(nsIDOMEvent* aEvent)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
nsAutoString eventType;
|
||||
aEvent->GetType(eventType);
|
||||
|
||||
MOZ_ASSERT(eventType.EqualsLiteral("mozfullscreenchange"));
|
||||
#endif
|
||||
|
||||
nsCOMPtr<EventTarget> target = aEvent->InternalDOMEvent()->GetCurrentTarget();
|
||||
MOZ_ASSERT(target);
|
||||
|
||||
nsCOMPtr<nsIDocument> doc = do_QueryInterface(target);
|
||||
MOZ_ASSERT(doc);
|
||||
|
||||
// We have to make sure that the event we got is the event sent when
|
||||
// fullscreen is disabled because we could get one when fullscreen
|
||||
// got enabled if the lock call is done at the same moment.
|
||||
if (doc->MozFullScreen()) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
hal::UnlockScreenOrientation();
|
||||
|
||||
nsresult rv = target->RemoveSystemEventListener(NS_LITERAL_STRING("mozfullscreenchange"),
|
||||
this, true);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return NS_OK;
|
||||
}
|
@ -7,9 +7,16 @@
|
||||
#ifndef mozilla_dom_ScreenOrientation_h
|
||||
#define mozilla_dom_ScreenOrientation_h
|
||||
|
||||
#include "mozilla/DOMEventTargetHelper.h"
|
||||
#include "mozilla/dom/ScreenOrientationBinding.h"
|
||||
#include "mozilla/HalScreenConfiguration.h"
|
||||
|
||||
class nsScreen;
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
class Promise;
|
||||
// Make sure that any change to ScreenOrientationInternal values are
|
||||
// also made in mobile/android/base/GeckoScreenOrientation.java
|
||||
typedef uint32_t ScreenOrientationInternal;
|
||||
@ -23,6 +30,88 @@ static const ScreenOrientationInternal eScreenOrientation_LandscapeSecondary = 1
|
||||
//it could be PortraitPrimary or LandscapePrimary depends on display resolution
|
||||
static const ScreenOrientationInternal eScreenOrientation_Default = 1u << 4;
|
||||
|
||||
class ScreenOrientation final : public DOMEventTargetHelper,
|
||||
public mozilla::hal::ScreenConfigurationObserver
|
||||
{
|
||||
// nsScreen has deprecated API that shares implementation.
|
||||
friend class ::nsScreen;
|
||||
|
||||
public:
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(ScreenOrientation, mozilla::DOMEventTargetHelper)
|
||||
NS_REALLY_FORWARD_NSIDOMEVENTTARGET(mozilla::DOMEventTargetHelper)
|
||||
|
||||
IMPL_EVENT_HANDLER(change)
|
||||
|
||||
ScreenOrientation(nsPIDOMWindow* aWindow, nsScreen* aScreen);
|
||||
|
||||
already_AddRefed<Promise> Lock(OrientationLockType aOrientation,
|
||||
ErrorResult& aRv);
|
||||
|
||||
void Unlock(ErrorResult& aRv);
|
||||
|
||||
// DeviceType and DeviceAngle gets the current type and angle of the device.
|
||||
OrientationType DeviceType() const;
|
||||
uint16_t DeviceAngle() const;
|
||||
|
||||
// GetType and GetAngle gets the type and angle of the responsible document
|
||||
// (as defined in specification).
|
||||
OrientationType GetType(ErrorResult& aRv) const;
|
||||
uint16_t GetAngle(ErrorResult& aRv) const;
|
||||
|
||||
virtual JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
|
||||
|
||||
void Notify(const mozilla::hal::ScreenConfiguration& aConfiguration) override;
|
||||
|
||||
private:
|
||||
virtual ~ScreenOrientation();
|
||||
|
||||
// Listener to unlock orientation if we leave fullscreen.
|
||||
class FullScreenEventListener;
|
||||
|
||||
// Listener to update document's orienation lock when document becomes
|
||||
// visible.
|
||||
class VisibleEventListener;
|
||||
|
||||
// Task to run step to lock orientation as defined in specification.
|
||||
class LockOrientationTask;
|
||||
|
||||
enum LockPermission {
|
||||
LOCK_DENIED,
|
||||
FULLSCREEN_LOCK_ALLOWED,
|
||||
LOCK_ALLOWED
|
||||
};
|
||||
|
||||
// This method calls into the HAL to lock the device and sets
|
||||
// up listeners for full screen change.
|
||||
bool LockDeviceOrientation(ScreenOrientationInternal aOrientation,
|
||||
bool aIsFullscreen, ErrorResult& aRv);
|
||||
|
||||
// This method calls in to the HAL to unlock the device and removes
|
||||
// full screen change listener.
|
||||
void UnlockDeviceOrientation();
|
||||
|
||||
// This method performs the same function as |Lock| except it takes
|
||||
// a ScreenOrientationInternal argument instead of an OrientationType.
|
||||
// This method exists in order to share implementation with nsScreen that
|
||||
// uses ScreenOrientationInternal.
|
||||
already_AddRefed<Promise> LockInternal(ScreenOrientationInternal aOrientation,
|
||||
ErrorResult& aRv);
|
||||
|
||||
void DispatchChangeEvent();
|
||||
|
||||
LockPermission GetLockOrientationPermission() const;
|
||||
|
||||
// Gets the responsible document as defined in the spec.
|
||||
nsIDocument* GetResponsibleDocument() const;
|
||||
|
||||
nsRefPtr<nsScreen> mScreen;
|
||||
nsRefPtr<FullScreenEventListener> mFullScreenListener;
|
||||
nsRefPtr<VisibleEventListener> mVisibleListener;
|
||||
OrientationType mType;
|
||||
uint16_t mAngle;
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
|
@ -7,11 +7,18 @@
|
||||
#include "StructuredCloneHelper.h"
|
||||
|
||||
#include "ImageContainer.h"
|
||||
#include "mozilla/AutoRestore.h"
|
||||
#include "mozilla/dom/BlobBinding.h"
|
||||
#include "mozilla/dom/File.h"
|
||||
#include "mozilla/dom/FileList.h"
|
||||
#include "mozilla/dom/FileListBinding.h"
|
||||
#include "mozilla/dom/ImageBitmap.h"
|
||||
#include "mozilla/dom/ImageBitmapBinding.h"
|
||||
#include "mozilla/dom/MessagePort.h"
|
||||
#include "mozilla/dom/MessagePortBinding.h"
|
||||
#include "mozilla/dom/PMessagePort.h"
|
||||
#include "mozilla/dom/StructuredCloneTags.h"
|
||||
#include "mozilla/dom/ToJSValue.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
@ -12,6 +12,7 @@
|
||||
#include "nsTArray.h"
|
||||
|
||||
namespace mozilla {
|
||||
class ErrorResult;
|
||||
namespace layers {
|
||||
class Image;
|
||||
}
|
||||
|
@ -337,6 +337,7 @@ UNIFIED_SOURCES += [
|
||||
'ProcessGlobal.cpp',
|
||||
'ResponsiveImageSelector.cpp',
|
||||
'SameProcessMessageQueue.cpp',
|
||||
'ScreenOrientation.cpp',
|
||||
'ScriptSettings.cpp',
|
||||
'ShadowRoot.cpp',
|
||||
'StructuredCloneHelper.cpp',
|
||||
|
@ -25,6 +25,9 @@
|
||||
#include "mozilla/MemoryReporting.h"
|
||||
#include "mozilla/dom/BindingDeclarations.h"
|
||||
|
||||
// Undefine LoadImage to prevent naming conflict with Windows.
|
||||
#undef LoadImage
|
||||
|
||||
class nsAString;
|
||||
class nsIDocument;
|
||||
class nsStyledElementNotElementCSSInlineStyle;
|
||||
|
@ -38,6 +38,7 @@
|
||||
#include "nsQueryObject.h"
|
||||
#include "nsDOMClassInfo.h"
|
||||
#include "mozilla/Services.h"
|
||||
#include "nsScreen.h"
|
||||
|
||||
#include "mozilla/AsyncEventDispatcher.h"
|
||||
#include "mozilla/BasicEvents.h"
|
||||
@ -1937,6 +1938,7 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INTERNAL(nsDocument)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mFirstBaseNodeWithHref)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDOMImplementation)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mImageMaps)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mOrientationPendingPromise)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mOriginalDocument)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mCachedEncoder)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mStateObjectCached)
|
||||
@ -2037,6 +2039,7 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsDocument)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mChildrenCollection)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mRegistry)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mMasterDocument)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mOrientationPendingPromise)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mImportManager)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mSubImportLinks)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mFontFaceSet)
|
||||
@ -11940,6 +11943,38 @@ nsDocument::IsFullScreenEnabled(bool aCallerIsChrome, bool aLogFailure)
|
||||
return allowed;
|
||||
}
|
||||
|
||||
uint16_t
|
||||
nsDocument::CurrentOrientationAngle() const
|
||||
{
|
||||
return mCurrentOrientationAngle;
|
||||
}
|
||||
|
||||
OrientationType
|
||||
nsDocument::CurrentOrientationType() const
|
||||
{
|
||||
return mCurrentOrientationType;
|
||||
}
|
||||
|
||||
void
|
||||
nsDocument::SetCurrentOrientation(mozilla::dom::OrientationType aType,
|
||||
uint16_t aAngle)
|
||||
{
|
||||
mCurrentOrientationType = aType;
|
||||
mCurrentOrientationAngle = aAngle;
|
||||
}
|
||||
|
||||
Promise*
|
||||
nsDocument::GetOrientationPendingPromise() const
|
||||
{
|
||||
return mOrientationPendingPromise;
|
||||
}
|
||||
|
||||
void
|
||||
nsDocument::SetOrientationPendingPromise(Promise* aPromise)
|
||||
{
|
||||
mOrientationPendingPromise = aPromise;
|
||||
}
|
||||
|
||||
static void
|
||||
DispatchPointerLockChange(nsIDocument* aTarget)
|
||||
{
|
||||
|
@ -1279,6 +1279,13 @@ public:
|
||||
bool SetPointerLock(Element* aElement, int aCursorStyle);
|
||||
static void UnlockPointer(nsIDocument* aDoc = nullptr);
|
||||
|
||||
void SetCurrentOrientation(mozilla::dom::OrientationType aType,
|
||||
uint16_t aAngle) override;
|
||||
uint16_t CurrentOrientationAngle() const override;
|
||||
mozilla::dom::OrientationType CurrentOrientationType() const override;
|
||||
void SetOrientationPendingPromise(mozilla::dom::Promise* aPromise) override;
|
||||
mozilla::dom::Promise* GetOrientationPendingPromise() const override;
|
||||
|
||||
// This method may fire a DOM event; if it does so it will happen
|
||||
// synchronously.
|
||||
void UpdateVisibilityState();
|
||||
@ -1520,6 +1527,8 @@ protected:
|
||||
virtual nsIScriptGlobalObject* GetScriptHandlingObjectInternal() const override;
|
||||
virtual bool InternalAllowXULXBL() override;
|
||||
|
||||
void UpdateScreenOrientation();
|
||||
|
||||
#define NS_DOCUMENT_NOTIFY_OBSERVERS(func_, params_) \
|
||||
NS_OBSERVER_ARRAY_NOTIFY_XPCOM_OBSERVERS(mObservers, nsIDocumentObserver, \
|
||||
func_, params_);
|
||||
@ -1667,6 +1676,13 @@ public:
|
||||
// user.
|
||||
bool mAllowRelocking:1;
|
||||
|
||||
// ScreenOrientation "pending promise" as described by
|
||||
// http://www.w3.org/TR/screen-orientation/
|
||||
nsRefPtr<mozilla::dom::Promise> mOrientationPendingPromise;
|
||||
|
||||
uint16_t mCurrentOrientationAngle;
|
||||
mozilla::dom::OrientationType mCurrentOrientationType;
|
||||
|
||||
// Whether we're observing the "app-theme-changed" observer service
|
||||
// notification. We need to keep track of this because we might get multiple
|
||||
// OnPageShow notifications in a row without an OnPageHide in between, if
|
||||
|
@ -133,7 +133,9 @@ class MediaQueryList;
|
||||
class GlobalObject;
|
||||
class NodeFilter;
|
||||
class NodeIterator;
|
||||
enum class OrientationType : uint32_t;
|
||||
class ProcessingInstruction;
|
||||
class Promise;
|
||||
class StyleSheetList;
|
||||
class SVGDocument;
|
||||
class Touch;
|
||||
@ -1202,6 +1204,14 @@ public:
|
||||
|
||||
static void UnlockPointer(nsIDocument* aDoc = nullptr);
|
||||
|
||||
// ScreenOrientation related APIs
|
||||
|
||||
virtual void SetCurrentOrientation(mozilla::dom::OrientationType aType,
|
||||
uint16_t aAngle) = 0;
|
||||
virtual uint16_t CurrentOrientationAngle() const = 0;
|
||||
virtual mozilla::dom::OrientationType CurrentOrientationType() const = 0;
|
||||
virtual void SetOrientationPendingPromise(mozilla::dom::Promise* aPromise) = 0;
|
||||
virtual mozilla::dom::Promise* GetOrientationPendingPromise() const = 0;
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
|
@ -4,7 +4,6 @@
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "mozilla/Hal.h"
|
||||
#include "mozilla/dom/Event.h" // for nsIDOMEvent::InternalDOMEvent()
|
||||
#include "mozilla/dom/ScreenBinding.h"
|
||||
#include "nsScreen.h"
|
||||
@ -36,36 +35,32 @@ nsScreen::Create(nsPIDOMWindow* aWindow)
|
||||
NS_ENSURE_TRUE(sgo, nullptr);
|
||||
|
||||
nsRefPtr<nsScreen> screen = new nsScreen(aWindow);
|
||||
|
||||
hal::RegisterScreenConfigurationObserver(screen);
|
||||
hal::ScreenConfiguration config;
|
||||
hal::GetCurrentScreenConfiguration(&config);
|
||||
screen->mOrientationInternal = config.orientation();
|
||||
|
||||
return screen.forget();
|
||||
}
|
||||
|
||||
nsScreen::nsScreen(nsPIDOMWindow* aWindow)
|
||||
: DOMEventTargetHelper(aWindow)
|
||||
, mEventListener(nullptr)
|
||||
, mScreenOrientation(new ScreenOrientation(aWindow, this))
|
||||
{
|
||||
}
|
||||
|
||||
nsScreen::~nsScreen()
|
||||
{
|
||||
MOZ_ASSERT(!mEventListener);
|
||||
hal::UnregisterScreenConfigurationObserver(this);
|
||||
}
|
||||
|
||||
|
||||
// QueryInterface implementation for nsScreen
|
||||
NS_INTERFACE_MAP_BEGIN(nsScreen)
|
||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(nsScreen)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIDOMScreen)
|
||||
NS_INTERFACE_MAP_END_INHERITING(DOMEventTargetHelper)
|
||||
|
||||
NS_IMPL_ADDREF_INHERITED(nsScreen, DOMEventTargetHelper)
|
||||
NS_IMPL_RELEASE_INHERITED(nsScreen, DOMEventTargetHelper)
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_INHERITED(nsScreen,
|
||||
DOMEventTargetHelper,
|
||||
mScreenOrientation)
|
||||
|
||||
int32_t
|
||||
nsScreen::GetPixelDepth(ErrorResult& aRv)
|
||||
{
|
||||
@ -162,45 +157,33 @@ nsScreen::GetAvailRect(nsRect& aRect)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
nsScreen::Notify(const hal::ScreenConfiguration& aConfiguration)
|
||||
mozilla::dom::ScreenOrientation*
|
||||
nsScreen::Orientation() const
|
||||
{
|
||||
ScreenOrientationInternal previousOrientation = mOrientationInternal;
|
||||
mOrientationInternal = aConfiguration.orientation();
|
||||
|
||||
NS_ASSERTION(mOrientationInternal == eScreenOrientation_PortraitPrimary ||
|
||||
mOrientationInternal == eScreenOrientation_PortraitSecondary ||
|
||||
mOrientationInternal == eScreenOrientation_LandscapePrimary ||
|
||||
mOrientationInternal == eScreenOrientation_LandscapeSecondary,
|
||||
"Invalid orientation value passed to notify method!");
|
||||
|
||||
if (mOrientationInternal != previousOrientation) {
|
||||
DispatchTrustedEvent(NS_LITERAL_STRING("mozorientationchange"));
|
||||
}
|
||||
return mScreenOrientation;
|
||||
}
|
||||
|
||||
void
|
||||
nsScreen::GetMozOrientation(nsString& aOrientation)
|
||||
nsScreen::GetMozOrientation(nsString& aOrientation) const
|
||||
{
|
||||
if (ShouldResistFingerprinting()) {
|
||||
aOrientation.AssignLiteral("landscape-primary");
|
||||
} else {
|
||||
switch (mOrientationInternal) {
|
||||
case eScreenOrientation_PortraitPrimary:
|
||||
switch (mScreenOrientation->DeviceType()) {
|
||||
case OrientationType::Portrait_primary:
|
||||
aOrientation.AssignLiteral("portrait-primary");
|
||||
break;
|
||||
case eScreenOrientation_PortraitSecondary:
|
||||
case OrientationType::Portrait_secondary:
|
||||
aOrientation.AssignLiteral("portrait-secondary");
|
||||
break;
|
||||
case eScreenOrientation_LandscapePrimary:
|
||||
case OrientationType::Landscape_primary:
|
||||
aOrientation.AssignLiteral("landscape-primary");
|
||||
break;
|
||||
case eScreenOrientation_LandscapeSecondary:
|
||||
case OrientationType::Landscape_secondary:
|
||||
aOrientation.AssignLiteral("landscape-secondary");
|
||||
break;
|
||||
case eScreenOrientation_None:
|
||||
default:
|
||||
MOZ_CRASH("Unacceptable mOrientationInternal value");
|
||||
MOZ_CRASH("Unacceptable screen orientation type.");
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -214,35 +197,6 @@ nsScreen::GetSlowMozOrientation(nsAString& aOrientation)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsScreen::LockPermission
|
||||
nsScreen::GetLockOrientationPermission() const
|
||||
{
|
||||
nsCOMPtr<nsPIDOMWindow> owner = GetOwner();
|
||||
if (!owner) {
|
||||
return LOCK_DENIED;
|
||||
}
|
||||
|
||||
// Chrome can always lock the screen orientation.
|
||||
nsIDocShell* docShell = owner->GetDocShell();
|
||||
if (docShell && docShell->ItemType() == nsIDocShellTreeItem::typeChrome) {
|
||||
return LOCK_ALLOWED;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIDocument> doc = owner->GetDoc();
|
||||
if (!doc || doc->Hidden()) {
|
||||
return LOCK_DENIED;
|
||||
}
|
||||
|
||||
// Apps can always lock the screen orientation.
|
||||
if (doc->NodePrincipal()->GetAppStatus() >=
|
||||
nsIPrincipal::APP_STATUS_INSTALLED) {
|
||||
return LOCK_ALLOWED;
|
||||
}
|
||||
|
||||
// Other content must be full-screen in order to lock orientation.
|
||||
return doc->MozFullScreen() ? FULLSCREEN_LOCK_ALLOWED : LOCK_DENIED;
|
||||
}
|
||||
|
||||
bool
|
||||
nsScreen::MozLockOrientation(const nsAString& aOrientation, ErrorResult& aRv)
|
||||
{
|
||||
@ -287,34 +241,13 @@ nsScreen::MozLockOrientation(const Sequence<nsString>& aOrientations,
|
||||
}
|
||||
}
|
||||
|
||||
switch (GetLockOrientationPermission()) {
|
||||
case LOCK_DENIED:
|
||||
switch (mScreenOrientation->GetLockOrientationPermission()) {
|
||||
case ScreenOrientation::LOCK_DENIED:
|
||||
return false;
|
||||
case LOCK_ALLOWED:
|
||||
return hal::LockScreenOrientation(orientation);
|
||||
case FULLSCREEN_LOCK_ALLOWED: {
|
||||
// We need to register a listener so we learn when we leave full-screen
|
||||
// and when we will have to unlock the screen.
|
||||
// This needs to be done before LockScreenOrientation call to make sure
|
||||
// the locking can be unlocked.
|
||||
nsCOMPtr<EventTarget> target = do_QueryInterface(GetOwner()->GetDoc());
|
||||
if (!target) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!hal::LockScreenOrientation(orientation)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// We are fullscreen and lock has been accepted.
|
||||
if (!mEventListener) {
|
||||
mEventListener = new FullScreenEventListener();
|
||||
}
|
||||
|
||||
aRv = target->AddSystemEventListener(NS_LITERAL_STRING("mozfullscreenchange"),
|
||||
mEventListener, /* useCapture = */ true);
|
||||
return true;
|
||||
}
|
||||
case ScreenOrientation::LOCK_ALLOWED:
|
||||
return mScreenOrientation->LockDeviceOrientation(orientation, false, aRv);
|
||||
case ScreenOrientation::FULLSCREEN_LOCK_ALLOWED:
|
||||
return mScreenOrientation->LockDeviceOrientation(orientation, true, aRv);
|
||||
}
|
||||
|
||||
// This is only for compilers that don't understand that the previous switch
|
||||
@ -325,20 +258,7 @@ nsScreen::MozLockOrientation(const Sequence<nsString>& aOrientations,
|
||||
void
|
||||
nsScreen::MozUnlockOrientation()
|
||||
{
|
||||
hal::UnlockScreenOrientation();
|
||||
|
||||
if (!mEventListener) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Remove event listener in case of fullscreen lock.
|
||||
nsCOMPtr<EventTarget> target = do_QueryInterface(GetOwner()->GetDoc());
|
||||
if (target) {
|
||||
target->RemoveSystemEventListener(NS_LITERAL_STRING("mozfullscreenchange"),
|
||||
mEventListener, /* useCapture */ true);
|
||||
}
|
||||
|
||||
mEventListener = nullptr;
|
||||
mScreenOrientation->UnlockDeviceOrientation();
|
||||
}
|
||||
|
||||
bool
|
||||
@ -361,39 +281,6 @@ nsScreen::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
|
||||
return ScreenBinding::Wrap(aCx, this, aGivenProto);
|
||||
}
|
||||
|
||||
NS_IMPL_ISUPPORTS(nsScreen::FullScreenEventListener, nsIDOMEventListener)
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsScreen::FullScreenEventListener::HandleEvent(nsIDOMEvent* aEvent)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
nsAutoString eventType;
|
||||
aEvent->GetType(eventType);
|
||||
|
||||
MOZ_ASSERT(eventType.EqualsLiteral("mozfullscreenchange"));
|
||||
#endif
|
||||
|
||||
nsCOMPtr<EventTarget> target = aEvent->InternalDOMEvent()->GetCurrentTarget();
|
||||
MOZ_ASSERT(target);
|
||||
|
||||
nsCOMPtr<nsIDocument> doc = do_QueryInterface(target);
|
||||
MOZ_ASSERT(doc);
|
||||
|
||||
// We have to make sure that the event we got is the event sent when
|
||||
// fullscreen is disabled because we could get one when fullscreen
|
||||
// got enabled if the lock call is done at the same moment.
|
||||
if (doc->MozFullScreen()) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
target->RemoveSystemEventListener(NS_LITERAL_STRING("mozfullscreenchange"),
|
||||
this, true);
|
||||
|
||||
hal::UnlockScreenOrientation();
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsScreen::GetWindowInnerRect(nsRect& aRect)
|
||||
{
|
||||
|
@ -10,7 +10,6 @@
|
||||
#include "mozilla/dom/ScreenOrientation.h"
|
||||
#include "mozilla/DOMEventTargetHelper.h"
|
||||
#include "mozilla/ErrorResult.h"
|
||||
#include "mozilla/HalScreenConfiguration.h"
|
||||
#include "nsIDOMScreen.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsRect.h"
|
||||
@ -20,7 +19,6 @@ class nsDeviceContext;
|
||||
// Script "screen" object
|
||||
class nsScreen : public mozilla::DOMEventTargetHelper
|
||||
, public nsIDOMScreen
|
||||
, public mozilla::hal::ScreenConfigurationObserver
|
||||
{
|
||||
typedef mozilla::ErrorResult ErrorResult;
|
||||
public:
|
||||
@ -28,6 +26,7 @@ public:
|
||||
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
NS_DECL_NSIDOMSCREEN
|
||||
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(nsScreen, mozilla::DOMEventTargetHelper)
|
||||
NS_REALLY_FORWARD_NSIDOMEVENTTARGET(mozilla::DOMEventTargetHelper)
|
||||
|
||||
nsPIDOMWindow* GetParentObject() const
|
||||
@ -115,7 +114,8 @@ public:
|
||||
return rect.height;
|
||||
}
|
||||
|
||||
void GetMozOrientation(nsString& aOrientation);
|
||||
// Deprecated
|
||||
void GetMozOrientation(nsString& aOrientation) const;
|
||||
|
||||
IMPL_EVENT_HANDLER(mozorientationchange)
|
||||
|
||||
@ -125,7 +125,7 @@ public:
|
||||
|
||||
virtual JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
|
||||
|
||||
void Notify(const mozilla::hal::ScreenConfiguration& aConfiguration) override;
|
||||
mozilla::dom::ScreenOrientation* Orientation() const;
|
||||
|
||||
protected:
|
||||
nsDeviceContext* GetDeviceContext();
|
||||
@ -133,35 +133,15 @@ protected:
|
||||
nsresult GetAvailRect(nsRect& aRect);
|
||||
nsresult GetWindowInnerRect(nsRect& aRect);
|
||||
|
||||
mozilla::dom::ScreenOrientationInternal mOrientationInternal;
|
||||
|
||||
private:
|
||||
class FullScreenEventListener final : public nsIDOMEventListener
|
||||
{
|
||||
~FullScreenEventListener() {}
|
||||
public:
|
||||
FullScreenEventListener() {}
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIDOMEVENTLISTENER
|
||||
};
|
||||
|
||||
explicit nsScreen(nsPIDOMWindow* aWindow);
|
||||
virtual ~nsScreen();
|
||||
|
||||
enum LockPermission {
|
||||
LOCK_DENIED,
|
||||
FULLSCREEN_LOCK_ALLOWED,
|
||||
LOCK_ALLOWED
|
||||
};
|
||||
|
||||
LockPermission GetLockOrientationPermission() const;
|
||||
|
||||
bool IsDeviceSizePageSize();
|
||||
|
||||
bool ShouldResistFingerprinting() const;
|
||||
|
||||
nsRefPtr<FullScreenEventListener> mEventListener;
|
||||
nsRefPtr<mozilla::dom::ScreenOrientation> mScreenOrientation;
|
||||
};
|
||||
|
||||
#endif /* nsScreen_h___ */
|
||||
|
@ -18,6 +18,8 @@ struct JSContext;
|
||||
struct JSStructuredCloneReader;
|
||||
struct JSStructuredCloneWriter;
|
||||
|
||||
class nsIGlobalObject;
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
class ErrorResult;
|
||||
|
@ -963,6 +963,8 @@ var interfaceNamesInGlobalScope =
|
||||
"RTCStatsReport",
|
||||
// IMPORTANT: Do not change this list without review from a DOM peer!
|
||||
"Screen",
|
||||
// IMPORTANT: Do not change this list without review from a DOM peer!
|
||||
"ScreenOrientation",
|
||||
// IMPORTANT: Do not change this list without review from a DOM peer!
|
||||
"ScriptProcessorNode",
|
||||
// IMPORTANT: Do not change this list without review from a DOM peer!
|
||||
|
@ -29,6 +29,7 @@ interface Screen : EventTarget {
|
||||
readonly attribute long availLeft;
|
||||
|
||||
/**
|
||||
* DEPRECATED, use ScreenOrientation API instead.
|
||||
* Returns the current screen orientation.
|
||||
* Can be: landscape-primary, landscape-secondary,
|
||||
* portrait-primary or portrait-secondary.
|
||||
@ -38,6 +39,7 @@ interface Screen : EventTarget {
|
||||
attribute EventHandler onmozorientationchange;
|
||||
|
||||
/**
|
||||
* DEPRECATED, use ScreenOrientation API instead.
|
||||
* Lock screen orientation to the specified type.
|
||||
*/
|
||||
[Throws, UnsafeInPrerendering]
|
||||
@ -46,8 +48,14 @@ interface Screen : EventTarget {
|
||||
boolean mozLockOrientation(sequence<DOMString> orientation);
|
||||
|
||||
/**
|
||||
* DEPRECATED, use ScreenOrientation API instead.
|
||||
* Unlock the screen orientation.
|
||||
*/
|
||||
[UnsafeInPrerendering]
|
||||
void mozUnlockOrientation();
|
||||
};
|
||||
|
||||
// https://w3c.github.io/screen-orientation
|
||||
partial interface Screen {
|
||||
readonly attribute ScreenOrientation orientation;
|
||||
};
|
||||
|
42
dom/webidl/ScreenOrientation.webidl
Normal file
42
dom/webidl/ScreenOrientation.webidl
Normal file
@ -0,0 +1,42 @@
|
||||
/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*
|
||||
* The origin of this IDL file is
|
||||
* https://w3c.github.io/screen-orientation
|
||||
*
|
||||
* Copyright © 2014 W3C® (MIT, ERCIM, Keio, Beihang), All Rights
|
||||
* Reserved. W3C liability, trademark and document use rules apply.
|
||||
*/
|
||||
|
||||
enum OrientationType {
|
||||
"portrait-primary",
|
||||
"portrait-secondary",
|
||||
"landscape-primary",
|
||||
"landscape-secondary"
|
||||
};
|
||||
|
||||
enum OrientationLockType {
|
||||
"any",
|
||||
"natural",
|
||||
"landscape",
|
||||
"portrait",
|
||||
"portrait-primary",
|
||||
"portrait-secondary",
|
||||
"landscape-primary",
|
||||
"landscape-secondary"
|
||||
};
|
||||
|
||||
[UnsafeInPrerendering]
|
||||
interface ScreenOrientation : EventTarget {
|
||||
[Throws]
|
||||
Promise<void> lock(OrientationLockType orientation);
|
||||
[Throws]
|
||||
void unlock();
|
||||
[Throws]
|
||||
readonly attribute OrientationType type;
|
||||
[Throws]
|
||||
readonly attribute unsigned short angle;
|
||||
attribute EventHandler onchange;
|
||||
};
|
@ -387,6 +387,7 @@ WEBIDL_FILES = [
|
||||
'RGBColor.webidl',
|
||||
'RTCStatsReport.webidl',
|
||||
'Screen.webidl',
|
||||
'ScreenOrientation.webidl',
|
||||
'ScriptProcessorNode.webidl',
|
||||
'ScrollAreaEvent.webidl',
|
||||
'ScrollBoxObject.webidl',
|
||||
|
@ -1,6 +1,5 @@
|
||||
[lock-bad-argument.html]
|
||||
type: testharness
|
||||
expected: ERROR
|
||||
[Test that screen.orientation.lock() throws when the input isn't valid.]
|
||||
expected: NOTRUN
|
||||
expected: FAIL
|
||||
|
||||
|
@ -1,8 +1,6 @@
|
||||
[lock-basic.html]
|
||||
type: testharness
|
||||
[Test that screen.orientation.unlock() doesn't throw when there is no lock]
|
||||
expected: FAIL
|
||||
|
||||
expected: TIMEOUT
|
||||
[Test that screen.orientation.lock returns a pending promise.]
|
||||
expected: FAIL
|
||||
expected: TIMEOUT
|
||||
|
||||
|
@ -2,7 +2,7 @@
|
||||
type: testharness
|
||||
expected: TIMEOUT
|
||||
[Test without 'allow-orientation-lock' sandboxing directive]
|
||||
expected: NOTRUN
|
||||
expected: FAIL
|
||||
|
||||
[Test with 'allow-orientation-lock' sandboxing directive]
|
||||
expected: NOTRUN
|
||||
|
@ -1,6 +1,6 @@
|
||||
[onchange-event-subframe.html]
|
||||
type: testharness
|
||||
expected: ERROR
|
||||
expected: TIMEOUT
|
||||
[Test subframes receive orientation change events]
|
||||
expected: NOTRUN
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
[onchange-event.html]
|
||||
type: testharness
|
||||
expected: ERROR
|
||||
expected: TIMEOUT
|
||||
[Test that orientationchange event is fired when the orientation changes.]
|
||||
expected: NOTRUN
|
||||
|
||||
|
@ -1,11 +0,0 @@
|
||||
[orientation-api.html]
|
||||
type: testharness
|
||||
[Test that the Screen Orientation API is present.]
|
||||
expected: FAIL
|
||||
|
||||
[Test Screen Orientation API property types.]
|
||||
expected: FAIL
|
||||
|
||||
[Test that screen.orientation is an EventTarget.]
|
||||
expected: FAIL
|
||||
|
@ -1,14 +1,8 @@
|
||||
[orientation-reading.html]
|
||||
type: testharness
|
||||
[Test screen.orientation properties]
|
||||
expected: FAIL
|
||||
|
||||
[Test screen.orientation default values.]
|
||||
expected: FAIL
|
||||
|
||||
[Test that screen.orientation properties are not writable]
|
||||
expected: FAIL
|
||||
|
||||
[Test that screen.orientation values change if the orientation changes]
|
||||
expected: FAIL
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user