diff --git a/docshell/base/nsDocShell.cpp b/docshell/base/nsDocShell.cpp index e7e35849c3f..9f690678aff 100644 --- a/docshell/base/nsDocShell.cpp +++ b/docshell/base/nsDocShell.cpp @@ -16,6 +16,7 @@ #include "mozilla/dom/Element.h" #include "mozilla/dom/TabChild.h" #include "mozilla/dom/ProfileTimelineMarkerBinding.h" +#include "mozilla/dom/ScreenOrientation.h" #include "mozilla/dom/ToJSValue.h" #include "mozilla/dom/workers/ServiceWorkerManager.h" #include "mozilla/EventStateManager.h" @@ -754,6 +755,7 @@ nsDocShell::nsDocShell() , mLoadedTransIndex(-1) , mSandboxFlags(0) , mFullscreenAllowed(CHECK_ATTRIBUTES) + , mOrientationLock(eScreenOrientation_None) , mCreated(false) , mAllowSubframes(true) , mAllowPlugins(true) @@ -2548,6 +2550,18 @@ nsDocShell::SetFullscreenAllowed(bool aFullscreenAllowed) return NS_OK; } +ScreenOrientationInternal +nsDocShell::OrientationLock() +{ + return mOrientationLock; +} + +void +nsDocShell::SetOrientationLock(ScreenOrientationInternal aOrientationLock) +{ + mOrientationLock = aOrientationLock; +} + NS_IMETHODIMP nsDocShell::GetMayEnableCharacterEncodingMenu( bool* aMayEnableCharacterEncodingMenu) @@ -5921,6 +5935,16 @@ nsDocShell::SetIsActive(bool aIsActive) if (mScriptGlobal) { mScriptGlobal->SetIsBackground(!aIsActive); if (nsCOMPtr doc = mScriptGlobal->GetExtantDoc()) { + if (aIsActive) { + nsCOMPtr parent; + GetSameTypeParent(getter_AddRefs(parent)); + if (!parent) { + // We only care about the top-level browsing context. + uint16_t orientation = OrientationLock(); + ScreenOrientation::UpdateActiveOrientationLock(orientation); + } + } + doc->PostVisibilityUpdateEvent(); } } @@ -10042,6 +10066,22 @@ nsDocShell::InternalLoad(nsIURI* aURI, mTiming->NotifyUnloadAccepted(mCurrentURI); } + // Whenever a top-level browsing context is navigated, the user agent MUST + // lock the orientation of the document to the document's default + // orientation. We don't explicitly check for a top-level browsing context + // here because orientation is only set on top-level browsing contexts. + if (OrientationLock() != eScreenOrientation_None) { +#ifdef DEBUG + nsCOMPtr parent; + GetSameTypeParent(getter_AddRefs(parent)); + MOZ_ASSERT(!parent); +#endif + SetOrientationLock(eScreenOrientation_None); + if (mIsActive) { + ScreenOrientation::UpdateActiveOrientationLock(eScreenOrientation_None); + } + } + // Check for saving the presentation here, before calling Stop(). // This is necessary so that we can catch any pending requests. // Since the new request has not been created yet, we pass null for the diff --git a/docshell/base/nsDocShell.h b/docshell/base/nsDocShell.h index ba23b371d66..992b4582c59 100644 --- a/docshell/base/nsDocShell.h +++ b/docshell/base/nsDocShell.h @@ -62,6 +62,7 @@ namespace mozilla { namespace dom { class EventTarget; +typedef uint32_t ScreenOrientationInternal; } // namespace dom } // namespace mozilla @@ -875,6 +876,10 @@ protected: }; FullscreenAllowedState mFullscreenAllowed; + // The orientation lock as described by + // https://w3c.github.io/screen-orientation/ + mozilla::dom::ScreenOrientationInternal mOrientationLock; + // Cached value of the "browser.xul.error_pages.enabled" preference. static bool sUseErrorPages; diff --git a/docshell/base/nsIDocShell.idl b/docshell/base/nsIDocShell.idl index b216c13c0f3..d637791f5ae 100644 --- a/docshell/base/nsIDocShell.idl +++ b/docshell/base/nsIDocShell.idl @@ -46,7 +46,7 @@ interface nsITabParent; typedef unsigned long nsLoadFlags; -[scriptable, builtinclass, uuid(97471054-0BC8-4A57-BBFE-6C255BCBBB67)] +[scriptable, builtinclass, uuid(35a26f70-dbb9-450d-b634-cd0bbb9b8e13)] interface nsIDocShell : nsIDocShellTreeItem { /** @@ -926,6 +926,9 @@ interface nsIDocShell : nsIDocShellTreeItem void setFullscreenAllowed(in boolean allowed); + [notxpcom] uint32_t orientationLock(); + [notxpcom] void setOrientationLock(in uint32_t orientationLock); + [noscript, infallible] attribute boolean affectPrivateSessionLifetime; /** diff --git a/dom/base/ScreenOrientation.cpp b/dom/base/ScreenOrientation.cpp index 7dacd18ecbd..ca24ca57fab 100644 --- a/dom/base/ScreenOrientation.cpp +++ b/dom/base/ScreenOrientation.cpp @@ -317,6 +317,7 @@ ScreenOrientation::LockInternal(ScreenOrientationInternal aOrientation, ErrorRes return nullptr; } + rootShell->SetOrientationLock(aOrientation); AbortOrientationPromises(rootShell); doc->SetOrientationPendingPromise(p); @@ -530,6 +531,16 @@ ScreenOrientation::Notify(const hal::ScreenConfiguration& aConfiguration) } } +void +ScreenOrientation::UpdateActiveOrientationLock(ScreenOrientationInternal aOrientation) +{ + if (aOrientation == eScreenOrientation_None) { + hal::UnlockScreenOrientation(); + } else { + hal::LockScreenOrientation(aOrientation); + } +} + void ScreenOrientation::DispatchChangeEvent() { diff --git a/dom/base/ScreenOrientation.h b/dom/base/ScreenOrientation.h index a7fcbd19d69..796cb9a9bd9 100644 --- a/dom/base/ScreenOrientation.h +++ b/dom/base/ScreenOrientation.h @@ -63,6 +63,8 @@ public: void Notify(const mozilla::hal::ScreenConfiguration& aConfiguration) override; + static void UpdateActiveOrientationLock(ScreenOrientationInternal aOrientation); + private: virtual ~ScreenOrientation();