Bug 1744101 - Support ScreenOrientation.unlock r=geckoview-reviewers,agi

Unlocking the screen orientation means locking the device to its default orientation. It is the same as calling `screen.orientation.lock('natural')`, where natural means the "device manufacturer's considered default orientation". That corresponds to the GeckoScreenOrientation constant `ScreenOrientation_Default`. In the Java public API, ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED corresponds to default, as specified by chromium (https://chromium.googlesource.com/chromium/src/+/66.0.3359.158/content/public/android/java/src/org/chromium/content/browser/ScreenOrientationProvider.java).

Differential Revision: https://phabricator.services.mozilla.com/D133083
This commit is contained in:
Cathy Lu 2021-12-15 16:51:28 +00:00
Родитель 2b2425407f
Коммит 623627fafc
3 изменённых файлов: 90 добавлений и 30 удалений

Просмотреть файл

@ -126,13 +126,7 @@ void GetCurrentScreenConfiguration(ScreenConfiguration* aScreenConfiguration) {
RefPtr<MozPromise<bool, bool, false>> LockScreenOrientation( RefPtr<MozPromise<bool, bool, false>> LockScreenOrientation(
const hal::ScreenOrientation& aOrientation) { const hal::ScreenOrientation& aOrientation) {
// Force the default orientation to be portrait-primary. switch (aOrientation) {
hal::ScreenOrientation orientation =
aOrientation == eScreenOrientation_Default
? eScreenOrientation_PortraitPrimary
: aOrientation;
switch (orientation) {
// The Android backend only supports these orientations. // The Android backend only supports these orientations.
case eScreenOrientation_PortraitPrimary: case eScreenOrientation_PortraitPrimary:
case eScreenOrientation_PortraitSecondary: case eScreenOrientation_PortraitSecondary:
@ -145,7 +139,7 @@ RefPtr<MozPromise<bool, bool, false>> LockScreenOrientation(
case eScreenOrientation_Default: { case eScreenOrientation_Default: {
java::GeckoRuntime::LocalRef runtime = java::GeckoRuntime::GetInstance(); java::GeckoRuntime::LocalRef runtime = java::GeckoRuntime::GetInstance();
if (runtime != NULL) { if (runtime != NULL) {
auto result = runtime->LockScreenOrientation(orientation); auto result = runtime->LockScreenOrientation(aOrientation);
auto geckoResult = java::GeckoResult::LocalRef(std::move(result)); auto geckoResult = java::GeckoResult::LocalRef(std::move(result));
return geckoResult return geckoResult
? MozPromise<bool, bool, false>::FromGeckoResult(geckoResult) ? MozPromise<bool, bool, false>::FromGeckoResult(geckoResult)
@ -160,7 +154,12 @@ RefPtr<MozPromise<bool, bool, false>> LockScreenOrientation(
} }
} }
void UnlockScreenOrientation() {} void UnlockScreenOrientation() {
java::GeckoRuntime::LocalRef runtime = java::GeckoRuntime::GetInstance();
if (runtime != NULL) {
runtime->UnlockScreenOrientation();
}
}
} // namespace hal_impl } // namespace hal_impl
} // namespace mozilla } // namespace mozilla

Просмотреть файл

@ -46,23 +46,31 @@ class OrientationDelegateTest : BaseSessionTest() {
promise.value promise.value
} }
private fun lockPortrait() {
sessionRule.delegateUntilTestEnd(TestOrientationDelegate(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT))
val promise = mainSession.evaluatePromiseJS("screen.orientation.lock('portrait-primary')")
sessionRule.waitUntilCalled(TestOrientationDelegate(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT))
sessionRule.runtime.orientationChanged(Configuration.ORIENTATION_PORTRAIT)
promise.value
}
private fun lockLandscape() {
sessionRule.delegateUntilTestEnd(TestOrientationDelegate(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE))
val promise = mainSession.evaluatePromiseJS("screen.orientation.lock('landscape-primary')")
sessionRule.waitUntilCalled(TestOrientationDelegate(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE))
sessionRule.runtime.orientationChanged(Configuration.ORIENTATION_LANDSCAPE)
promise.value
}
@Ignore("disable test for frequently failing Bug 1744372") @Ignore("disable test for frequently failing Bug 1744372")
@Test fun orientationLockedAlready() { @Test fun orientationLockedAlready() {
sessionRule.setPrefsUntilTestEnd(mapOf("dom.screenorientation.allow-lock" to true)) sessionRule.setPrefsUntilTestEnd(mapOf("dom.screenorientation.allow-lock" to true))
goFullscreen() goFullscreen()
// Lock to the current orientation // Lock to the current orientation
if (activityRule.activity.resources.configuration.orientation == ActivityInfo.SCREEN_ORIENTATION_PORTRAIT){ if (activityRule.activity.resources.configuration.orientation == ActivityInfo.SCREEN_ORIENTATION_PORTRAIT){
sessionRule.delegateUntilTestEnd(TestOrientationDelegate(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT)) lockPortrait()
val promise = mainSession.evaluatePromiseJS("screen.orientation.lock('portrait-primary')")
sessionRule.waitUntilCalled(TestOrientationDelegate(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT))
sessionRule.runtime.orientationChanged(Configuration.ORIENTATION_PORTRAIT)
promise.value
} else if (activityRule.activity.resources.configuration.orientation == ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE) { } else if (activityRule.activity.resources.configuration.orientation == ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE) {
sessionRule.delegateUntilTestEnd(TestOrientationDelegate(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE)) lockLandscape()
val promise = mainSession.evaluatePromiseJS("screen.orientation.lock('landscape-primary')")
sessionRule.waitUntilCalled(TestOrientationDelegate(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE))
sessionRule.runtime.orientationChanged(Configuration.ORIENTATION_LANDSCAPE)
promise.value
} }
} }
@ -81,23 +89,61 @@ class OrientationDelegateTest : BaseSessionTest() {
goFullscreen() goFullscreen()
// If the orientation is landscape, lock to portrait and wait for delegate. If portrait, lock to landscape instead. // If the orientation is landscape, lock to portrait and wait for delegate. If portrait, lock to landscape instead.
if (activityRule.activity.resources.configuration.orientation == ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE){ if (activityRule.activity.resources.configuration.orientation == ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE){
sessionRule.delegateUntilTestEnd(TestOrientationDelegate(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT)) lockPortrait()
val promise = mainSession.evaluatePromiseJS("screen.orientation.lock('portrait-primary')")
sessionRule.waitUntilCalled(TestOrientationDelegate(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT))
sessionRule.runtime.orientationChanged(Configuration.ORIENTATION_PORTRAIT)
promise.value
} else if (activityRule.activity.resources.configuration.orientation == ActivityInfo.SCREEN_ORIENTATION_PORTRAIT) { } else if (activityRule.activity.resources.configuration.orientation == ActivityInfo.SCREEN_ORIENTATION_PORTRAIT) {
sessionRule.delegateUntilTestEnd(TestOrientationDelegate(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE)) lockLandscape()
}
}
@Test fun orientationUnlock() {
sessionRule.setPrefsUntilTestEnd(mapOf("dom.screenorientation.allow-lock" to true))
goFullscreen()
mainSession.evaluateJS("screen.orientation.unlock()")
sessionRule.waitUntilCalled(object : OrientationController.OrientationDelegate {
@AssertCalled(count = 1)
override fun onOrientationUnlock() {
activityRule.activity.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED
}
})
}
@Test fun orientationLockUnlock() {
sessionRule.setPrefsUntilTestEnd(mapOf("dom.screenorientation.allow-lock" to true))
goFullscreen()
val promise = mainSession.evaluatePromiseJS("screen.orientation.lock('landscape-primary')") val promise = mainSession.evaluatePromiseJS("screen.orientation.lock('landscape-primary')")
sessionRule.waitUntilCalled(TestOrientationDelegate(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE)) sessionRule.waitUntilCalled(object : OrientationController.OrientationDelegate {
@AssertCalled(count = 1)
override fun onOrientationLock(aOrientation: Int): GeckoResult<AllowOrDeny>? {
assertThat(
"The orientation value is as expected",
aOrientation,
equalTo(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE)
)
activityRule.activity.requestedOrientation = aOrientation
return GeckoResult.allow()
}
})
sessionRule.runtime.orientationChanged(Configuration.ORIENTATION_LANDSCAPE) sessionRule.runtime.orientationChanged(Configuration.ORIENTATION_LANDSCAPE)
promise.value promise.value
// after locking to orientation landscape, unlock to default
mainSession.evaluateJS("screen.orientation.unlock()")
sessionRule.waitUntilCalled(object : OrientationController.OrientationDelegate {
@AssertCalled(count = 1)
override fun onOrientationUnlock() {
activityRule.activity.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED
} }
})
} }
inner class TestOrientationDelegate(private val expectedOrientation : Int) : OrientationController.OrientationDelegate { inner class TestOrientationDelegate(private val expectedOrientation : Int) : OrientationController.OrientationDelegate {
override fun onOrientationLock(aOrientation: Int): GeckoResult<AllowOrDeny>? { override fun onOrientationLock(aOrientation: Int): GeckoResult<AllowOrDeny>? {
assertThat("The orientation value is as expected", aOrientation, equalTo(expectedOrientation)) assertThat(
"The orientation value is as expected",
aOrientation,
equalTo(expectedOrientation)
)
activityRule.activity.requestedOrientation = aOrientation activityRule.activity.requestedOrientation = aOrientation
return GeckoResult.allow() return GeckoResult.allow()
} }

Просмотреть файл

@ -871,6 +871,8 @@ public final class GeckoRuntime implements Parcelable {
return ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE; return ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
} else if (geckoOrientation == ScreenOrientation.LANDSCAPE_SECONDARY.value) { } else if (geckoOrientation == ScreenOrientation.LANDSCAPE_SECONDARY.value) {
return ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE; return ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE;
} else if (geckoOrientation == ScreenOrientation.DEFAULT.value) {
return ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
} }
return ActivityInfo.SCREEN_ORIENTATION_PORTRAIT; return ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
} }
@ -902,6 +904,19 @@ public final class GeckoRuntime implements Parcelable {
return res; return res;
} }
/** Unlock screen orientation using OrientationController's onOrientationUnlock. */
@WrapForJNI(calledFrom = "gecko")
private void unlockScreenOrientation() {
ThreadUtils.runOnUiThread(
() -> {
final OrientationController.OrientationDelegate delegate =
getOrientationController().getDelegate();
if (delegate != null) {
delegate.onOrientationUnlock();
}
});
}
/** /**
* Get the storage controller for this runtime. The storage controller can be used to manage * Get the storage controller for this runtime. The storage controller can be used to manage
* persistent storage data accumulated by {@link GeckoSession}. * persistent storage data accumulated by {@link GeckoSession}.