Commit f3ee106f authored by Makoto Kato's avatar Makoto Kato
Browse files

Bug 1750670 - Better support orientation.lock('natural'). r=geckoview-reviewers,calu

natural is defined as (from https://w3c.github.io/screen-orientation/#dfn-natural)

> A computer monitor are commonly naturally landscape-primary, while a mobile
> phones are commonly naturally portrait-primary.

But GeckoView sets `SCREEN_ORIENTATION_UNSPECIFIED` that is unlock orientation.

Like Blink, we should set landscape-primary or portrait-primary (depends on
current monitor).

Differential Revision: https://phabricator.services.mozilla.com/D164436
parent 0dcbfc50
Loading
Loading
Loading
Loading
+13 −1
Original line number Diff line number Diff line
@@ -114,7 +114,19 @@ RefPtr<GenericNonExclusivePromise> LockScreenOrientation(
    return GenericNonExclusivePromise::CreateAndReject(NS_ERROR_DOM_ABORT_ERR,
                                                       __func__);
  }
  auto result = runtime->LockScreenOrientation(uint32_t(aOrientation));

  hal::ScreenOrientation orientation = [&aOrientation]() {
    if (aOrientation == hal::ScreenOrientation::Default) {
      // GeckoView only supports single monitor, so get primary screen data for
      // natural orientation.
      RefPtr<widget::Screen> screen =
          widget::ScreenManager::GetSingleton().GetPrimaryScreen();
      return screen->GetDefaultOrientationType();
    }
    return aOrientation;
  }();

  auto result = runtime->LockScreenOrientation(uint32_t(orientation));
  auto geckoResult = java::GeckoResult::LocalRef(std::move(result));
  return GenericNonExclusivePromise::FromGeckoResult(geckoResult)
      ->Then(
+53 −9
Original line number Diff line number Diff line
@@ -10,6 +10,7 @@ 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
@@ -29,6 +30,11 @@ class OrientationDelegateTest : BaseSessionTest() {
    @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)
@@ -88,7 +94,6 @@ class OrientationDelegateTest : BaseSessionTest() {
    }

    @Test fun orientationLock() {
        sessionRule.setPrefsUntilTestEnd(mapOf("dom.screenorientation.allow-lock" to true))
        goFullscreen()
        activityRule.scenario.onActivity { activity ->
            // If the orientation is landscape, lock to portrait and wait for delegate. If portrait, lock to landscape instead.
@@ -101,7 +106,6 @@ class OrientationDelegateTest : BaseSessionTest() {
    }

    @Test fun orientationUnlock() {
        sessionRule.setPrefsUntilTestEnd(mapOf("dom.screenorientation.allow-lock" to true))
        goFullscreen()
        mainSession.evaluateJS("screen.orientation.unlock()")
        sessionRule.waitUntilCalled(object : OrientationController.OrientationDelegate {
@@ -115,7 +119,6 @@ class OrientationDelegateTest : BaseSessionTest() {
    }

    @Test fun orientationLockedAlready() {
        sessionRule.setPrefsUntilTestEnd(mapOf("dom.screenorientation.allow-lock" to true))
        goFullscreen()
        // Lock to landscape twice to verify successful locking with existing lock
        lockLandscape()
@@ -123,7 +126,6 @@ class OrientationDelegateTest : BaseSessionTest() {
    }

    @Test fun orientationLockedExistingOrientation() {
        sessionRule.setPrefsUntilTestEnd(mapOf("dom.screenorientation.allow-lock" to true))
        goFullscreen()
        // Lock to landscape twice to verify successful locking to existing orientation
        activityRule.scenario.onActivity { activity ->
@@ -135,14 +137,12 @@ class OrientationDelegateTest : BaseSessionTest() {
    @Test(expected = GeckoSessionTestRule.RejectedPromiseException::class)
    fun orientationLockNoFullscreen() {
        // Verify if fullscreen pre-lock conditions are not met, a rejected promise is returned.
        sessionRule.setPrefsUntilTestEnd(mapOf("dom.screenorientation.allow-lock" to true))
        mainSession.loadTestPath(FULLSCREEN_PATH)
        mainSession.waitForPageStop()
        mainSession.evaluateJS("screen.orientation.lock('landscape-primary')")
    }

    @Test fun orientationLockUnlock() {
        sessionRule.setPrefsUntilTestEnd(mapOf("dom.screenorientation.allow-lock" to true))
        goFullscreen()

        val promise = mainSession.evaluatePromiseJS("screen.orientation.lock('landscape-primary')")
@@ -179,7 +179,6 @@ class OrientationDelegateTest : BaseSessionTest() {

    @Test fun orientationLockUnsupported() {
        // If no delegate, orientation.lock must throws NotSupportedError
        sessionRule.setPrefsUntilTestEnd(mapOf("dom.screenorientation.allow-lock" to true))
        goFullscreen()

        val promise = mainSession.evaluatePromiseJS(
@@ -218,8 +217,6 @@ class OrientationDelegateTest : BaseSessionTest() {
    @WithDisplay(width = 300, height = 200)
    @Test
    fun orientationUnlockByExitFullscreen() {
        sessionRule.setPrefsUntilTestEnd(mapOf("dom.screenorientation.allow-lock" to true))

        goFullscreen()
        activityRule.scenario.onActivity { activity ->
            // If the orientation is landscape, lock to portrait and wait for delegate. If portrait, lock to landscape instead.
@@ -246,4 +243,51 @@ class OrientationDelegateTest : BaseSessionTest() {
        })
        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()
    }
}