зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1753919 - AndroidWebAuthnTokenManager uses GeckoResult directly instead of callback. r=geckoview-reviewers,agi
Since WebAuthnTokenManager uses GeckoReuslt, we can remove callback of WebAuthnTokenManager. Differential Revision: https://phabricator.services.mozilla.com/D137973
This commit is contained in:
Родитель
988ddd76dc
Коммит
926307a1d7
|
@ -10,9 +10,38 @@
|
|||
|
||||
#include "AndroidWebAuthnTokenManager.h"
|
||||
#include "JavaBuiltins.h"
|
||||
#include "JavaExceptions.h"
|
||||
#include "mozilla/java/WebAuthnTokenManagerWrappers.h"
|
||||
#include "mozilla/jni/Conversions.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace jni {
|
||||
|
||||
template <>
|
||||
dom::AndroidWebAuthnResult Java2Native(mozilla::jni::Object::Param aData,
|
||||
JNIEnv* aEnv) {
|
||||
// TODO:
|
||||
// AndroidWebAuthnResult stores successful both result and failure result.
|
||||
// We should split it into success and failure (Bug 1754157)
|
||||
if (aData.IsInstanceOf<jni::Throwable>()) {
|
||||
java::sdk::Throwable::LocalRef throwable(aData);
|
||||
return dom::AndroidWebAuthnResult(throwable->GetMessage()->ToString());
|
||||
}
|
||||
|
||||
if (aData
|
||||
.IsInstanceOf<java::WebAuthnTokenManager::MakeCredentialResponse>()) {
|
||||
java::WebAuthnTokenManager::MakeCredentialResponse::LocalRef response(
|
||||
aData);
|
||||
return dom::AndroidWebAuthnResult(response);
|
||||
}
|
||||
|
||||
MOZ_ASSERT(
|
||||
aData.IsInstanceOf<java::WebAuthnTokenManager::GetAssertionResponse>());
|
||||
java::WebAuthnTokenManager::GetAssertionResponse::LocalRef response(aData);
|
||||
return dom::AndroidWebAuthnResult(response);
|
||||
}
|
||||
} // namespace jni
|
||||
|
||||
namespace dom {
|
||||
|
||||
static nsIThread* gAndroidPBackgroundThread;
|
||||
|
@ -65,7 +94,7 @@ RefPtr<U2FRegisterPromise> AndroidWebAuthnTokenManager::Register(
|
|||
|
||||
GetMainThreadEventTarget()->Dispatch(NS_NewRunnableFunction(
|
||||
"java::WebAuthnTokenManager::WebAuthnMakeCredential",
|
||||
[aInfo, aForceNoneAttestation]() {
|
||||
[self = RefPtr{this}, aInfo, aForceNoneAttestation]() {
|
||||
AssertIsOnMainThread();
|
||||
|
||||
// Produce the credential exclusion list
|
||||
|
@ -193,9 +222,22 @@ RefPtr<U2FRegisterPromise> AndroidWebAuthnTokenManager::Register(
|
|||
const_cast<void*>(static_cast<const void*>(uidBuf.Elements())),
|
||||
uidBuf.Length());
|
||||
|
||||
java::WebAuthnTokenManager::WebAuthnMakeCredential(
|
||||
auto result = java::WebAuthnTokenManager::WebAuthnMakeCredential(
|
||||
credentialBundle, uid, challenge, idList, transportList,
|
||||
authSelBundle, extensionsBundle);
|
||||
auto geckoResult = java::GeckoResult::LocalRef(std::move(result));
|
||||
// This is likely running on the main thread, so we'll always dispatch
|
||||
// to the background for state updates.
|
||||
MozPromise<AndroidWebAuthnResult, AndroidWebAuthnResult,
|
||||
false>::FromGeckoResult(geckoResult)
|
||||
->Then(
|
||||
GetMainThreadSerialEventTarget(), __func__,
|
||||
[self = std::move(self)](const AndroidWebAuthnResult& aValue) {
|
||||
self->HandleRegisterResult(aValue);
|
||||
},
|
||||
[self = std::move(self)](const AndroidWebAuthnResult& aValue) {
|
||||
self->HandleRegisterResult(aValue);
|
||||
});
|
||||
}));
|
||||
|
||||
return mRegisterPromise.Ensure(__func__);
|
||||
|
@ -203,6 +245,10 @@ RefPtr<U2FRegisterPromise> AndroidWebAuthnTokenManager::Register(
|
|||
|
||||
void AndroidWebAuthnTokenManager::HandleRegisterResult(
|
||||
const AndroidWebAuthnResult& aResult) {
|
||||
if (!gAndroidPBackgroundThread) {
|
||||
// Promise is already rejected when shutting down background thread
|
||||
return;
|
||||
}
|
||||
// This is likely running on the main thread, so we'll always dispatch to the
|
||||
// background for state updates.
|
||||
if (aResult.IsError()) {
|
||||
|
@ -234,7 +280,8 @@ RefPtr<U2FSignPromise> AndroidWebAuthnTokenManager::Sign(
|
|||
ClearPromises();
|
||||
|
||||
GetMainThreadEventTarget()->Dispatch(NS_NewRunnableFunction(
|
||||
"java::WebAuthnTokenManager::WebAuthnGetAssertion", [aInfo]() {
|
||||
"java::WebAuthnTokenManager::WebAuthnGetAssertion",
|
||||
[self = RefPtr{this}, aInfo]() {
|
||||
AssertIsOnMainThread();
|
||||
|
||||
jni::ObjectArray::LocalRef idList =
|
||||
|
@ -298,9 +345,20 @@ RefPtr<U2FSignPromise> AndroidWebAuthnTokenManager::Sign(
|
|||
GECKOBUNDLE_FINISH(assertionBundle);
|
||||
GECKOBUNDLE_FINISH(extensionsBundle);
|
||||
|
||||
java::WebAuthnTokenManager::WebAuthnGetAssertion(
|
||||
auto result = java::WebAuthnTokenManager::WebAuthnGetAssertion(
|
||||
challenge, idList, transportList, assertionBundle,
|
||||
extensionsBundle);
|
||||
auto geckoResult = java::GeckoResult::LocalRef(std::move(result));
|
||||
MozPromise<AndroidWebAuthnResult, AndroidWebAuthnResult,
|
||||
false>::FromGeckoResult(geckoResult)
|
||||
->Then(
|
||||
GetMainThreadSerialEventTarget(), __func__,
|
||||
[self = std::move(self)](const AndroidWebAuthnResult& aValue) {
|
||||
self->HandleSignResult(aValue);
|
||||
},
|
||||
[self = std::move(self)](const AndroidWebAuthnResult& aValue) {
|
||||
self->HandleSignResult(aValue);
|
||||
});
|
||||
}));
|
||||
|
||||
return mSignPromise.Ensure(__func__);
|
||||
|
@ -308,6 +366,10 @@ RefPtr<U2FSignPromise> AndroidWebAuthnTokenManager::Sign(
|
|||
|
||||
void AndroidWebAuthnTokenManager::HandleSignResult(
|
||||
const AndroidWebAuthnResult& aResult) {
|
||||
if (!gAndroidPBackgroundThread) {
|
||||
// Promise is already rejected when shutting down background thread
|
||||
return;
|
||||
}
|
||||
// This is likely running on the main thread, so we'll always dispatch to the
|
||||
// background for state updates.
|
||||
if (aResult.IsError()) {
|
||||
|
@ -340,5 +402,41 @@ void AndroidWebAuthnTokenManager::Cancel() {
|
|||
ClearPromises();
|
||||
}
|
||||
|
||||
AndroidWebAuthnResult::AndroidWebAuthnResult(
|
||||
const java::WebAuthnTokenManager::MakeCredentialResponse::LocalRef&
|
||||
aResponse) {
|
||||
mClientDataJSON.Assign(
|
||||
reinterpret_cast<const char*>(
|
||||
aResponse->ClientDataJson()->GetElements().Elements()),
|
||||
aResponse->ClientDataJson()->Length());
|
||||
mKeyHandle.Assign(reinterpret_cast<uint8_t*>(
|
||||
aResponse->KeyHandle()->GetElements().Elements()),
|
||||
aResponse->KeyHandle()->Length());
|
||||
mAttObj.Assign(reinterpret_cast<uint8_t*>(
|
||||
aResponse->AttestationObject()->GetElements().Elements()),
|
||||
aResponse->AttestationObject()->Length());
|
||||
}
|
||||
|
||||
AndroidWebAuthnResult::AndroidWebAuthnResult(
|
||||
const java::WebAuthnTokenManager::GetAssertionResponse::LocalRef&
|
||||
aResponse) {
|
||||
mClientDataJSON.Assign(
|
||||
reinterpret_cast<const char*>(
|
||||
aResponse->ClientDataJson()->GetElements().Elements()),
|
||||
aResponse->ClientDataJson()->Length());
|
||||
mKeyHandle.Assign(reinterpret_cast<uint8_t*>(
|
||||
aResponse->KeyHandle()->GetElements().Elements()),
|
||||
aResponse->KeyHandle()->Length());
|
||||
mAuthData.Assign(reinterpret_cast<uint8_t*>(
|
||||
aResponse->AuthData()->GetElements().Elements()),
|
||||
aResponse->AuthData()->Length());
|
||||
mSignature.Assign(reinterpret_cast<uint8_t*>(
|
||||
aResponse->Signature()->GetElements().Elements()),
|
||||
aResponse->Signature()->Length());
|
||||
mUserHandle.Assign(reinterpret_cast<uint8_t*>(
|
||||
aResponse->UserHandle()->GetElements().Elements()),
|
||||
aResponse->UserHandle()->Length());
|
||||
}
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
|
||||
#include "mozilla/dom/CryptoBuffer.h"
|
||||
#include "mozilla/dom/U2FTokenTransport.h"
|
||||
#include "mozilla/java/WebAuthnTokenManagerNatives.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
@ -32,7 +33,15 @@ class AndroidWebAuthnResult {
|
|||
explicit AndroidWebAuthnResult(const nsAString& aErrorCode)
|
||||
: mErrorCode(aErrorCode) {}
|
||||
|
||||
explicit AndroidWebAuthnResult() {}
|
||||
explicit AndroidWebAuthnResult(
|
||||
const java::WebAuthnTokenManager::MakeCredentialResponse::LocalRef&
|
||||
aResponse);
|
||||
|
||||
explicit AndroidWebAuthnResult(
|
||||
const java::WebAuthnTokenManager::GetAssertionResponse::LocalRef&
|
||||
aResponse);
|
||||
|
||||
AndroidWebAuthnResult() = delete;
|
||||
|
||||
bool IsError() const { return NS_FAILED(GetError()); }
|
||||
|
||||
|
@ -114,13 +123,13 @@ class AndroidWebAuthnTokenManager final : public U2FTokenTransport {
|
|||
|
||||
void Drop() override;
|
||||
|
||||
static AndroidWebAuthnTokenManager* GetInstance();
|
||||
|
||||
private:
|
||||
void HandleRegisterResult(const AndroidWebAuthnResult& aResult);
|
||||
|
||||
void HandleSignResult(const AndroidWebAuthnResult& aResult);
|
||||
|
||||
static AndroidWebAuthnTokenManager* GetInstance();
|
||||
|
||||
private:
|
||||
void ClearPromises() {
|
||||
mRegisterPromise.RejectIfExists(NS_ERROR_DOM_UNKNOWN_ERR, __func__);
|
||||
mSignPromise.RejectIfExists(NS_ERROR_DOM_UNKNOWN_ERR, __func__);
|
||||
|
|
|
@ -118,6 +118,7 @@ import org.mozilla.gecko.util.GeckoBundle;
|
|||
DIRECT,
|
||||
}
|
||||
|
||||
@WrapForJNI
|
||||
public static class MakeCredentialResponse {
|
||||
public final byte[] clientDataJson;
|
||||
public final byte[] keyHandle;
|
||||
|
@ -301,7 +302,6 @@ import org.mozilla.gecko.util.GeckoBundle;
|
|||
}
|
||||
},
|
||||
e -> {
|
||||
Log.w(LOGTAG, "Failed to launch activity: ", e);
|
||||
Log.w(LOGTAG, "Failed to launch activity: ", e);
|
||||
result.completeExceptionally(new WebAuthnTokenManager.Exception("ABORT_ERR"));
|
||||
});
|
||||
|
@ -317,7 +317,7 @@ import org.mozilla.gecko.util.GeckoBundle;
|
|||
}
|
||||
|
||||
@WrapForJNI(calledFrom = "gecko")
|
||||
private static void webAuthnMakeCredential(
|
||||
private static GeckoResult<MakeCredentialResponse> webAuthnMakeCredential(
|
||||
final GeckoBundle credentialBundle,
|
||||
final ByteBuffer userId,
|
||||
final ByteBuffer challenge,
|
||||
|
@ -327,8 +327,6 @@ import org.mozilla.gecko.util.GeckoBundle;
|
|||
final GeckoBundle extensions) {
|
||||
final ArrayList<WebAuthnPublicCredential> excludeList;
|
||||
|
||||
// TODO: Return a GeckoResult instead, Bug 1550116
|
||||
|
||||
final byte[] challBytes = new byte[challenge.remaining()];
|
||||
final byte[] userBytes = new byte[userId.remaining()];
|
||||
try {
|
||||
|
@ -338,44 +336,28 @@ import org.mozilla.gecko.util.GeckoBundle;
|
|||
excludeList = WebAuthnPublicCredential.CombineBuffers(idList, transportList);
|
||||
} catch (final RuntimeException e) {
|
||||
Log.w(LOGTAG, "Couldn't extract nio byte arrays!", e);
|
||||
webAuthnMakeCredentialReturnError("UNKNOWN_ERR");
|
||||
return;
|
||||
return GeckoResult.fromException(new WebAuthnTokenManager.Exception("UNKNOWN_ERR"));
|
||||
}
|
||||
|
||||
try {
|
||||
final GeckoResult<MakeCredentialResponse> result =
|
||||
makeCredential(
|
||||
credentialBundle,
|
||||
userBytes,
|
||||
challBytes,
|
||||
excludeList.toArray(new WebAuthnPublicCredential[0]),
|
||||
authenticatorSelection,
|
||||
extensions);
|
||||
result.accept(
|
||||
cred -> {
|
||||
webAuthnMakeCredentialFinish(
|
||||
cred.clientDataJson, cred.keyHandle, cred.attestationObject);
|
||||
},
|
||||
e -> {
|
||||
webAuthnGetAssertionReturnError(e.getMessage());
|
||||
});
|
||||
return makeCredential(
|
||||
credentialBundle,
|
||||
userBytes,
|
||||
challBytes,
|
||||
excludeList.toArray(new WebAuthnPublicCredential[0]),
|
||||
authenticatorSelection,
|
||||
extensions);
|
||||
} catch (final Exception e) {
|
||||
// We need to ensure we catch any possible exception here in order to ensure
|
||||
// that the Promise on the content side is appropriately rejected. In particular,
|
||||
// we will get `NoClassDefFoundError` if we're running on a device that does not
|
||||
// have Google Play Services.
|
||||
Log.w(LOGTAG, "Couldn't make credential", e);
|
||||
webAuthnMakeCredentialReturnError("UNKNOWN_ERR");
|
||||
return GeckoResult.fromException(new WebAuthnTokenManager.Exception("UNKNOWN_ERR"));
|
||||
}
|
||||
}
|
||||
|
||||
@WrapForJNI(dispatchTo = "gecko")
|
||||
/* package */ static native void webAuthnMakeCredentialFinish(
|
||||
final byte[] clientDataJson, final byte[] keyHandle, final byte[] attestationObject);
|
||||
|
||||
@WrapForJNI(dispatchTo = "gecko")
|
||||
/* package */ static native void webAuthnMakeCredentialReturnError(String errorCode);
|
||||
|
||||
@WrapForJNI
|
||||
public static class GetAssertionResponse {
|
||||
public final byte[] clientDataJson;
|
||||
public final byte[] keyHandle;
|
||||
|
@ -412,7 +394,7 @@ import org.mozilla.gecko.util.GeckoBundle;
|
|||
return new WebAuthnTokenManager.Exception(responseData.getErrorCode().name());
|
||||
}
|
||||
|
||||
public static GeckoResult<GetAssertionResponse> getAssertion(
|
||||
private static GeckoResult<GetAssertionResponse> getAssertion(
|
||||
final byte[] challenge,
|
||||
final WebAuthnTokenManager.WebAuthnPublicCredential[] allowList,
|
||||
final GeckoBundle assertionBundle,
|
||||
|
@ -533,7 +515,7 @@ import org.mozilla.gecko.util.GeckoBundle;
|
|||
}
|
||||
|
||||
@WrapForJNI(calledFrom = "gecko")
|
||||
private static void webAuthnGetAssertion(
|
||||
private static GeckoResult<GetAssertionResponse> webAuthnGetAssertion(
|
||||
final ByteBuffer challenge,
|
||||
final Object[] idList,
|
||||
final ByteBuffer transportList,
|
||||
|
@ -541,53 +523,27 @@ import org.mozilla.gecko.util.GeckoBundle;
|
|||
final GeckoBundle extensions) {
|
||||
final ArrayList<WebAuthnPublicCredential> allowList;
|
||||
|
||||
// TODO: Return a GeckoResult instead, Bug 1550116
|
||||
|
||||
final byte[] challBytes = new byte[challenge.remaining()];
|
||||
try {
|
||||
challenge.get(challBytes);
|
||||
allowList = WebAuthnPublicCredential.CombineBuffers(idList, transportList);
|
||||
} catch (final RuntimeException e) {
|
||||
Log.w(LOGTAG, "Couldn't extract nio byte arrays!", e);
|
||||
webAuthnGetAssertionReturnError("UNKNOWN_ERR");
|
||||
return;
|
||||
return GeckoResult.fromException(new WebAuthnTokenManager.Exception("UNKNOWN_ERR"));
|
||||
}
|
||||
|
||||
try {
|
||||
getAssertion(
|
||||
challBytes,
|
||||
allowList.toArray(new WebAuthnPublicCredential[0]),
|
||||
assertionBundle,
|
||||
extensions)
|
||||
.accept(
|
||||
response -> {
|
||||
webAuthnGetAssertionFinish(
|
||||
response.clientDataJson,
|
||||
response.keyHandle,
|
||||
response.authData,
|
||||
response.signature,
|
||||
response.userHandle);
|
||||
},
|
||||
e -> {
|
||||
webAuthnGetAssertionReturnError(e.getMessage());
|
||||
});
|
||||
return getAssertion(
|
||||
challBytes,
|
||||
allowList.toArray(new WebAuthnPublicCredential[0]),
|
||||
assertionBundle,
|
||||
extensions);
|
||||
} catch (final java.lang.Exception e) {
|
||||
Log.w(LOGTAG, "Couldn't get assertion", e);
|
||||
webAuthnGetAssertionReturnError("UNKNOWN_ERR");
|
||||
return GeckoResult.fromException(new WebAuthnTokenManager.Exception("UNKNOWN_ERR"));
|
||||
}
|
||||
}
|
||||
|
||||
@WrapForJNI(dispatchTo = "gecko")
|
||||
/* package */ static native void webAuthnGetAssertionFinish(
|
||||
final byte[] clientDataJson,
|
||||
final byte[] keyHandle,
|
||||
final byte[] authData,
|
||||
final byte[] signature,
|
||||
final byte[] userHandle);
|
||||
|
||||
@WrapForJNI(dispatchTo = "gecko")
|
||||
/* package */ static native void webAuthnGetAssertionReturnError(String errorCode);
|
||||
|
||||
@WrapForJNI(calledFrom = "gecko")
|
||||
private static GeckoResult<Boolean> webAuthnIsUserVerifyingPlatformAuthenticatorAvailable() {
|
||||
final Task<Boolean> task;
|
||||
|
|
|
@ -1,79 +0,0 @@
|
|||
/* -*- Mode: c++; c-basic-offset: 2; tab-width: 20; indent-tabs-mode: nil; -*-
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef WebAuthnTokenManager_h
|
||||
#define WebAuthnTokenManager_h
|
||||
|
||||
#include "mozilla/dom/AndroidWebAuthnTokenManager.h"
|
||||
|
||||
#include "mozilla/java/WebAuthnTokenManagerNatives.h"
|
||||
|
||||
namespace mozilla {
|
||||
class WebAuthnTokenManager final
|
||||
: public java::WebAuthnTokenManager::Natives<WebAuthnTokenManager> {
|
||||
public:
|
||||
static void WebAuthnMakeCredentialFinish(
|
||||
jni::ByteArray::Param aClientDataJson, jni::ByteArray::Param aKeyHandle,
|
||||
jni::ByteArray::Param aAttestationObject) {
|
||||
mozilla::dom::AndroidWebAuthnResult result;
|
||||
|
||||
result.mClientDataJSON.Assign(
|
||||
reinterpret_cast<const char*>(
|
||||
aClientDataJson->GetElements().Elements()),
|
||||
aClientDataJson->Length());
|
||||
result.mKeyHandle.Assign(
|
||||
reinterpret_cast<uint8_t*>(aKeyHandle->GetElements().Elements()),
|
||||
aKeyHandle->Length());
|
||||
result.mAttObj.Assign(reinterpret_cast<uint8_t*>(
|
||||
aAttestationObject->GetElements().Elements()),
|
||||
aAttestationObject->Length());
|
||||
|
||||
mozilla::dom::AndroidWebAuthnTokenManager::GetInstance()
|
||||
->HandleRegisterResult(std::move(result));
|
||||
}
|
||||
|
||||
static void WebAuthnMakeCredentialReturnError(jni::String::Param aErrorCode) {
|
||||
mozilla::dom::AndroidWebAuthnResult result(aErrorCode->ToString());
|
||||
mozilla::dom::AndroidWebAuthnTokenManager::GetInstance()
|
||||
->HandleRegisterResult(std::move(result));
|
||||
}
|
||||
|
||||
static void WebAuthnGetAssertionFinish(jni::ByteArray::Param aClientDataJson,
|
||||
jni::ByteArray::Param aKeyHandle,
|
||||
jni::ByteArray::Param aAuthData,
|
||||
jni::ByteArray::Param aSignature,
|
||||
jni::ByteArray::Param aUserHandle) {
|
||||
mozilla::dom::AndroidWebAuthnResult result;
|
||||
|
||||
result.mClientDataJSON.Assign(
|
||||
reinterpret_cast<const char*>(
|
||||
aClientDataJson->GetElements().Elements()),
|
||||
aClientDataJson->Length());
|
||||
result.mKeyHandle.Assign(
|
||||
reinterpret_cast<uint8_t*>(aKeyHandle->GetElements().Elements()),
|
||||
aKeyHandle->Length());
|
||||
result.mAuthData.Assign(
|
||||
reinterpret_cast<uint8_t*>(aAuthData->GetElements().Elements()),
|
||||
aAuthData->Length());
|
||||
result.mSignature.Assign(
|
||||
reinterpret_cast<uint8_t*>(aSignature->GetElements().Elements()),
|
||||
aSignature->Length());
|
||||
result.mUserHandle.Assign(
|
||||
reinterpret_cast<uint8_t*>(aUserHandle->GetElements().Elements()),
|
||||
aUserHandle->Length());
|
||||
|
||||
mozilla::dom::AndroidWebAuthnTokenManager::GetInstance()->HandleSignResult(
|
||||
std::move(result));
|
||||
}
|
||||
|
||||
static void WebAuthnGetAssertionReturnError(jni::String::Param aErrorCode) {
|
||||
mozilla::dom::AndroidWebAuthnResult result(aErrorCode->ToString());
|
||||
mozilla::dom::AndroidWebAuthnTokenManager::GetInstance()->HandleSignResult(
|
||||
std::move(result));
|
||||
}
|
||||
};
|
||||
} // namespace mozilla
|
||||
|
||||
#endif
|
|
@ -3,3 +3,6 @@
|
|||
|
||||
[java.lang.IllegalArgumentException = skip:true]
|
||||
<init>(Ljava/lang/String;)V =
|
||||
|
||||
[java.lang.Throwable = skip:true]
|
||||
getMessage()Ljava/lang/String; =
|
||||
|
|
|
@ -75,7 +75,6 @@
|
|||
#include "Telemetry.h"
|
||||
#include "WebExecutorSupport.h"
|
||||
#include "Base64UtilsSupport.h"
|
||||
#include "WebAuthnTokenManager.h"
|
||||
|
||||
#ifdef DEBUG_ANDROID_EVENTS
|
||||
# define EVLOG(args...) ALOG(args)
|
||||
|
@ -437,7 +436,6 @@ nsAppShell::nsAppShell()
|
|||
mozilla::widget::Base64UtilsSupport::Init();
|
||||
nsWindow::InitNatives();
|
||||
mozilla::gl::AndroidSurfaceTexture::Init();
|
||||
mozilla::WebAuthnTokenManager::Init();
|
||||
mozilla::widget::GeckoTelemetryDelegate::Init();
|
||||
|
||||
java::GeckoThread::SetState(java::GeckoThread::State::JNI_READY());
|
||||
|
|
Загрузка…
Ссылка в новой задаче