Skip to content
This repository has been archived by the owner on Nov 1, 2022. It is now read-only.

Commit

Permalink
For #12289 Add lib-auth for authentication using biometrics or PIN.
Browse files Browse the repository at this point in the history
  • Loading branch information
iorgamgabriel committed Jun 14, 2022
2 parents 4feb1cf + ab3cfe1 commit f367f5c
Show file tree
Hide file tree
Showing 35 changed files with 409 additions and 257 deletions.
8 changes: 4 additions & 4 deletions .buildconfig.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,6 @@ projects:
path: components/concept/awesomebar
description: 'An abstract definition of an awesomebar component.'
publish: true
lib-auth:
path: components/lib/biometric-prompt
description: 'Component for authentication using biometric'
publish: true
concept-base:
path: components/concept/base
description: 'A component for basic interfaces needed by multiple components and that do not warrant a standalone component.'
Expand Down Expand Up @@ -375,6 +371,10 @@ projects:
path: components/support/webextensions
description: 'A component containing building blocks for features implemented as web extensions.'
publish: true
lib-auth:
path: components/lib/auth
description: 'A component for various kinds of authenticating mechanisms.'
publish: true
lib-crash:
path: components/lib/crash
description: 'A generic crash reporter library that can report crashes to multiple services.'
Expand Down
4 changes: 2 additions & 2 deletions buildSrc/src/main/java/Dependencies.kt
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,9 @@ object Versions {
const val disklrucache = "2.0.2"
const val leakcanary = "2.8.1"

const val mozilla_appservices = "93.2.2"
const val mozilla_appservices = "93.4.0"

const val mozilla_glean = "44.1.1"
const val mozilla_glean = "50.0.1"

const val material = "1.2.1"

Expand Down
2 changes: 1 addition & 1 deletion buildSrc/src/main/java/Gecko.kt
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ object Gecko {
/**
* GeckoView Version.
*/
const val version = "103.0.20220607093440"
const val version = "103.0.20220609065921"

/**
* GeckoView channel
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ class GeckoAdapter : RuntimeTelemetry.Delegate {
metric.value.forEach { labelIndex -> categorical[labelIndex.toInt()].add(1) }
}
} else {
GleanGeckoMetricsMapping.getHistogram(metric.name)?.accumulateSamples(metric.value)
GleanGeckoMetricsMapping.getHistogram(metric.name)?.accumulateSamples(metric.value.toList())
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- The tile for the list of external apps to open the link in -->
<string name="mozac_feature_applinks_open_in">Ṣi nínú…</string>
<!-- Opens the selected time -->
<string name="mozac_feature_applinks_confirm_dialog_confirm">Ṣi</string>
<!-- Cancels the prompt -->
<string name="mozac_feature_applinks_confirm_dialog_deny">Fagile</string>
</resources>
31 changes: 31 additions & 0 deletions components/feature/autofill/src/main/res/values-yo/strings.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- Autofill: Text shown in popup in third-party app if the browser app needs to be unlocked before
a username or password can be autofilled for the highlighted text field. %1$s will be replaced
with the name of the browser application (e.g. Firefox) -->
<string name="mozac_feature_autofill_popup_unlock_application">Ṣi sílẹ̀ %1$s</string>

<!-- Autofill: Text shown in popup in third-party app if we found a matching account, but no
username is saved (e.g. we only have a password). This text will be shown in place where otherwise
the username would be displayed. -->
<string name="mozac_feature_autofill_popup_no_username">(Kò sí orúkọ àmúlò)
</string>

<!-- Autofill: Title of a dialog asking the user to confirm before autofilling credentials into
a third-party app after the authenticity verification failed. -->
<string name="mozac_feature_autofill_confirmation_title">Iṣẹ́ ìmúdájú kùnà</string>

<!-- Autofill: Positive button shown in dialog asking the user to confirm before autofilling
credentials in a third-part app (Also see string mozac_feature_autofill_confirmation_authenticity). -->
<string name="mozac_feature_autofill_confirmation_yes">Bẹ́ẹ̀ni</string>

<!-- Autofill: Negative button shown in dialog asking the user to confirm before autofilling
credentials in a third-part app (Also see string mozac_feature_autofill_confirmation_authenticity). -->
<string name="mozac_feature_autofill_confirmation_no">Bẹ́ẹ̀ kọ́</string>

<!-- Autofill: When showing a list of logins to autofill in a third-party app, then this is the
last item in the list. When clicking it a new screen opens which allows the user to search for
a specific login. %1$s will be replaced with the name of the application (e.g. "Firefox") -->
<string name="mozac_feature_autofill_search_suggestions">Ṣàwárí %1$s</string>

</resources>
27 changes: 27 additions & 0 deletions components/feature/contextmenu/src/main/res/values-yo/strings.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- Text for context menu item to share the link with an other app. -->
<string name="mozac_feature_contextmenu_share_link">Pín ìtọ́kasí</string>
<!-- Text for context menu item to share the image with an other app. -->
<string name="mozac_feature_contextmenu_share_image">Pín àwòrán</string>
<!-- Text for context menu item to copy the link to the clipboard. -->
<string name="mozac_feature_contextmenu_copy_link">Ṣe àdàkọ ìtọ́kasí</string>
<!-- Text for context menu item to save / download the image. -->
<string name="mozac_feature_contextmenu_save_image">Fi àwòrán pamọ́</string>
<!-- Text for confirmation "snackbar" shown after opening a link in a new tab. -->
<string name="mozac_feature_contextmenu_snackbar_new_tab_opened">Táàbù tuntún wà ní ṣíṣí</string>
<!-- Action shown in a "snacbkar" after opening a new/private tab. Clicking this action will switch to the newly opened tab. -->
<string name="mozac_feature_contextmenu_snackbar_action_switch">Ṣe àyípadà</string>
<!-- Text for context menu item to add to a contact. -->
<string name="mozac_feature_contextmenu_add_to_contact">Fikún àwọn olùbásọ̀rọ̀</string>
<!-- Action shown in a text selection context menu. This will prompt a search using the selected text.-->
<string name="mozac_selection_context_menu_search_2">Ṣe àwárí</string>
<!-- Action shown in a text selection context menu. This will prompt a search in a private tab using the selected text-->
<string name="mozac_selection_context_menu_search_privately_2">Àwárí ìkọ̀kọ̀</string>
<!-- Action shown in a text selection context menu. This will prompt a share of the selected text. -->
<string name="mozac_selection_context_menu_share">Pín</string>
<!-- Action shown in a text selection context menu. This will prompt a new email from the selected text. -->
<string name="mozac_selection_context_menu_email">Ímeèlì</string>
<!-- Action shown in a text selection context menu. This will prompt a new call from the selected text. -->
<string name="mozac_selection_context_menu_call">Ìpè</string>
</resources>
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.cancel
import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.flow.map
import mozilla.components.browser.state.selector.findCustomTabOrSelectedTab
import mozilla.components.browser.state.state.SessionState
import mozilla.components.browser.state.store.BrowserStore
import mozilla.components.lib.state.ext.flowScoped
Expand All @@ -22,7 +23,8 @@ import mozilla.components.support.ktx.kotlinx.coroutines.flow.ifChanged
*/
class MediaSessionFullscreenFeature(
private val activity: Activity,
private val store: BrowserStore
private val store: BrowserStore,
private val tabId: String?,
) : LifecycleAwareFeature {

private var scope: CoroutineScope? = null
Expand All @@ -48,7 +50,7 @@ class MediaSessionFullscreenFeature(
return
}

if (store.state.selectedTabId == activeState.id) {
if (store.state.findCustomTabOrSelectedTab(tabId)?.id == activeState.id) {
when (activeState.mediaSessionState?.elementMetadata?.portrait) {
true ->
activity.requestedOrientation =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,17 +9,22 @@ import android.content.pm.ActivityInfo
import android.os.Build
import androidx.test.ext.junit.runners.AndroidJUnit4
import mozilla.components.browser.state.action.ContentAction
import mozilla.components.browser.state.action.CustomTabListAction
import mozilla.components.browser.state.action.MediaSessionAction
import mozilla.components.browser.state.action.TabListAction
import mozilla.components.browser.state.state.BrowserState
import mozilla.components.browser.state.state.MediaSessionState
import mozilla.components.browser.state.state.SessionState
import mozilla.components.browser.state.state.createCustomTab
import mozilla.components.browser.state.state.createTab
import mozilla.components.browser.state.store.BrowserStore
import mozilla.components.concept.engine.mediasession.MediaSession
import mozilla.components.support.test.ext.joinBlocking
import mozilla.components.support.test.libstate.ext.waitUntilIdle
import mozilla.components.support.test.mock
import mozilla.components.support.test.rule.MainCoroutineRule
import org.junit.Assert.assertEquals
import org.junit.Assert.assertNotEquals
import org.junit.Assert.assertTrue
import org.junit.Rule
import org.junit.Test
Expand Down Expand Up @@ -55,7 +60,8 @@ class MediaSessionFullscreenFeatureTest {
val store = BrowserStore(initialState)
val feature = MediaSessionFullscreenFeature(
activity,
store
store,
null
)

feature.start()
Expand Down Expand Up @@ -84,7 +90,8 @@ class MediaSessionFullscreenFeatureTest {
val store = BrowserStore(initialState)
val feature = MediaSessionFullscreenFeature(
activity,
store
store,
null
)

feature.start()
Expand Down Expand Up @@ -113,7 +120,8 @@ class MediaSessionFullscreenFeatureTest {
val store = BrowserStore(initialState)
val feature = MediaSessionFullscreenFeature(
activity,
store
store,
null
)

feature.start()
Expand Down Expand Up @@ -144,7 +152,8 @@ class MediaSessionFullscreenFeatureTest {
val store = BrowserStore(initialState)
val feature = MediaSessionFullscreenFeature(
activity,
store
store,
null
)

feature.start()
Expand Down Expand Up @@ -181,7 +190,8 @@ class MediaSessionFullscreenFeatureTest {
val store = BrowserStore(initialState)
val feature = MediaSessionFullscreenFeature(
activity,
store
store,
null
)

feature.start()
Expand Down Expand Up @@ -230,7 +240,8 @@ class MediaSessionFullscreenFeatureTest {
val store = BrowserStore(initialState)
val feature = MediaSessionFullscreenFeature(
activity,
store
store,
null
)

feature.start()
Expand All @@ -254,4 +265,59 @@ class MediaSessionFullscreenFeatureTest {

assertEquals(ActivityInfo.SCREEN_ORIENTATION_USER, activity.requestedOrientation)
}

@Suppress("Deprecation")
@Test
@Config(sdk = [Build.VERSION_CODES.N])
fun `GIVEN the currently selected tab is in pip mode WHEN a custom tab loads THEN display custom tab in device's current orientation`() {
val activity = Robolectric.buildActivity(Activity::class.java).setup().get()
val elementMetadata = MediaSession.ElementMetadata()
val initialState = BrowserState(
tabs = listOf(
createTab(
"https://www.mozilla.org", id = "tab1",
mediaSessionState = MediaSessionState(
mock(),
elementMetadata = elementMetadata,
playbackState = MediaSession.PlaybackState.PLAYING,
fullscreen = true
)
)
),
selectedTabId = "tab1"
)
val store = BrowserStore(initialState)

val feature = MediaSessionFullscreenFeature(
activity,
store,
null
)

feature.start()
activity.enterPictureInPictureMode()
store.waitUntilIdle()

store.dispatch(ContentAction.PictureInPictureChangedAction("tab1", true))
store.waitUntilIdle()
assertEquals(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED, activity.requestedOrientation)

val customTab = createCustomTab(
"https://www.mozilla.org",
source = SessionState.Source.Internal.CustomTab,
id = "tab2"
)
store.dispatch(CustomTabListAction.AddCustomTabAction(customTab)).joinBlocking()
val externalActivity = Robolectric.buildActivity(Activity::class.java).setup().get()
assertEquals(1, store.state.customTabs.size)
store.waitUntilIdle()
val featureForExternalAppBrowser = MediaSessionFullscreenFeature(
externalActivity,
store,
"tab2"
)
featureForExternalAppBrowser.start()

assertNotEquals(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE, externalActivity.requestedOrientation)
}
}
10 changes: 10 additions & 0 deletions components/feature/prompts/src/main/res/values-cy/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -113,4 +113,14 @@
<string name="mozac_feature_prompts_update_credit_card_prompt_title">Diweddaru dyddiad dod i ben cerdyn?</string>
<!-- Subtitle text displayed under the title of the save credit card dialog. -->
<string name="mozac_feature_prompts_save_credit_card_prompt_body">Bydd rhif y cerdyn yn cael ei amgryptio. Ni fydd y cod diogelwch yn cael ei gadw.</string>

<!-- Address Autofill -->
<!-- Header for the select address prompt to allow users to fill a form with a saved address. -->
<string name="mozac_feature_prompts_select_address">Dewiswch gyfeiriadau</string>
<!-- Content description for expanding the select addresses options in the select address prompt. -->
<string name="mozac_feature_prompts_expand_address_content_description">Ehangu awgrymiadau cyfeiriadau</string>
<!-- Content description for collapsing the select address options in the select address prompt. -->
<string name="mozac_feature_prompts_collapse_address_content_description">Lleihau awgrymiadau cyfeiriadau</string>
<!-- Text for the manage addresses button. -->
<string name="mozac_feature_prompts_manage_address">Rheoli cyfeiriadau</string>
</resources>
10 changes: 10 additions & 0 deletions components/feature/prompts/src/main/res/values-fy-rNL/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -113,4 +113,14 @@
<string name="mozac_feature_prompts_update_credit_card_prompt_title">Ferrindatum kaart bywurkje?</string>
<!-- Subtitle text displayed under the title of the save credit card dialog. -->
<string name="mozac_feature_prompts_save_credit_card_prompt_body">It kaartnûmer sil fersifere wurde. De befeiligingskoade wurdt net bewarre.</string>

<!-- Address Autofill -->
<!-- Header for the select address prompt to allow users to fill a form with a saved address. -->
<string name="mozac_feature_prompts_select_address">Adressen selektearje</string>
<!-- Content description for expanding the select addresses options in the select address prompt. -->
<string name="mozac_feature_prompts_expand_address_content_description">Foarstelde adressen útklappe</string>
<!-- Content description for collapsing the select address options in the select address prompt. -->
<string name="mozac_feature_prompts_collapse_address_content_description">Foarstelde adressen ynklappe</string>
<!-- Text for the manage addresses button. -->
<string name="mozac_feature_prompts_manage_address">Adressen beheare</string>
</resources>
4 changes: 4 additions & 0 deletions components/lib/auth/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest package="mozilla.components.lib.auth">

</manifest>
Original file line number Diff line number Diff line change
Expand Up @@ -7,20 +7,23 @@ package mozilla.components.lib.auth
/**
* Callbacks for BiometricPrompt Authentication
*/
interface AuthenticationCallbacks {
interface AuthenticationDelegate {

/**
* Called when a biometric (e.g. fingerprint, face, etc.) is presented but not recognized as belonging to the user.
* Called when a biometric (e.g. fingerprint, face, etc.)
* is presented but not recognized as belonging to the user.
*/
val onAuthFailure: () -> Unit
fun onAuthFailure()

/**
* Called when a biometric (e.g. fingerprint, face, etc.) is recognized, indicating that the user has successfully authenticated.
* Called when a biometric (e.g. fingerprint, face, etc.) is recognized,
* indicating that the user has successfully authenticated.
*/
val onAuthSuccess: () -> Unit
fun onAuthSuccess()

/**
* Called when an unrecoverable error has been encountered and authentication has stopped.
* @param errorText A human-readable error string that can be shown on an UI
*/
val onAuthError: (errorText: String) -> Unit
fun onAuthError(errorText: String)
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,16 @@ import mozilla.components.support.base.log.logger.Logger

/**
* A [LifecycleAwareFeature] for the Android Biometric API to prompt for user authentication.
* The prompt also requests support for the device PIN as a fallback authentication mechanism.
*
* @param context Android context.
* @param fragment The fragment on which this feature will live.
* @param authenticationCallbacks Callbacks for BiometricPrompt.
* @param authenticationDelegate Callbacks for BiometricPrompt.
*/
class BiometricPromptFeature(
class BiometricPromptAuth(
private val context: Context,
private val fragment: Fragment,
private val authenticationCallbacks: AuthenticationCallbacks
private val authenticationDelegate: AuthenticationDelegate
) : LifecycleAwareFeature {
private val logger = Logger(javaClass.simpleName)

Expand Down Expand Up @@ -61,17 +62,17 @@ class BiometricPromptFeature(
internal inner class PromptCallback : BiometricPrompt.AuthenticationCallback() {
override fun onAuthenticationError(errorCode: Int, errString: CharSequence) {
logger.error("onAuthenticationError: errorMessage $errString errorCode=$errorCode")
authenticationCallbacks.onAuthError(errString.toString())
authenticationDelegate.onAuthError(errString.toString())
}

override fun onAuthenticationSucceeded(result: BiometricPrompt.AuthenticationResult) {
logger.debug("onAuthenticationSucceeded")
authenticationCallbacks.onAuthSuccess()
authenticationDelegate.onAuthSuccess()
}

override fun onAuthenticationFailed() {
logger.error("onAuthenticationFailed")
authenticationCallbacks.onAuthFailure()
authenticationDelegate.onAuthFailure()
}
}
}
Loading

0 comments on commit f367f5c

Please sign in to comment.