summaryrefslogtreecommitdiffstats
path: root/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/OrientationDelegateTest.kt
diff options
context:
space:
mode:
Diffstat (limited to 'mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/OrientationDelegateTest.kt')
-rw-r--r--mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/OrientationDelegateTest.kt311
1 files changed, 311 insertions, 0 deletions
diff --git a/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/OrientationDelegateTest.kt b/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/OrientationDelegateTest.kt
new file mode 100644
index 0000000000..26ff365659
--- /dev/null
+++ b/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/OrientationDelegateTest.kt
@@ -0,0 +1,311 @@
+/* -*- Mode: Java; c-basic-offset: 4; tab-width: 4; indent-tabs-mode: nil; -*-
+ * Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+
+package org.mozilla.geckoview.test
+
+import android.content.pm.ActivityInfo
+import android.content.res.Configuration
+import androidx.test.ext.junit.rules.ActivityScenarioRule
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.MediumTest
+import org.hamcrest.Matchers.* // ktlint-disable no-wildcard-imports
+import org.junit.Before
+import org.junit.Rule
+import org.junit.Test
+import org.junit.rules.RuleChain
+import org.junit.runner.RunWith
+import org.mozilla.geckoview.* // ktlint-disable no-wildcard-imports
+import org.mozilla.geckoview.GeckoSession.ContentDelegate
+import org.mozilla.geckoview.OrientationController
+import org.mozilla.geckoview.test.rule.GeckoSessionTestRule
+import org.mozilla.geckoview.test.rule.GeckoSessionTestRule.AssertCalled
+import org.mozilla.geckoview.test.rule.GeckoSessionTestRule.WithDisplay
+
+@RunWith(AndroidJUnit4::class)
+@MediumTest
+class OrientationDelegateTest : BaseSessionTest() {
+ val activityRule = ActivityScenarioRule(GeckoViewTestActivity::class.java)
+
+ @get:Rule
+ override val rules: RuleChain = RuleChain.outerRule(activityRule).around(sessionRule)
+
+ @Before
+ fun setup() {
+ sessionRule.setPrefsUntilTestEnd(mapOf("dom.screenorientation.allow-lock" to true))
+ }
+
+ private fun goFullscreen() {
+ sessionRule.setPrefsUntilTestEnd(mapOf("full-screen-api.allow-trusted-requests-only" to false))
+ mainSession.loadTestPath(FULLSCREEN_PATH)
+ mainSession.waitForPageStop()
+ val promise = mainSession.evaluatePromiseJS("document.querySelector('#fullscreen').requestFullscreen()")
+ sessionRule.waitUntilCalled(object : ContentDelegate {
+ @AssertCalled(count = 1)
+ override fun onFullScreen(session: GeckoSession, fullScreen: Boolean) {
+ assertThat("Div went fullscreen", fullScreen, equalTo(true))
+ }
+ })
+ promise.value
+ }
+
+ private fun lockPortrait() {
+ val promise = mainSession.evaluatePromiseJS("screen.orientation.lock('portrait-primary')")
+ sessionRule.delegateDuringNextWait(object : OrientationController.OrientationDelegate {
+ @AssertCalled(count = 1)
+ override fun onOrientationLock(aOrientation: Int): GeckoResult<AllowOrDeny> {
+ assertThat(
+ "The orientation should be portrait",
+ aOrientation,
+ equalTo(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT),
+ )
+ activityRule.scenario.onActivity { activity ->
+ activity.requestedOrientation = aOrientation
+ }
+ return GeckoResult.allow()
+ }
+ })
+ sessionRule.runtime.orientationChanged(Configuration.ORIENTATION_PORTRAIT)
+ promise.value
+ // Remove previous delegate
+ mainSession.waitForRoundTrip()
+ }
+
+ private fun lockLandscape() {
+ val promise = mainSession.evaluatePromiseJS("screen.orientation.lock('landscape-primary')")
+ sessionRule.delegateDuringNextWait(object : OrientationController.OrientationDelegate {
+ @AssertCalled(count = 1)
+ override fun onOrientationLock(aOrientation: Int): GeckoResult<AllowOrDeny> {
+ assertThat(
+ "The orientation should be landscape",
+ aOrientation,
+ equalTo(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE),
+ )
+ activityRule.scenario.onActivity { activity ->
+ activity.requestedOrientation = aOrientation
+ }
+ return GeckoResult.allow()
+ }
+ })
+ sessionRule.runtime.orientationChanged(Configuration.ORIENTATION_LANDSCAPE)
+ promise.value
+ // Remove previous delegate
+ mainSession.waitForRoundTrip()
+ }
+
+ @Test fun orientationLock() {
+ goFullscreen()
+ activityRule.scenario.onActivity { activity ->
+ // If the orientation is landscape, lock to portrait and wait for delegate. If portrait, lock to landscape instead.
+ if (activity.resources.configuration.orientation == ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE) {
+ lockPortrait()
+ } else if (activity.resources.configuration.orientation == ActivityInfo.SCREEN_ORIENTATION_PORTRAIT) {
+ lockLandscape()
+ }
+ }
+ }
+
+ @Test fun orientationUnlock() {
+ goFullscreen()
+ mainSession.evaluateJS("screen.orientation.unlock()")
+ sessionRule.waitUntilCalled(object : OrientationController.OrientationDelegate {
+ @AssertCalled(count = 1)
+ override fun onOrientationUnlock() {
+ activityRule.scenario.onActivity { activity ->
+ activity.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED
+ }
+ }
+ })
+ }
+
+ @Test fun orientationLockedAlready() {
+ goFullscreen()
+ // Lock to landscape twice to verify successful locking with existing lock
+ lockLandscape()
+ lockLandscape()
+ }
+
+ @Test fun orientationLockedExistingOrientation() {
+ goFullscreen()
+
+ val promise = mainSession.evaluatePromiseJS(
+ """
+ new Promise(resolve => {
+ if (screen.orientation.type == "landscape-primary") {
+ resolve();
+ }
+ screen.orientation.addEventListener("change", e => {
+ if (screen.orientation.type == "landscape-primary") {
+ resolve();
+ }
+ }, { once: true });
+ })
+ """.trimIndent(),
+ )
+
+ // Lock to landscape twice to verify successful locking to existing orientation
+ activityRule.scenario.onActivity { activity ->
+ activity.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE
+ }
+ // Wait for orientation change by activity.requestedOrientation.
+ promise.value
+ lockLandscape()
+ }
+
+ @Test(expected = GeckoSessionTestRule.RejectedPromiseException::class)
+ fun orientationLockNoFullscreen() {
+ // Verify if fullscreen pre-lock conditions are not met, a rejected promise is returned.
+ mainSession.loadTestPath(FULLSCREEN_PATH)
+ mainSession.waitForPageStop()
+ mainSession.evaluateJS("screen.orientation.lock('landscape-primary')")
+ }
+
+ @Test fun orientationLockUnlock() {
+ goFullscreen()
+
+ val promise = mainSession.evaluatePromiseJS("screen.orientation.lock('landscape-primary')")
+ sessionRule.delegateDuringNextWait(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.scenario.onActivity { activity ->
+ activity.requestedOrientation = aOrientation
+ }
+ return GeckoResult.allow()
+ }
+ })
+ sessionRule.runtime.orientationChanged(Configuration.ORIENTATION_LANDSCAPE)
+ promise.value
+ // Remove previous delegate
+ mainSession.waitForRoundTrip()
+
+ // 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.scenario.onActivity { activity ->
+ activity.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED
+ }
+ }
+ })
+ }
+
+ @Test fun orientationLockUnsupported() {
+ // If no delegate, orientation.lock must throws NotSupportedError
+ goFullscreen()
+
+ val promise = mainSession.evaluatePromiseJS(
+ """
+ new Promise(r => {
+ screen.orientation.lock('landscape-primary')
+ .then(() => r("successful"))
+ .catch(e => r(e.name))
+ })
+ """.trimIndent(),
+ )
+
+ assertThat(
+ "The operation must throw NotSupportedError",
+ promise.value,
+ equalTo("NotSupportedError"),
+ )
+
+ val promise2 = mainSession.evaluatePromiseJS(
+ """
+ new Promise(r => {
+ screen.orientation.lock(screen.orientation.type)
+ .then(() => r("successful"))
+ .catch(e => r(e.name))
+ })
+ """.trimIndent(),
+ )
+
+ assertThat(
+ "The operation must throw NotSupportedError even if same orientation",
+ promise2.value,
+ equalTo("NotSupportedError"),
+ )
+ }
+
+ @WithDisplay(width = 300, height = 200)
+ @Test
+ fun orientationUnlockByExitFullscreen() {
+ goFullscreen()
+ activityRule.scenario.onActivity { activity ->
+ // If the orientation is landscape, lock to portrait and wait for delegate. If portrait, lock to landscape instead.
+ if (activity.resources.configuration.orientation == ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE) {
+ lockPortrait()
+ } else if (activity.resources.configuration.orientation == ActivityInfo.SCREEN_ORIENTATION_PORTRAIT) {
+ lockLandscape()
+ }
+ }
+
+ val promise = mainSession.evaluatePromiseJS("document.exitFullscreen()")
+ sessionRule.waitUntilCalled(object : ContentDelegate, OrientationController.OrientationDelegate {
+ @AssertCalled(count = 1)
+ override fun onFullScreen(session: GeckoSession, fullScreen: Boolean) {
+ assertThat("Exited fullscreen", fullScreen, equalTo(false))
+ }
+
+ @AssertCalled(count = 1)
+ override fun onOrientationUnlock() {
+ activityRule.scenario.onActivity { activity ->
+ activity.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED
+ }
+ }
+ })
+ promise.value
+ }
+
+ @WithDisplay(width = 200, height = 300)
+ @Test
+ fun orientationNatural() {
+ goFullscreen()
+
+ // Set orientation to landscape since natural is portrait.
+ var promise = mainSession.evaluatePromiseJS(
+ """
+ new Promise(resolve => {
+ if (screen.orientation.type == "landscape-primary") {
+ resolve();
+ }
+ screen.orientation.addEventListener("change", e => {
+ if (screen.orientation.type == "landscape-primary") {
+ resolve();
+ }
+ }, { once: true });
+ })
+ """.trimIndent(),
+ )
+
+ activityRule.scenario.onActivity { activity ->
+ activity.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE
+ }
+ // Wait for orientation change by activity.requestedOrientation.
+ promise.value
+
+ sessionRule.delegateDuringNextWait(object : OrientationController.OrientationDelegate {
+ @AssertCalled(count = 1)
+ override fun onOrientationLock(aOrientation: Int): GeckoResult<AllowOrDeny> {
+ assertThat(
+ "The orientation should be portrait",
+ aOrientation,
+ equalTo(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT),
+ )
+ activityRule.scenario.onActivity { activity ->
+ activity.requestedOrientation = aOrientation
+ }
+ return GeckoResult.allow()
+ }
+ })
+ promise = mainSession.evaluatePromiseJS("screen.orientation.lock('natural')")
+ promise.value
+ // Remove previous delegate
+ mainSession.waitForRoundTrip()
+ }
+}