Bug 1753574 - hal::LockOrientation can return error status. r=smaug,geckoview-reviewers,agi,calu

From https://w3c.github.io/screen-orientation/#apply-an-orientation-lock

> 7.2. Apply an orientation lock
>
> The steps to apply an orientation lock to a Document using orientation are as
> follows:
>
>  1. If the user agent does not support locking the screen orientation, return
>     a promise rejected with a "NotSupportedError" DOMException and abort
>     these steps.

So if orientation controller delegate isn't set, we should throw
`NotSupportedError`.  But, actually, we throws `AbortError`, so this isn't
correct.

To return any DOM error from platform implementation of
`screen.orientation.lock`, I would like to change return value to
`GenericPromise`'s.

Differential Revision: https://phabricator.services.mozilla.com/D137970
This commit is contained in:
Makoto Kato 2022-03-02 03:48:14 +00:00
parent ad14d19c54
commit 3493d2727e
11 changed files with 110 additions and 64 deletions

View File

@ -152,8 +152,6 @@ ScreenOrientation::LockOrientationTask::LockOrientationTask(
ScreenOrientation::LockOrientationTask::~LockOrientationTask() = default;
using LockOrientationPromise = MozPromise<bool, bool, false>;
bool ScreenOrientation::LockOrientationTask::OrientationLockContains(
OrientationType aOrientationType) {
return bool(mOrientationLock & OrientationTypeToInternal(aOrientationType));
@ -189,15 +187,16 @@ ScreenOrientation::LockOrientationTask::Run() {
}
mScreenOrientation->LockDeviceOrientation(mOrientationLock, mIsFullscreen)
->Then(GetCurrentSerialEventTarget(), __func__,
[self = RefPtr{this}](
const LockOrientationPromise::ResolveOrRejectValue& aValue) {
if (aValue.IsResolve()) {
return;
}
self->mPromise->MaybeReject(NS_ERROR_DOM_ABORT_ERR);
self->mDocument->ClearOrientationPendingPromise();
});
->Then(
GetCurrentSerialEventTarget(), __func__,
[self = RefPtr{this}](
const GenericNonExclusivePromise::ResolveOrRejectValue& aValue) {
if (aValue.IsResolve()) {
return;
}
self->mPromise->MaybeReject(aValue.RejectValue());
self->mDocument->ClearOrientationPendingPromise();
});
BrowsingContext* bc = mDocument->GetBrowsingContext();
if (OrientationLockContains(bc->GetCurrentOrientationType()) ||
@ -352,10 +351,11 @@ already_AddRefed<Promise> ScreenOrientation::LockInternal(
#endif
}
RefPtr<LockOrientationPromise> ScreenOrientation::LockDeviceOrientation(
RefPtr<GenericNonExclusivePromise> ScreenOrientation::LockDeviceOrientation(
hal::ScreenOrientation aOrientation, bool aIsFullscreen) {
if (!GetOwner()) {
return LockOrientationPromise::CreateAndReject(false, __func__);
return GenericNonExclusivePromise::CreateAndReject(NS_ERROR_DOM_ABORT_ERR,
__func__);
}
nsCOMPtr<EventTarget> target = GetOwner()->GetDoc();
@ -364,7 +364,8 @@ RefPtr<LockOrientationPromise> ScreenOrientation::LockDeviceOrientation(
// This needs to be done before LockScreenOrientation call to make sure
// the locking can be unlocked.
if (aIsFullscreen && !target) {
return LockOrientationPromise::CreateAndReject(false, __func__);
return GenericNonExclusivePromise::CreateAndReject(NS_ERROR_DOM_ABORT_ERR,
__func__);
}
// We are fullscreen and lock has been accepted.
@ -377,7 +378,8 @@ RefPtr<LockOrientationPromise> ScreenOrientation::LockDeviceOrientation(
mFullscreenListener,
/* aUseCapture = */ true);
if (NS_WARN_IF(NS_FAILED(rv))) {
return LockOrientationPromise::CreateAndReject(false, __func__);
return GenericNonExclusivePromise::CreateAndReject(NS_ERROR_DOM_ABORT_ERR,
__func__);
}
}
@ -552,8 +554,7 @@ void ScreenOrientation::UpdateActiveOrientationLock(
hal::LockScreenOrientation(aOrientation)
->Then(
GetMainThreadSerialEventTarget(), __func__,
[](const mozilla::MozPromise<bool, bool,
false>::ResolveOrRejectValue& aValue) {
[](const GenericNonExclusivePromise::ResolveOrRejectValue& aValue) {
NS_WARNING_ASSERTION(aValue.IsResolve(),
"hal::LockScreenOrientation failed");
});

View File

@ -74,7 +74,7 @@ class ScreenOrientation final : public DOMEventTargetHelper {
// This method calls into the HAL to lock the device and sets
// up listeners for full screen change.
RefPtr<MozPromise<bool, bool, false>> LockDeviceOrientation(
RefPtr<GenericNonExclusivePromise> LockDeviceOrientation(
hal::ScreenOrientation aOrientation, bool aIsFullscreen);
// This method calls in to the HAL to unlock the device and removes

View File

@ -378,7 +378,7 @@ void NotifyWakeLockChange(const WakeLockInformation& aInfo) {
WakeLockObservers()->BroadcastInformation(aInfo);
}
RefPtr<mozilla::MozPromise<bool, bool, false>> LockScreenOrientation(
RefPtr<GenericNonExclusivePromise> LockScreenOrientation(
const ScreenOrientation& aOrientation) {
AssertMainThread();
RETURN_PROXY_IF_SANDBOXED(LockScreenOrientation(aOrientation), nullptr);

View File

@ -220,8 +220,8 @@ void NotifyWakeLockChange(const hal::WakeLockInformation& aWakeLockInfo);
* Lock the screen orientation to the specific orientation.
* @return A promise indicating that the screen orientation has been locked.
*/
[[nodiscard]] RefPtr<mozilla::MozPromise<bool, bool, false>>
LockScreenOrientation(const hal::ScreenOrientation& aOrientation);
[[nodiscard]] RefPtr<GenericNonExclusivePromise> LockScreenOrientation(
const hal::ScreenOrientation& aOrientation);
/**
* Unlock the screen orientation.

View File

@ -101,25 +101,39 @@ static bool IsSupportedScreenOrientation(hal::ScreenOrientation aOrientation) {
return false;
}
RefPtr<MozPromise<bool, bool, false>> LockScreenOrientation(
RefPtr<GenericNonExclusivePromise> LockScreenOrientation(
const hal::ScreenOrientation& aOrientation) {
using LockPromise = MozPromise<bool, bool, false>;
if (!IsSupportedScreenOrientation(aOrientation)) {
NS_WARNING("Unsupported screen orientation type");
return LockPromise::CreateAndReject(false, __func__);
return GenericNonExclusivePromise::CreateAndReject(
NS_ERROR_DOM_NOT_SUPPORTED_ERR, __func__);
}
java::GeckoRuntime::LocalRef runtime = java::GeckoRuntime::GetInstance();
if (!runtime) {
return LockPromise::CreateAndReject(false, __func__);
return GenericNonExclusivePromise::CreateAndReject(NS_ERROR_DOM_ABORT_ERR,
__func__);
}
auto result = runtime->LockScreenOrientation(uint32_t(aOrientation));
auto geckoResult = java::GeckoResult::LocalRef(std::move(result));
if (!geckoResult) {
return LockPromise::CreateAndReject(false, __func__);
}
return LockPromise::FromGeckoResult(geckoResult);
return GenericNonExclusivePromise::FromGeckoResult(geckoResult)
->Then(
GetCurrentSerialEventTarget(), __func__,
[](const GenericNonExclusivePromise::ResolveOrRejectValue& aValue) {
if (aValue.IsResolve()) {
if (aValue.ResolveValue()) {
return GenericNonExclusivePromise::CreateAndResolve(true,
__func__);
}
// Delegated orientation controller returns failure for
// lock.
return GenericNonExclusivePromise::CreateAndReject(
NS_ERROR_DOM_ABORT_ERR, __func__);
}
// Browser side doesn't implement orientation delegate.
return GenericNonExclusivePromise::CreateAndReject(
NS_ERROR_DOM_NOT_SUPPORTED_ERR, __func__);
});
}
void UnlockScreenOrientation() {

View File

@ -6,10 +6,10 @@
namespace mozilla::hal_impl {
RefPtr<mozilla::MozPromise<bool, bool, false>> LockScreenOrientation(
RefPtr<GenericNonExclusivePromise> LockScreenOrientation(
const hal::ScreenOrientation& aOrientation) {
return mozilla::MozPromise<bool, bool, false>::CreateAndReject(false,
__func__);
return GenericNonExclusivePromise::CreateAndReject(
NS_ERROR_DOM_NOT_SUPPORTED_ERR, __func__);
}
void UnlockScreenOrientation() {}

View File

@ -82,7 +82,7 @@ parent:
returns (WakeLockInformation aWakeLockInfo);
async LockScreenOrientation(ScreenOrientation aOrientation)
returns (bool allowed);
returns (nsresult result);
async UnlockScreenOrientation();
child:

View File

@ -69,21 +69,24 @@ void GetCurrentNetworkInformation(NetworkInformation* aNetworkInfo) {
Hal()->SendGetCurrentNetworkInformation(aNetworkInfo);
}
RefPtr<mozilla::MozPromise<bool, bool, false>> LockScreenOrientation(
RefPtr<GenericNonExclusivePromise> LockScreenOrientation(
const hal::ScreenOrientation& aOrientation) {
return Hal()
->SendLockScreenOrientation(aOrientation)
->Then(
GetCurrentSerialEventTarget(), __func__,
[=](const mozilla::MozPromise<bool, ipc::ResponseRejectReason,
true>::ResolveOrRejectValue& aValue) {
if (aValue.IsResolve() && aValue.ResolveValue()) {
return mozilla::MozPromise<bool, bool, false>::CreateAndResolve(
true, __func__);
}
return mozilla::MozPromise<bool, bool, false>::CreateAndReject(
false, __func__);
});
->Then(GetCurrentSerialEventTarget(), __func__,
[](const mozilla::MozPromise<nsresult, ipc::ResponseRejectReason,
true>::ResolveOrRejectValue& aValue) {
if (aValue.IsResolve()) {
if (NS_SUCCEEDED(aValue.ResolveValue())) {
return GenericNonExclusivePromise::CreateAndResolve(
true, __func__);
}
return GenericNonExclusivePromise::CreateAndReject(
aValue.ResolveValue(), __func__);
}
return GenericNonExclusivePromise::CreateAndReject(
NS_ERROR_FAILURE, __func__);
});
}
void UnlockScreenOrientation() { Hal()->SendUnlockScreenOrientation(); }
@ -223,15 +226,17 @@ class HalParent : public PHalParent,
// fullscreen. We don't have that information currently.
hal::LockScreenOrientation(aOrientation)
->Then(GetMainThreadSerialEventTarget(), __func__,
[aResolve](const mozilla::MozPromise<
bool, bool, false>::ResolveOrRejectValue& aValue) {
if (aValue.IsResolve()) {
aResolve(aValue.ResolveValue());
} else {
aResolve(false);
}
});
->Then(
GetMainThreadSerialEventTarget(), __func__,
[aResolve](const GenericNonExclusivePromise::ResolveOrRejectValue&
aValue) {
if (aValue.IsResolve()) {
MOZ_ASSERT(aValue.ResolveValue());
aResolve(NS_OK);
return;
}
aResolve(aValue.RejectValue());
});
return IPC_OK();
}

View File

@ -178,4 +178,22 @@ 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("""
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"))
}
}

View File

@ -919,16 +919,18 @@ public final class GeckoRuntime implements Parcelable {
final OrientationController.OrientationDelegate delegate =
getOrientationController().getDelegate();
if (delegate == null) {
res.complete(false);
} else {
final GeckoResult<AllowOrDeny> response =
delegate.onOrientationLock(toAndroidOrientation(aOrientation));
if (response == null) {
res.complete(false);
} else {
res.completeFrom(response.map(v -> v == AllowOrDeny.ALLOW));
}
// Delegate is not set
res.completeExceptionally(new Exception("Not supported"));
return;
}
final GeckoResult<AllowOrDeny> response =
delegate.onOrientationLock(toAndroidOrientation(aOrientation));
if (response == null) {
// Delegate is default. So lock orientation is not implemented
res.completeExceptionally(new Exception("Not supported"));
return;
}
res.completeFrom(response.map(v -> v == AllowOrDeny.ALLOW));
});
return res;
}

View File

@ -103,5 +103,11 @@ nsString Java2Native(mozilla::jni::Object::Param aData, JNIEnv* aEnv) {
return result;
}
template <>
nsresult Java2Native(mozilla::jni::Object::Param aData, JNIEnv* aEnv) {
MOZ_ASSERT(aData.IsInstanceOf<jni::Throwable>());
return NS_ERROR_FAILURE;
}
} // namespace jni
} // namespace mozilla