Use microG for WebAuthn support in Gecko

Also drop Ads Identifier library dummy to avoid a conflict between
microG library and this dummy.

WebAuthn will work only if microG Service Core is installed on the
device! It will not work with Google Services because Google requires
a cumbersome registration of an app before they allow it to use
WebAuthn API in GMS.

See https://microg.org for more info on microG.
This commit is contained in:
relan
2023-11-09 10:43:59 +03:00
parent a8e2ec98d3
commit cff4cc4e90
5 changed files with 127 additions and 586 deletions

View File

@@ -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

View File

@@ -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
+ <string name="default_top_site_eff" translatable="false">EFF</string>
+</resources>
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
</androidx.preference.PreferenceCategory>
<PreferenceCategory
@@ -189,11 +184,6 @@
@@ -188,11 +183,6 @@
android:title="@string/preferences_category_about"
app:iconSpaceReserved="false"
android:layout="@layout/preference_category_no_icon_style">
@@ -957,10 +930,27 @@ index 64c90b599b..621f184e68 100644
<androidx.preference.Preference
diff --git a/fenix/plugins/fenixdependencies/src/main/java/FenixDependenciesPlugin.kt b/fenix/plugins/fenixdependencies/src/main/java/FenixDependenciesPlugin.kt
index fff754c099..35599805e6 100644
index 5d61a9bdbd..d55e93b5f1 100644
--- a/fenix/plugins/fenixdependencies/src/main/java/FenixDependenciesPlugin.kt
+++ b/fenix/plugins/fenixdependencies/src/main/java/FenixDependenciesPlugin.kt
@@ -70,9 +70,6 @@ object FenixDependencies {
@@ -28,16 +28,9 @@ object FenixVersions {
const val androidx_datastore = "1.0.0"
const val google_accompanist = "0.30.1"
- const val adjust = "4.35.1"
- const val installreferrer = "2.2"
-
const val junit = "5.9.3"
const val mockk = "1.13.7"
- const val google_ads_id_version = "16.0.0"
-
- const val google_play_review_version = "2.0.1"
-
// keep in sync with the versions used in AS.
const val protobuf = "3.21.10"
const val protobuf_plugin = "0.9.4"
@@ -66,9 +59,6 @@ object FenixDependencies {
const val protobuf_javalite = "com.google.protobuf:protobuf-javalite:${FenixVersions.protobuf}"
const val protobuf_compiler = "com.google.protobuf:protoc:${FenixVersions.protobuf}"
@@ -970,16 +960,16 @@ index fff754c099..35599805e6 100644
const val mockk = "io.mockk:mockk:${FenixVersions.mockk}"
const val mockk_android = "io.mockk:mockk-android:${FenixVersions.mockk}"
const val falcon = "com.jraska:falcon:${FenixVersions.falcon}"
@@ -97,12 +94,6 @@ object FenixDependencies {
const val mockwebserver = "com.squareup.okhttp3:mockwebserver:${FenixVersions.mockwebserver}"
@@ -91,11 +81,7 @@ object FenixDependencies {
// Test services is unused
// --- END AndroidX test dependencies --- //
- const val google_ads_id = "com.google.android.gms:play-services-ads-identifier:${FenixVersions.google_ads_id_version}"
-
- // Required for in-app reviews
- const val google_play_review = "com.google.android.play:review:${FenixVersions.google_play_review_version}"
- const val google_play_review_ktx = "com.google.android.play:review-ktx:${FenixVersions.google_play_review_version}"
-
+ const val google_ads_id = "org.microg.gms:play-services-ads-identifier:0.3.+"
const val junitApi = "org.junit.jupiter:junit-jupiter-api:${FenixVersions.junit}"
const val junitParams = "org.junit.jupiter:junit-jupiter-params:${FenixVersions.junit}"
const val junitEngine = "org.junit.jupiter:junit-jupiter-engine:${FenixVersions.junit}"

View File

@@ -1,235 +1,22 @@
diff -r 2d7ee05a65e0 mobile/android/geckoview/src/main/java/org/mozilla/geckoview/WebAuthnTokenManager.java
--- a/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/WebAuthnTokenManager.java Thu Nov 16 17:51:50 2023 +0000
+++ b/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/WebAuthnTokenManager.java Mon Nov 20 19:43:22 2023 -0500
@@ -5,83 +5,12 @@
diff -r d80eefe94738 mobile/android/geckoview/build.gradle
--- a/mobile/android/geckoview/build.gradle Tue Nov 28 21:01:37 2023 +0000
+++ b/mobile/android/geckoview/build.gradle Fri Dec 15 11:32:38 2023 +0300
@@ -222,7 +222,7 @@
implementation "androidx.annotation:annotation:1.6.0"
implementation "androidx.legacy:legacy-support-v4:1.0.0"
package org.mozilla.geckoview;
- implementation "com.google.android.gms:play-services-fido:20.0.1"
+ implementation "org.microg.gms:play-services-fido:0.3.+"
implementation "org.yaml:snakeyaml:2.0"
-import android.app.PendingIntent;
-import android.content.Intent;
-import android.net.Uri;
-import android.util.Base64;
-import android.util.Log;
-import com.google.android.gms.fido.Fido;
-import com.google.android.gms.fido.common.Transport;
-import com.google.android.gms.fido.fido2.Fido2ApiClient;
-import com.google.android.gms.fido.fido2.Fido2PrivilegedApiClient;
-import com.google.android.gms.fido.fido2.api.common.Algorithm;
-import com.google.android.gms.fido.fido2.api.common.Attachment;
-import com.google.android.gms.fido.fido2.api.common.AttestationConveyancePreference;
-import com.google.android.gms.fido.fido2.api.common.AuthenticationExtensions;
-import com.google.android.gms.fido.fido2.api.common.AuthenticatorAssertionResponse;
-import com.google.android.gms.fido.fido2.api.common.AuthenticatorAttestationResponse;
-import com.google.android.gms.fido.fido2.api.common.AuthenticatorErrorResponse;
-import com.google.android.gms.fido.fido2.api.common.AuthenticatorSelectionCriteria;
-import com.google.android.gms.fido.fido2.api.common.BrowserPublicKeyCredentialCreationOptions;
-import com.google.android.gms.fido.fido2.api.common.BrowserPublicKeyCredentialRequestOptions;
-import com.google.android.gms.fido.fido2.api.common.EC2Algorithm;
-import com.google.android.gms.fido.fido2.api.common.FidoAppIdExtension;
-import com.google.android.gms.fido.fido2.api.common.PublicKeyCredentialCreationOptions;
-import com.google.android.gms.fido.fido2.api.common.PublicKeyCredentialDescriptor;
-import com.google.android.gms.fido.fido2.api.common.PublicKeyCredentialParameters;
-import com.google.android.gms.fido.fido2.api.common.PublicKeyCredentialRequestOptions;
-import com.google.android.gms.fido.fido2.api.common.PublicKeyCredentialRpEntity;
-import com.google.android.gms.fido.fido2.api.common.PublicKeyCredentialType;
-import com.google.android.gms.fido.fido2.api.common.PublicKeyCredentialUserEntity;
-import com.google.android.gms.fido.fido2.api.common.RSAAlgorithm;
-import com.google.android.gms.fido.fido2.api.common.ResidentKeyRequirement;
-import com.google.android.gms.tasks.Task;
import java.nio.ByteBuffer;
import java.util.ArrayList;
-import java.util.List;
-import org.mozilla.gecko.GeckoAppShell;
import org.mozilla.gecko.annotation.WrapForJNI;
import org.mozilla.gecko.util.GeckoBundle;
implementation "androidx.lifecycle:lifecycle-common:2.6.1"
diff -r d80eefe94738 mobile/android/geckoview/src/main/java/org/mozilla/geckoview/WebAuthnTokenManager.java
--- a/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/WebAuthnTokenManager.java Tue Nov 28 21:01:37 2023 +0000
+++ b/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/WebAuthnTokenManager.java Fri Dec 15 11:32:38 2023 +0300
@@ -260,27 +260,15 @@
/* package */ class WebAuthnTokenManager {
- private static final String LOGTAG = "WebAuthnTokenManager";
-
- // from dom/webauthn/WebAuthnTransportIdentifiers.h
- private static final byte AUTHENTICATOR_TRANSPORT_USB = 1;
- private static final byte AUTHENTICATOR_TRANSPORT_NFC = 2;
- private static final byte AUTHENTICATOR_TRANSPORT_BLE = 4;
- private static final byte AUTHENTICATOR_TRANSPORT_INTERNAL = 8;
-
- private static final Algorithm[] SUPPORTED_ALGORITHMS = {
- EC2Algorithm.ES256,
- EC2Algorithm.ES384,
- EC2Algorithm.ES512,
- EC2Algorithm.ED256, /* no ED384 */
- EC2Algorithm.ED512,
- RSAAlgorithm.PS256,
- RSAAlgorithm.PS384,
- RSAAlgorithm.PS512,
- RSAAlgorithm.RS256,
- RSAAlgorithm.RS384,
- RSAAlgorithm.RS512
- };
-
- private static List<Transport> getTransportsForByte(final byte transports) {
- final ArrayList<Transport> result = new ArrayList<Transport>();
- 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<PendingIntent> intentTask;
public static class WebAuthnPublicCredential {
public final byte[] id;
@@ -94,34 +23,12 @@
static ArrayList<WebAuthnPublicCredential> CombineBuffers(
final Object[] idObjectList, final ByteBuffer transportList) {
- if (idObjectList.length != transportList.remaining()) {
- throw new RuntimeException("Couldn't extract allowed list!");
- }
-
final ArrayList<WebAuthnPublicCredential> credList =
new ArrayList<WebAuthnPublicCredential>();
-
- 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<PublicKeyCredentialParameters> params =
- new ArrayList<PublicKeyCredentialParameters>();
-
- // 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<PublicKeyCredentialDescriptor> excludedList =
- new ArrayList<PublicKeyCredentialDescriptor>();
- 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<PendingIntent> 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<MakeCredentialResponse> 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<WebAuthnPublicCredential> 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<MakeCredentialResponse> 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<GetAssertionResponse> 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<PublicKeyCredentialDescriptor> allowedList =
- new ArrayList<PublicKeyCredentialDescriptor>();
- 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<PendingIntent> intentTask;
final Task<PendingIntent> 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<GetAssertionResponse> 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<WebAuthnPublicCredential> 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<GetAssertionResponse> result = new GeckoResult<>();
+ return result;
}
intentTask.addOnSuccessListener(
@@ -573,15 +554,9 @@
@WrapForJNI(calledFrom = "gecko")
private static GeckoResult<Boolean> webAuthnIsUserVerifyingPlatformAuthenticatorAvailable() {
- final Task<Boolean> task;
final Task<Boolean> 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<Boolean> 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(

View File

@@ -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)

View File

@@ -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