diff --git a/build.sh b/build.sh
index a571269..dd2441e 100755
--- a/build.sh
+++ b/build.sh
@@ -57,6 +57,16 @@ make \
-j"$(nproc)"
popd
+# Build microG libraries
+pushd "$gmscore"
+gradle -x javaDocReleaseGeneration \
+ :play-services-ads-identifier:publishToMavenLocal \
+ :play-services-base:publishToMavenLocal \
+ :play-services-basement:publishToMavenLocal \
+ :play-services-fido:publishToMavenLocal \
+ :play-services-tasks:publishToMavenLocal
+popd
+
pushd "$mozilla_release"
MOZ_CHROME_MULTILOCALE=$(< "$patches/locales")
export MOZ_CHROME_MULTILOCALE
diff --git a/fenix-liberate.patch b/fenix-liberate.patch
index e7fb4c8..1550da8 100644
--- a/fenix-liberate.patch
+++ b/fenix-liberate.patch
@@ -1,8 +1,8 @@
diff --git a/fenix/app/build.gradle b/fenix/app/build.gradle
-index 78d698dad9..0fbf4cb1cf 100644
+index ecf270db09..eeb42dc674 100644
--- a/fenix/app/build.gradle
+++ b/fenix/app/build.gradle
-@@ -576,7 +576,6 @@ dependencies {
+@@ -599,7 +599,6 @@ dependencies {
implementation project(':lib-crash')
implementation project(':lib-crash-sentry')
@@ -10,15 +10,15 @@ index 78d698dad9..0fbf4cb1cf 100644
implementation project(':lib-state')
implementation project(':lib-dataprotect')
-@@ -615,15 +614,6 @@ dependencies {
+@@ -638,15 +637,8 @@ dependencies {
implementation FenixDependencies.protobuf_javalite
implementation ComponentsDependencies.google_material
- implementation FenixDependencies.adjust
- implementation FenixDependencies.installreferrer // Required by Adjust
-
-- implementation FenixDependencies.google_ads_id // Required for the Google Advertising ID
--
+ implementation FenixDependencies.google_ads_id // Required for the Google Advertising ID
+
- // Required for in-app reviews
- implementation FenixDependencies.google_play_review
- implementation FenixDependencies.google_play_review_ktx
@@ -353,63 +353,6 @@ index 0000000000..7efa1c6804
+public interface OnAttributionChangedListener {
+ void onAttributionChanged(AdjustAttribution attribution);
+}
-diff --git a/fenix/app/src/main/java/com/google/android/gms/ads/identifier/AdvertisingIdClient.java b/fenix/app/src/main/java/com/google/android/gms/ads/identifier/AdvertisingIdClient.java
-new file mode 100644
-index 0000000000..0f2a47b141
---- /dev/null
-+++ b/fenix/app/src/main/java/com/google/android/gms/ads/identifier/AdvertisingIdClient.java
-@@ -0,0 +1,23 @@
-+/* 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/. */
-+
-+package com.google.android.gms.ads.identifier;
-+
-+import android.content.Context;
-+
-+public class AdvertisingIdClient {
-+
-+ public static final class Info {
-+
-+ public String getId() {
-+ return "";
-+ }
-+
-+ }
-+
-+ public static Info getAdvertisingIdInfo(Context context) {
-+ return new Info();
-+ }
-+
-+}
-diff --git a/fenix/app/src/main/java/com/google/android/gms/common/GooglePlayServicesNotAvailableException.java b/fenix/app/src/main/java/com/google/android/gms/common/GooglePlayServicesNotAvailableException.java
-new file mode 100644
-index 0000000000..d3bff12497
---- /dev/null
-+++ b/fenix/app/src/main/java/com/google/android/gms/common/GooglePlayServicesNotAvailableException.java
-@@ -0,0 +1,8 @@
-+/* 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/. */
-+
-+package com.google.android.gms.common;
-+
-+public class GooglePlayServicesNotAvailableException extends Exception {
-+}
-diff --git a/fenix/app/src/main/java/com/google/android/gms/common/GooglePlayServicesRepairableException.java b/fenix/app/src/main/java/com/google/android/gms/common/GooglePlayServicesRepairableException.java
-new file mode 100644
-index 0000000000..b72a7cdb16
---- /dev/null
-+++ b/fenix/app/src/main/java/com/google/android/gms/common/GooglePlayServicesRepairableException.java
-@@ -0,0 +1,8 @@
-+/* 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/. */
-+
-+package com.google.android.gms.common;
-+
-+public class GooglePlayServicesRepairableException extends Exception {
-+}
diff --git a/fenix/app/src/main/java/com/google/firebase/messaging/FirebaseMessagingService.java b/fenix/app/src/main/java/com/google/firebase/messaging/FirebaseMessagingService.java
new file mode 100644
index 0000000000..4d5fd8153d
@@ -536,7 +479,7 @@ index 0000000000..b50a6f03a2
+ }
+}
diff --git a/fenix/app/src/main/java/org/mozilla/fenix/FeatureFlags.kt b/fenix/app/src/main/java/org/mozilla/fenix/FeatureFlags.kt
-index d3d63c17b9..7228e67716 100644
+index dbfd66328a..dad70c421f 100644
--- a/fenix/app/src/main/java/org/mozilla/fenix/FeatureFlags.kt
+++ b/fenix/app/src/main/java/org/mozilla/fenix/FeatureFlags.kt
@@ -18,7 +18,7 @@ object FeatureFlags {
@@ -557,11 +500,41 @@ index d3d63c17b9..7228e67716 100644
}
/**
+diff --git a/fenix/app/src/main/java/org/mozilla/fenix/browser/BaseBrowserFragment.kt b/fenix/app/src/main/java/org/mozilla/fenix/browser/BaseBrowserFragment.kt
+index 03e1b6b832..33bdbe364b 100644
+--- a/fenix/app/src/main/java/org/mozilla/fenix/browser/BaseBrowserFragment.kt
++++ b/fenix/app/src/main/java/org/mozilla/fenix/browser/BaseBrowserFragment.kt
+@@ -839,17 +839,14 @@ abstract class BaseBrowserFragment :
+ view = view,
+ )
+
+- // This component feature only works on Fenix when built on Mozilla infrastructure.
+- if (BuildConfig.MOZILLA_OFFICIAL) {
+- webAuthnFeature.set(
+- feature = WebAuthnFeature(
+- engine = requireComponents.core.engine,
+- activity = requireActivity(),
+- ),
+- owner = this,
+- view = view,
+- )
+- }
++ webAuthnFeature.set(
++ feature = WebAuthnFeature(
++ engine = requireComponents.core.engine,
++ activity = requireActivity(),
++ ),
++ owner = this,
++ view = view,
++ )
+
+ screenOrientationFeature.set(
+ feature = ScreenOrientationFeature(
diff --git a/fenix/app/src/main/java/org/mozilla/fenix/components/Analytics.kt b/fenix/app/src/main/java/org/mozilla/fenix/components/Analytics.kt
-index 3cd954a5bb..31f4e6fe34 100644
+index da0fe53ea0..6ce3c2a4d6 100644
--- a/fenix/app/src/main/java/org/mozilla/fenix/components/Analytics.kt
+++ b/fenix/app/src/main/java/org/mozilla/fenix/components/Analytics.kt
-@@ -137,11 +137,7 @@ class Analytics(
+@@ -147,11 +147,7 @@ class Analytics(
MetricController.create(
listOf(
GleanMetricsService(context),
@@ -575,7 +548,7 @@ index 3cd954a5bb..31f4e6fe34 100644
),
isDataTelemetryEnabled = { context.settings().isTelemetryEnabled },
diff --git a/fenix/app/src/main/java/org/mozilla/fenix/components/Components.kt b/fenix/app/src/main/java/org/mozilla/fenix/components/Components.kt
-index d077ca2972..a55a167ad5 100644
+index fb5dc10724..76e2de470e 100644
--- a/fenix/app/src/main/java/org/mozilla/fenix/components/Components.kt
+++ b/fenix/app/src/main/java/org/mozilla/fenix/components/Components.kt
@@ -10,7 +10,6 @@ import android.content.Context
@@ -595,10 +568,10 @@ index d077ca2972..a55a167ad5 100644
)
}
diff --git a/fenix/app/src/main/java/org/mozilla/fenix/components/Core.kt b/fenix/app/src/main/java/org/mozilla/fenix/components/Core.kt
-index f6d7a2b0df..366c256bdb 100644
+index aece11e5ac..583f777fa8 100644
--- a/fenix/app/src/main/java/org/mozilla/fenix/components/Core.kt
+++ b/fenix/app/src/main/java/org/mozilla/fenix/components/Core.kt
-@@ -510,8 +510,14 @@ class Core(
+@@ -508,8 +508,14 @@ class Core(
} else {
defaultTopSites.add(
Pair(
@@ -823,7 +796,7 @@ index d69f27e570..171f54a6d5 100644
itemView.context.components.core.icons.loadIntoView(binding.faviconImage, topSite.url)
}
diff --git a/fenix/app/src/main/java/org/mozilla/fenix/settings/SupportUtils.kt b/fenix/app/src/main/java/org/mozilla/fenix/settings/SupportUtils.kt
-index e867be39f2..a1667b1c2b 100644
+index 961ea541c3..7bb88bd7c2 100644
--- a/fenix/app/src/main/java/org/mozilla/fenix/settings/SupportUtils.kt
+++ b/fenix/app/src/main/java/org/mozilla/fenix/settings/SupportUtils.kt
@@ -38,6 +38,8 @@ object SupportUtils {
@@ -836,10 +809,10 @@ index e867be39f2..a1667b1c2b 100644
enum class SumoTopic(internal val topicStr: String) {
HELP("faq-android"),
diff --git a/fenix/app/src/main/java/org/mozilla/fenix/utils/Settings.kt b/fenix/app/src/main/java/org/mozilla/fenix/utils/Settings.kt
-index 01ed68bbe6..c35ab607f7 100644
+index 4e4e6f38e9..37d64fd5fe 100644
--- a/fenix/app/src/main/java/org/mozilla/fenix/utils/Settings.kt
+++ b/fenix/app/src/main/java/org/mozilla/fenix/utils/Settings.kt
-@@ -332,17 +332,17 @@ class Settings(private val appContext: Context) : PreferencesHolder {
+@@ -334,17 +334,17 @@ class Settings(private val appContext: Context) : PreferencesHolder {
var isTelemetryEnabled by booleanPreference(
appContext.getPreferenceKey(R.string.pref_key_telemetry),
@@ -860,7 +833,7 @@ index 01ed68bbe6..c35ab607f7 100644
)
var isOverrideTPPopupsForPerformanceTest = false
-@@ -1553,7 +1553,7 @@ class Settings(private val appContext: Context) : PreferencesHolder {
+@@ -1593,7 +1593,7 @@ class Settings(private val appContext: Context) : PreferencesHolder {
var showPocketRecommendationsFeature by lazyFeatureFlagPreference(
appContext.getPreferenceKey(R.string.pref_key_pocket_homescreen_recommendations),
featureFlag = FeatureFlags.isPocketRecommendationsFeatureEnabled(appContext),
@@ -869,7 +842,7 @@ index 01ed68bbe6..c35ab607f7 100644
)
/**
-@@ -1611,7 +1611,7 @@ class Settings(private val appContext: Context) : PreferencesHolder {
+@@ -1651,7 +1651,7 @@ class Settings(private val appContext: Context) : PreferencesHolder {
*/
var showContileFeature by booleanPreference(
key = appContext.getPreferenceKey(R.string.pref_key_enable_contile),
@@ -893,7 +866,7 @@ index 0000000000..101f4e0d0a
+ EFF
+
diff --git a/fenix/app/src/main/res/xml/preferences.xml b/fenix/app/src/main/res/xml/preferences.xml
-index 2e0366e11b..4a684b7fb6 100644
+index 9f62309f1e..d9732e9c03 100644
--- a/fenix/app/src/main/res/xml/preferences.xml
+++ b/fenix/app/src/main/res/xml/preferences.xml
@@ -133,11 +133,6 @@
@@ -908,7 +881,7 @@ index 2e0366e11b..4a684b7fb6 100644
@@ -957,10 +930,27 @@ index 64c90b599b..621f184e68 100644
getTransportsForByte(final byte transports) {
-- final ArrayList result = new ArrayList();
-- if ((transports & AUTHENTICATOR_TRANSPORT_USB) == AUTHENTICATOR_TRANSPORT_USB) {
-- result.add(Transport.USB);
-- }
-- if ((transports & AUTHENTICATOR_TRANSPORT_NFC) == AUTHENTICATOR_TRANSPORT_NFC) {
-- result.add(Transport.NFC);
-- }
-- if ((transports & AUTHENTICATOR_TRANSPORT_BLE) == AUTHENTICATOR_TRANSPORT_BLE) {
-- result.add(Transport.BLUETOOTH_LOW_ENERGY);
-- }
-- if ((transports & AUTHENTICATOR_TRANSPORT_INTERNAL) == AUTHENTICATOR_TRANSPORT_INTERNAL) {
-- result.add(Transport.INTERNAL);
-- }
-- return result;
-- }
+ final Task intentTask;
- public static class WebAuthnPublicCredential {
- public final byte[] id;
-@@ -94,34 +23,12 @@
-
- static ArrayList CombineBuffers(
- final Object[] idObjectList, final ByteBuffer transportList) {
-- if (idObjectList.length != transportList.remaining()) {
-- throw new RuntimeException("Couldn't extract allowed list!");
-- }
--
- final ArrayList credList =
- new ArrayList();
--
-- final byte[] transportBytes = new byte[transportList.remaining()];
-- transportList.get(transportBytes);
--
-- for (int i = 0; i < idObjectList.length; i++) {
-- final ByteBuffer id = (ByteBuffer) idObjectList[i];
-- final byte[] idBytes = new byte[id.remaining()];
-- id.get(idBytes);
--
-- credList.add(new WebAuthnPublicCredential(idBytes, transportBytes[i]));
-- }
- return credList;
- }
- }
-
-- // From WebAuthentication.webidl
-- public enum AttestationPreference {
-- NONE,
-- INDIRECT,
-- DIRECT,
-- }
--
- @WrapForJNI
- public static class MakeCredentialResponse {
- public final byte[] clientDataJson;
-@@ -154,191 +61,7 @@
- final WebAuthnTokenManager.WebAuthnPublicCredential[] excludeList,
- final GeckoBundle authenticatorSelection,
- final GeckoBundle extensions) {
-- if (!credentialBundle.containsKey("isWebAuthn")) {
-- // FIDO U2F not supported by Android (for us anyway) at this time
-- return GeckoResult.fromException(new WebAuthnTokenManager.Exception("NOT_SUPPORTED_ERR"));
-- }
--
-- final PublicKeyCredentialCreationOptions.Builder requestBuilder =
-- new PublicKeyCredentialCreationOptions.Builder();
--
-- final List params =
-- new ArrayList();
--
-- // WebAuthn supports more algorithms
-- for (final Algorithm algo : SUPPORTED_ALGORITHMS) {
-- params.add(
-- new PublicKeyCredentialParameters(
-- PublicKeyCredentialType.PUBLIC_KEY.toString(), algo.getAlgoValue()));
-- }
--
-- final PublicKeyCredentialUserEntity user =
-- new PublicKeyCredentialUserEntity(
-- userId,
-- credentialBundle.getString("userName", ""),
-- /* deprecated userIcon field */ "",
-- credentialBundle.getString("userDisplayName", ""));
--
-- AttestationConveyancePreference pref = AttestationConveyancePreference.NONE;
-- final String attestationPreference =
-- authenticatorSelection.getString("attestationPreference", "NONE");
-- if (attestationPreference.equalsIgnoreCase(AttestationConveyancePreference.DIRECT.name())) {
-- pref = AttestationConveyancePreference.DIRECT;
-- } else if (attestationPreference.equalsIgnoreCase(
-- AttestationConveyancePreference.INDIRECT.name())) {
-- pref = AttestationConveyancePreference.INDIRECT;
-- }
--
-- final AuthenticatorSelectionCriteria.Builder selBuild =
-- new AuthenticatorSelectionCriteria.Builder();
-- if (authenticatorSelection.getInt("requirePlatformAttachment", 0) == 1) {
-- selBuild.setAttachment(Attachment.PLATFORM);
-- }
-- if (authenticatorSelection.getInt("requireCrossPlatformAttachment", 0) == 1) {
-- selBuild.setAttachment(Attachment.CROSS_PLATFORM);
-- }
-- final String residentKey = authenticatorSelection.getString("residentKey", "");
-- if (residentKey.equals("required")) {
-- selBuild
-- .setRequireResidentKey(true)
-- .setResidentKeyRequirement(ResidentKeyRequirement.RESIDENT_KEY_REQUIRED);
-- } else if (residentKey.equals("preferred")) {
-- selBuild
-- .setRequireResidentKey(false)
-- .setResidentKeyRequirement(ResidentKeyRequirement.RESIDENT_KEY_PREFERRED);
-- } else if (residentKey.equals("discouraged")) {
-- selBuild
-- .setRequireResidentKey(false)
-- .setResidentKeyRequirement(ResidentKeyRequirement.RESIDENT_KEY_DISCOURAGED);
-- }
-- final AuthenticatorSelectionCriteria sel = selBuild.build();
--
-- final AuthenticationExtensions.Builder extBuilder = new AuthenticationExtensions.Builder();
-- if (extensions.containsKey("fidoAppId")) {
-- extBuilder.setFido2Extension(new FidoAppIdExtension(extensions.getString("fidoAppId")));
-- }
-- final AuthenticationExtensions ext = extBuilder.build();
--
-- // requireUserVerification are not yet consumed by Android's API
--
-- final List excludedList =
-- new ArrayList();
-- for (final WebAuthnTokenManager.WebAuthnPublicCredential cred : excludeList) {
-- excludedList.add(
-- new PublicKeyCredentialDescriptor(
-- PublicKeyCredentialType.PUBLIC_KEY.toString(),
-- cred.id,
-- getTransportsForByte(cred.transports)));
-- }
--
-- final PublicKeyCredentialRpEntity rp =
-- new PublicKeyCredentialRpEntity(
-- credentialBundle.getString("rpId"),
-- credentialBundle.getString("rpName", ""),
-- /* deprecated rpIcon field */ "");
--
-- final PublicKeyCredentialCreationOptions requestOptions =
-- requestBuilder
-- .setUser(user)
-- .setAttestationConveyancePreference(pref)
-- .setAuthenticatorSelection(sel)
-- .setAuthenticationExtensions(ext)
-- .setChallenge(challenge)
-- .setRp(rp)
-- .setParameters(params)
-- .setTimeoutSeconds(credentialBundle.getLong("timeoutMS") / 1000.0)
-- .setExcludeList(excludedList)
-- .build();
--
-- final Uri origin = Uri.parse(credentialBundle.getString("origin"));
--
-- final BrowserPublicKeyCredentialCreationOptions browserOptions =
-- new BrowserPublicKeyCredentialCreationOptions.Builder()
-- .setPublicKeyCredentialCreationOptions(requestOptions)
-- .setOrigin(origin)
-- .build();
--
-- final Task intentTask;
--
- if (BuildConfig.MOZILLA_OFFICIAL) {
- // Certain Fenix builds and signing keys are whitelisted for Web Authentication.
- // See https://wiki.mozilla.org/Security/Web_Authentication
@@ -237,7 +24,14 @@ diff -r 2d7ee05a65e0 mobile/android/geckoview/src/main/java/org/mozilla/geckovie
- // Third party apps will need to get whitelisted themselves.
- final Fido2PrivilegedApiClient fidoClient =
- Fido.getFido2PrivilegedApiClient(GeckoAppShell.getApplicationContext());
--
++ // The privileged FIDO2 API normally is restricted to apps with package
++ // names and signatures that Google knows to be a browser. microG does not
++ // have such a list, instead it asks the user to confirm that the app doing
++ // the request is indeed a browser app (only for the first request from
++ // that app).
++ final Fido2PrivilegedApiClient fidoClient =
++ Fido.getFido2PrivilegedApiClient(GeckoAppShell.getApplicationContext());
+
- intentTask = fidoClient.getRegisterPendingIntent(browserOptions);
- } else {
- // For non-official builds, websites have to opt-in to permit the
@@ -251,175 +45,24 @@ diff -r 2d7ee05a65e0 mobile/android/geckoview/src/main/java/org/mozilla/geckovie
-
- intentTask = fidoClient.getRegisterPendingIntent(requestOptions);
- }
--
++ intentTask = fidoClient.getRegisterPendingIntent(browserOptions);
+
final GeckoResult result = new GeckoResult<>();
--
-- intentTask.addOnSuccessListener(
-- pendingIntent -> {
-- GeckoRuntime.getInstance()
-- .startActivityForResult(pendingIntent)
-- .accept(
-- intent -> {
-- final WebAuthnTokenManager.Exception error = parseErrorIntent(intent);
-- if (error != null) {
-- result.completeExceptionally(error);
-- return;
-- }
--
-- final byte[] rspData = intent.getByteArrayExtra(Fido.FIDO2_KEY_RESPONSE_EXTRA);
-- if (rspData != null) {
-- final AuthenticatorAttestationResponse responseData =
-- AuthenticatorAttestationResponse.deserializeFromBytes(rspData);
--
-- Log.d(
-- LOGTAG,
-- "key handle: "
-- + Base64.encodeToString(responseData.getKeyHandle(), Base64.DEFAULT));
-- Log.d(
-- LOGTAG,
-- "clientDataJSON: "
-- + Base64.encodeToString(
-- responseData.getClientDataJSON(), Base64.DEFAULT));
-- Log.d(
-- LOGTAG,
-- "attestation Object: "
-- + Base64.encodeToString(
-- responseData.getAttestationObject(), Base64.DEFAULT));
--
-- Log.d(
-- LOGTAG, "transports: " + String.join(", ", responseData.getTransports()));
--
-- result.complete(
-- new WebAuthnTokenManager.MakeCredentialResponse(
-- responseData.getClientDataJSON(),
-- responseData.getKeyHandle(),
-- responseData.getAttestationObject(),
-- responseData.getTransports()));
-- }
-- },
-- e -> {
-- Log.w(LOGTAG, "Failed to launch activity: ", e);
-- result.completeExceptionally(new WebAuthnTokenManager.Exception("ABORT_ERR"));
-- });
-- });
--
-- intentTask.addOnFailureListener(
-- e -> {
-- Log.w(LOGTAG, "Failed to get FIDO intent", e);
-- result.completeExceptionally(new WebAuthnTokenManager.Exception("ABORT_ERR"));
-- });
--
- return result;
- }
-@@ -351,36 +74,8 @@
- final ByteBuffer transportList,
- final GeckoBundle authenticatorSelection,
- final GeckoBundle extensions) {
-- final ArrayList excludeList;
--
-- final byte[] challBytes = new byte[challenge.remaining()];
-- final byte[] userBytes = new byte[userId.remaining()];
-- try {
-- challenge.get(challBytes);
-- userId.get(userBytes);
--
-- excludeList = WebAuthnPublicCredential.CombineBuffers(idList, transportList);
-- } catch (final RuntimeException e) {
-- Log.w(LOGTAG, "Couldn't extract nio byte arrays!", e);
-- return GeckoResult.fromException(new WebAuthnTokenManager.Exception("UNKNOWN_ERR"));
-- }
--
-- try {
-- 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);
-- return GeckoResult.fromException(new WebAuthnTokenManager.Exception("UNKNOWN_ERR"));
-- }
-+ final GeckoResult result = new GeckoResult<>();
-+ return result;
- }
+@@ -464,19 +452,12 @@
+ .build();
- @WrapForJNI
-@@ -405,138 +100,12 @@
- }
- }
-
-- private static WebAuthnTokenManager.Exception parseErrorIntent(final Intent intent) {
-- if (!intent.hasExtra(Fido.FIDO2_KEY_ERROR_EXTRA)) {
-- return null;
-- }
--
-- final byte[] errData = intent.getByteArrayExtra(Fido.FIDO2_KEY_ERROR_EXTRA);
-- final AuthenticatorErrorResponse responseData =
-- AuthenticatorErrorResponse.deserializeFromBytes(errData);
--
-- Log.e(LOGTAG, "errorCode.name: " + responseData.getErrorCode());
-- Log.e(LOGTAG, "errorMessage: " + responseData.getErrorMessage());
--
-- return new WebAuthnTokenManager.Exception(responseData.getErrorCode().name());
-- }
--
- private static GeckoResult getAssertion(
- final byte[] challenge,
- final WebAuthnTokenManager.WebAuthnPublicCredential[] allowList,
- final GeckoBundle assertionBundle,
- final GeckoBundle extensions) {
--
-- if (!assertionBundle.containsKey("isWebAuthn")) {
-- // FIDO U2F not supported by Android (for us anyway) at this time
-- return GeckoResult.fromException(new WebAuthnTokenManager.Exception("NOT_SUPPORTED_ERR"));
-- }
--
-- final List allowedList =
-- new ArrayList();
-- for (final WebAuthnTokenManager.WebAuthnPublicCredential cred : allowList) {
-- allowedList.add(
-- new PublicKeyCredentialDescriptor(
-- PublicKeyCredentialType.PUBLIC_KEY.toString(),
-- cred.id,
-- getTransportsForByte(cred.transports)));
-- }
--
-- final AuthenticationExtensions.Builder extBuilder = new AuthenticationExtensions.Builder();
-- if (extensions.containsKey("fidoAppId")) {
-- extBuilder.setFido2Extension(new FidoAppIdExtension(extensions.getString("fidoAppId")));
-- }
-- final AuthenticationExtensions ext = extBuilder.build();
--
-- final PublicKeyCredentialRequestOptions requestOptions =
-- new PublicKeyCredentialRequestOptions.Builder()
-- .setChallenge(challenge)
-- .setAllowList(allowedList)
-- .setTimeoutSeconds(assertionBundle.getLong("timeoutMS") / 1000.0)
-- .setRpId(assertionBundle.getString("rpId"))
-- .setAuthenticationExtensions(ext)
-- .build();
--
-- final Uri origin = Uri.parse(assertionBundle.getString("origin"));
-- final BrowserPublicKeyCredentialRequestOptions browserOptions =
-- new BrowserPublicKeyCredentialRequestOptions.Builder()
-- .setPublicKeyCredentialRequestOptions(requestOptions)
-- .setOrigin(origin)
-- .build();
--
-- final Task intentTask;
+ final Task intentTask;
- // See the makeCredential method for documentation about this
- // conditional.
- if (BuildConfig.MOZILLA_OFFICIAL) {
- final Fido2PrivilegedApiClient fidoClient =
- Fido.getFido2PrivilegedApiClient(GeckoAppShell.getApplicationContext());
--
++ // See the makeCredential method for documentation about the FIDO2 API and
++ // microG.
++ final Fido2PrivilegedApiClient fidoClient =
++ Fido.getFido2PrivilegedApiClient(GeckoAppShell.getApplicationContext());
+
- intentTask = fidoClient.getSignPendingIntent(browserOptions);
- } else {
- final Fido2ApiClient fidoClient =
@@ -427,101 +70,14 @@ diff -r 2d7ee05a65e0 mobile/android/geckoview/src/main/java/org/mozilla/geckovie
-
- intentTask = fidoClient.getSignPendingIntent(requestOptions);
- }
--
++ intentTask = fidoClient.getSignPendingIntent(browserOptions);
+
final GeckoResult result = new GeckoResult<>();
-- intentTask.addOnSuccessListener(
-- pendingIntent -> {
-- GeckoRuntime.getInstance()
-- .startActivityForResult(pendingIntent)
-- .accept(
-- intent -> {
-- final WebAuthnTokenManager.Exception error = parseErrorIntent(intent);
-- if (error != null) {
-- result.completeExceptionally(error);
-- return;
-- }
--
-- if (intent.hasExtra(Fido.FIDO2_KEY_RESPONSE_EXTRA)) {
-- final byte[] rspData =
-- intent.getByteArrayExtra(Fido.FIDO2_KEY_RESPONSE_EXTRA);
-- final AuthenticatorAssertionResponse responseData =
-- AuthenticatorAssertionResponse.deserializeFromBytes(rspData);
--
-- Log.d(
-- LOGTAG,
-- "key handle: "
-- + Base64.encodeToString(responseData.getKeyHandle(), Base64.DEFAULT));
-- Log.d(
-- LOGTAG,
-- "clientDataJSON: "
-- + Base64.encodeToString(
-- responseData.getClientDataJSON(), Base64.DEFAULT));
-- Log.d(
-- LOGTAG,
-- "auth data: "
-- + Base64.encodeToString(
-- responseData.getAuthenticatorData(), Base64.DEFAULT));
-- Log.d(
-- LOGTAG,
-- "signature: "
-- + Base64.encodeToString(responseData.getSignature(), Base64.DEFAULT));
--
-- // Nullable field
-- byte[] userHandle = responseData.getUserHandle();
-- if (userHandle == null) {
-- userHandle = new byte[0];
-- }
--
-- result.complete(
-- new WebAuthnTokenManager.GetAssertionResponse(
-- responseData.getClientDataJSON(),
-- responseData.getKeyHandle(),
-- responseData.getAuthenticatorData(),
-- responseData.getSignature(),
-- userHandle));
-- }
-- },
-- e -> {
-- Log.w(LOGTAG, "Failed to get FIDO intent", e);
-- result.completeExceptionally(new WebAuthnTokenManager.Exception("UNKNOWN_ERR"));
-- });
-- });
--
- return result;
- }
-
-@@ -547,52 +116,13 @@
- final ByteBuffer transportList,
- final GeckoBundle assertionBundle,
- final GeckoBundle extensions) {
-- final ArrayList allowList;
--
-- 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);
-- return GeckoResult.fromException(new WebAuthnTokenManager.Exception("UNKNOWN_ERR"));
-- }
--
-- try {
-- return getAssertion(
-- challBytes,
-- allowList.toArray(new WebAuthnPublicCredential[0]),
-- assertionBundle,
-- extensions);
-- } catch (final java.lang.Exception e) {
-- Log.w(LOGTAG, "Couldn't get assertion", e);
-- return GeckoResult.fromException(new WebAuthnTokenManager.Exception("UNKNOWN_ERR"));
-- }
-+ final GeckoResult result = new GeckoResult<>();
-+ return result;
- }
-
+ intentTask.addOnSuccessListener(
+@@ -573,15 +554,9 @@
@WrapForJNI(calledFrom = "gecko")
private static GeckoResult webAuthnIsUserVerifyingPlatformAuthenticatorAvailable() {
-- final Task task;
+ final Task task;
- if (BuildConfig.MOZILLA_OFFICIAL) {
- final Fido2PrivilegedApiClient fidoClient =
- Fido.getFido2PrivilegedApiClient(GeckoAppShell.getApplicationContext());
@@ -531,17 +87,9 @@ diff -r 2d7ee05a65e0 mobile/android/geckoview/src/main/java/org/mozilla/geckovie
- Fido.getFido2ApiClient(GeckoAppShell.getApplicationContext());
- task = fidoClient.isUserVerifyingPlatformAuthenticatorAvailable();
- }
--
++ final Fido2PrivilegedApiClient fidoClient =
++ Fido.getFido2PrivilegedApiClient(GeckoAppShell.getApplicationContext());
++ task = fidoClient.isUserVerifyingPlatformAuthenticatorAvailable();
+
final GeckoResult res = new GeckoResult<>();
-- task.addOnSuccessListener(
-- isUVPAA -> {
-- res.complete(isUVPAA);
-- });
-- task.addOnFailureListener(
-- e -> {
-- Log.w(LOGTAG, "isUserVerifyingPlatformAuthenticatorAvailable is failed", e);
-- res.complete(false);
-- });
- return res;
- }
- }
+ task.addOnSuccessListener(
diff --git a/paths.sh b/paths.sh
index ce74f44..4a06cf5 100644
--- a/paths.sh
+++ b/paths.sh
@@ -27,3 +27,4 @@ readonly fenix=$(realpath ./fenix)
readonly mozilla_release=$(realpath ../srclib/MozFennec)
readonly rustup=$(realpath ../srclib/rustup)
readonly wasi=$(realpath ../srclib/wasi-sdk)
+readonly gmscore=$(realpath ../srclib/gmscore)
diff --git a/prebuild.sh b/prebuild.sh
index e99f7ac..421c557 100755
--- a/prebuild.sh
+++ b/prebuild.sh
@@ -258,12 +258,7 @@ hg revert media/openmax_dl -r ebd43acaeeb3a5b82ab6a9027ab88fa2a72aea81
# Revert https://bugzilla.mozilla.org/show_bug.cgi?id=1836826
hg revert media/libvpx -r 699059262f56
-# Remove proprietary libraries
-sed -i \
- -e '/com.google.android.gms/d' \
- mobile/android/geckoview/build.gradle
-
-# Patch the use of proprietary libraries
+# Replace GMS with microG client library
patch -p1 --no-backup-if-mismatch --quiet < "$patches/gecko-liberate.patch"
# Fixup, unsupported on Android
@@ -344,9 +339,6 @@ pref("media.gmp-gmpopenh264.enabled", false);
// Disable casting (Roku, Chromecast)
pref("browser.casting.enabled", false);
-
-// Disable WebAuthn, since it is a stub
-pref("security.webauth.webauthn", false);
EOF
popd