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 7b5f8d5
Show file tree
Hide file tree
Showing 35 changed files with 411 additions and 258 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

1 comment on commit 7b5f8d5

@firefoxci-taskcluster
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Uh oh! Looks like an error! Details

Failed to fetch task artifact public/github/customCheckRunText.md for GitHub integration.
Make sure the artifact exists on the worker or other location.

Please sign in to comment.