Commit 623627fa authored by Cathy Lu's avatar Cathy Lu
Browse files

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
parent 2b242540
Loading
Loading
Loading
Loading
+8 −9
Original line number Diff line number Diff line
@@ -126,13 +126,7 @@ void GetCurrentScreenConfiguration(ScreenConfiguration* aScreenConfiguration) {

RefPtr<MozPromise<bool, bool, false>> LockScreenOrientation(
    const hal::ScreenOrientation& aOrientation) {
  // Force the default orientation to be portrait-primary.
  hal::ScreenOrientation orientation =
      aOrientation == eScreenOrientation_Default
          ? eScreenOrientation_PortraitPrimary
          : aOrientation;

  switch (orientation) {
  switch (aOrientation) {
    // The Android backend only supports these orientations.
    case eScreenOrientation_PortraitPrimary:
    case eScreenOrientation_PortraitSecondary:
@@ -145,7 +139,7 @@ RefPtr<MozPromise<bool, bool, false>> LockScreenOrientation(
    case eScreenOrientation_Default: {
      java::GeckoRuntime::LocalRef runtime = java::GeckoRuntime::GetInstance();
      if (runtime != NULL) {
        auto result = runtime->LockScreenOrientation(orientation);
        auto result = runtime->LockScreenOrientation(aOrientation);
        auto geckoResult = java::GeckoResult::LocalRef(std::move(result));
        return 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 mozilla
+67 −21
Original line number Diff line number Diff line
@@ -46,24 +46,32 @@ class OrientationDelegateTest : BaseSessionTest() {
        promise.value
    }

    @Ignore("disable test for frequently failing Bug 1744372")
    @Test fun orientationLockedAlready() {
        sessionRule.setPrefsUntilTestEnd(mapOf("dom.screenorientation.allow-lock" to true))
        goFullscreen()
        // Lock to the current orientation
        if (activityRule.activity.resources.configuration.orientation == ActivityInfo.SCREEN_ORIENTATION_PORTRAIT){
    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
        } else if (activityRule.activity.resources.configuration.orientation == ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE) {
    }

    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")
    @Test fun orientationLockedAlready() {
        sessionRule.setPrefsUntilTestEnd(mapOf("dom.screenorientation.allow-lock" to true))
        goFullscreen()
        // Lock to the current orientation
        if (activityRule.activity.resources.configuration.orientation == ActivityInfo.SCREEN_ORIENTATION_PORTRAIT){
            lockPortrait()
        } else if (activityRule.activity.resources.configuration.orientation == ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE) {
            lockLandscape()
        }
    }

    @Test(expected = GeckoSessionTestRule.RejectedPromiseException::class)
@@ -81,23 +89,61 @@ class OrientationDelegateTest : BaseSessionTest() {
        goFullscreen()
        // 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){
            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
            lockPortrait()
        } 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')")
            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)
        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 {
        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
            return GeckoResult.allow()
        }
+15 −0
Original line number Diff line number Diff line
@@ -871,6 +871,8 @@ public final class GeckoRuntime implements Parcelable {
      return ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
    } else if (geckoOrientation == ScreenOrientation.LANDSCAPE_SECONDARY.value) {
      return ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE;
    } else if (geckoOrientation == ScreenOrientation.DEFAULT.value) {
      return ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
    }
    return ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
  }
@@ -902,6 +904,19 @@ public final class GeckoRuntime implements Parcelable {
    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
   * persistent storage data accumulated by {@link GeckoSession}.