diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index b11a4c32f..c31179fb4 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -50,11 +50,4 @@ # Possible regressions throughout the app *.pro @mozilla-mobile/Performance *proguard* @mozilla-mobile/Performance - -# Possible startup regressions -*Application.kt @mozilla-mobile/Performance - -# We want to be aware of new features behind flags as well as features -# about to be enabled. -FeatureFlags.kt @mozilla-mobile/Performance # --- PERFORMANCE END --- # diff --git a/.github/workflows/build-contributor-pr.yml b/.github/workflows/build-contributor-pr.yml index e890fa5bc..4f09120a9 100644 --- a/.github/workflows/build-contributor-pr.yml +++ b/.github/workflows/build-contributor-pr.yml @@ -105,3 +105,30 @@ jobs: name: lintDebug report path: app/build/reports/lint-results-debug.html + run-ui: + runs-on: macos-latest + if: github.event.pull_request.head.repo.full_name != github.repository && github.actor != 'MickeyMoz' + + timeout-minutes: 60 + strategy: + matrix: + api-level: [28] + target: [google_apis] + steps: + - name: Checkout + uses: actions/checkout@v2 + - name: Run subset of UI Tests + uses: reactivecircus/android-emulator-runner@v2 + with: + api-level: ${{ matrix.api-level }} + target: ${{ matrix.target }} + arch: x86_64 + profile: pixel_3a + script: + "./gradlew connectedDebugAndroidTest -Pandroid.testInstrumentationRunnerArguments.class=\ + org.mozilla.fenix.ui.NavigationToolbarTest#visitURLTest" + - name: Upload Test Artifacts + uses: actions/upload-artifact@v2 + with: + name: test-report + path: app/build/reports diff --git a/.github/workflows/sync-strings.yml b/.github/workflows/sync-strings.yml index 35e1c5544..6578c36a1 100644 --- a/.github/workflows/sync-strings.yml +++ b/.github/workflows/sync-strings.yml @@ -6,7 +6,7 @@ name: "Sync Strings" on: schedule: - - cron: '0 */4 * * *' + - cron: '0 2 * * *' jobs: main: @@ -15,9 +15,7 @@ jobs: steps: - name: "Discover Fenix Beta Version" id: fenix-beta-version - uses: mozilla-mobile/fenix-beta-version@1.0.0 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + uses: mozilla-mobile/fenix-beta-version@1.1.0 - name: "Checkout Master Branch" uses: actions/checkout@v2 with: diff --git a/app/build.gradle b/app/build.gradle index 5f5711313..cbc19c830 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -198,18 +198,12 @@ android { androidTest { resources.srcDirs += ['src/androidTest/resources'] } - debug { - java.srcDirs = ['src/geckoNightly/java'] - } - nightly { - java.srcDirs = ['src/geckoNightly/java'] - } beta { - java.srcDirs = ['src/migration/java', 'src/geckoBeta/java'] + java.srcDirs = ['src/migration/java'] manifest.srcFile "src/migration/AndroidManifest.xml" } release { - java.srcDirs = ['src/migration/java', 'src/geckoRelease/java'] + java.srcDirs = ['src/migration/java'] manifest.srcFile "src/migration/AndroidManifest.xml" } forkDebug { @@ -281,7 +275,7 @@ android.applicationVariants.all { variant -> def isDebug = variant.buildType.resValues['IS_DEBUG']?.value ?: false def useReleaseVersioning = variant.buildType.buildConfigFields['USE_RELEASE_VERSIONING']?.value ?: false - def versionName = Config.releaseVersionName(project) == "" ? Config.generateDebugVersionName() : Config.releaseVersionName(project) + def versionName = variant.buildType.name == 'nightly' ? Config.nightlyVersionName() : Config.releaseVersionName(project) println("----------------------------------------------") println("Variant name: " + variant.name) @@ -295,9 +289,9 @@ android.applicationVariants.all { variant -> // The Google Play Store does not allow multiple APKs for the same app that all have the // same version code. Therefore we need to have different version codes for our ARM and x86 // builds. - - println("Version Name: " + versionName) - + + println("versionName override: $versionName") + variant.outputs.each { output -> def abi = output.getFilter(OutputFile.ABI) // We use the same version code generator, that we inherited from Fennec, across all channels - even on @@ -416,9 +410,7 @@ androidExtensions { experimental = true } -// Generate Kotlin code and markdown docs for the Fenix Glean metrics. -ext.gleanGenerateMarkdownDocs = true -ext.gleanDocsDirectory = "$rootDir/docs" +// Generate Kotlin code for the Fenix Glean metrics. apply plugin: "org.mozilla.telemetry.glean-gradle-plugin" configurations { @@ -446,13 +438,7 @@ dependencies { jnaForTest Deps.jna testImplementation files(configurations.jnaForTest.copyRecursive().files) - debugImplementation Deps.mozilla_browser_engine_gecko_nightly - forkDebugImplementation Deps.mozilla_browser_engine_gecko_nightly - - nightlyImplementation Deps.mozilla_browser_engine_gecko_nightly - betaImplementation Deps.mozilla_browser_engine_gecko_beta - releaseImplementation Deps.mozilla_browser_engine_gecko_release - forkReleaseImplementation Deps.mozilla_browser_engine_gecko_release + implementation Deps.mozilla_browser_engine_gecko implementation Deps.kotlin_stdlib implementation Deps.kotlin_coroutines @@ -479,7 +465,6 @@ dependencies { implementation Deps.mozilla_browser_icons implementation Deps.mozilla_browser_menu implementation Deps.mozilla_browser_menu2 - implementation Deps.mozilla_browser_search implementation Deps.mozilla_browser_session implementation Deps.mozilla_browser_session_storage implementation Deps.mozilla_browser_state @@ -548,6 +533,7 @@ dependencies { implementation Deps.mozilla_ui_tabcounter implementation Deps.mozilla_lib_crash + implementation Deps.mozilla_lib_state implementation Deps.mozilla_lib_dataprotect debugImplementation Deps.leakcanary forkDebugImplementation Deps.leakcanary @@ -572,6 +558,8 @@ dependencies { androidTestImplementation Deps.uiautomator // Removed pending AndroidX fixes androidTestImplementation "tools.fastlane:screengrab:2.0.0" + // This Falcon version is added to maven central now required for Screengrab + implementation 'com.jraska:falcon:2.2.0' // androidTestImplementation "br.com.concretesolutions:kappuccino:1.2.1" androidTestImplementation Deps.espresso_core, { diff --git a/app/metrics.yaml b/app/metrics.yaml index 59f89331d..3e63f22ec 100644 --- a/app/metrics.yaml +++ b/app/metrics.yaml @@ -70,17 +70,19 @@ events: - https://github.com/mozilla-mobile/fenix/issues/12573 - https://github.com/mozilla-mobile/fenix/pull/13494 - https://github.com/mozilla-mobile/fenix/issues/10069 + - https://github.com/mozilla-mobile/fenix/issues/19923 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/12114#pullrequestreview-445245341 - https://github.com/mozilla-mobile/fenix/pull/13958#issuecomment-676857877 - https://github.com/mozilla-mobile/fenix/pull/13494#pullrequestreview-474050499 - https://github.com/mozilla-mobile/fenix/pull/15605#issuecomment-702365594 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - interaction notification_emails: - esmyth@mozilla.com - perf-android-fe@mozilla.com - expires: "2021-06-01" + expires: "2021-12-01" app_received_intent: type: event description: | @@ -101,13 +103,15 @@ events: `custom_tab`, `link` or `unknown` bugs: - https://github.com/mozilla-mobile/fenix/issues/11830 + - https://github.com/mozilla-mobile/fenix/issues/19923 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/11940/ - https://github.com/mozilla-mobile/fenix/pull/13958#issuecomment-676857877 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 notification_emails: - esmyth@mozilla.com - perf-android-fe@mozilla.com - expires: "2021-06-01" + expires: "2021-12-01" app_opened: type: event description: | @@ -120,16 +124,18 @@ events: bugs: - https://github.com/mozilla-mobile/fenix/issues/968 - https://github.com/mozilla-mobile/fenix/issues/10616 + - https://github.com/mozilla-mobile/fenix/issues/19923 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/1067#issuecomment-474598673 - https://github.com/mozilla-mobile/fenix/pull/13958#issuecomment-676857877 - https://github.com/mozilla-mobile/fenix/pull/18143 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - interaction notification_emails: - telemetry-client-dev@mozilla.com - - fenix-core@mozilla.com - expires: "2021-07-01" + - android-probes@mozilla.com + expires: "2021-12-01" search_bar_tapped: type: event description: | @@ -141,15 +147,17 @@ events: `Home` or `Browser`) bugs: - https://github.com/mozilla-mobile/fenix/issues/959 + - https://github.com/mozilla-mobile/fenix/issues/19923 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/1067#issuecomment-474598673 - https://github.com/mozilla-mobile/fenix/pull/13958#issuecomment-676857877 - https://github.com/mozilla-mobile/fenix/pull/18143 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - interaction notification_emails: - - fenix-core@mozilla.com - expires: "2021-07-01" + - android-probes@mozilla.com + expires: "2021-12-01" entered_url: type: event description: | @@ -161,15 +169,17 @@ events: Autocomplete suggestion bugs: - https://github.com/mozilla-mobile/fenix/issues/959 + - https://github.com/mozilla-mobile/fenix/issues/19923 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/1067#issuecomment-474598673 - https://github.com/mozilla-mobile/fenix/pull/13958#issuecomment-676857877 - https://github.com/mozilla-mobile/fenix/pull/18143 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - interaction notification_emails: - - fenix-core@mozilla.com - expires: "2021-07-01" + - android-probes@mozilla.com + expires: "2021-12-01" performed_search: type: event description: | @@ -186,16 +196,18 @@ events: * shortcut.suggestion bugs: - https://github.com/mozilla-mobile/fenix/issues/959 + - https://github.com/mozilla-mobile/fenix/issues/19923 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/1067#issuecomment-474598673 - https://github.com/mozilla-mobile/fenix/pull/1677 - https://github.com/mozilla-mobile/fenix/pull/13958#issuecomment-676857877 - https://github.com/mozilla-mobile/fenix/pull/18143 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - interaction notification_emails: - - fenix-core@mozilla.com - expires: "2021-07-01" + - android-probes@mozilla.com + expires: "2021-12-01" browser_menu_action: type: event description: | @@ -205,24 +217,28 @@ events: description: | A string containing the name of the item the user tapped. These items include: - - Settings, Help, Desktop Site toggle on/off, Find in Page, - New Tab, Private Tab, Share, Report Site Issue, Back/Forward button, - Reload Button, Quit, Reader Mode On, Reader Mode Off, Open In app, - Add To Top Sites, Add-ons Manager, Bookmarks, History + add_to_homescreen, add_to_top_sites, addons_manager, back, bookmark, + bookmarks, desktop_view_off, desktop_view_on, downloads, + find_in_page, forward, help, history, library, new_private_tab, + new_tab, open_in_app, open_in_fenix, quit, reader_mode_appearance, + reader_mode_off, reader_mode_on, reload, save_to_collection, + set_default_browser, settings, share, stop, sync_account, and + sync_tabs. bugs: - https://github.com/mozilla-mobile/fenix/issues/1024 + - https://github.com/mozilla-mobile/fenix/issues/19923 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/1214#issue-264756708 - https://github.com/mozilla-mobile/fenix/pull/5098#issuecomment-529658996 - https://github.com/mozilla-mobile/fenix/pull/6310 - https://github.com/mozilla-mobile/fenix/pull/13958#issuecomment-676857877 - https://github.com/mozilla-mobile/fenix/pull/18143 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - interaction notification_emails: - - fenix-core@mozilla.com - expires: "2021-07-01" + - android-probes@mozilla.com + expires: "2021-12-01" default_browser_changed: type: event description: | @@ -231,10 +247,11 @@ events: - https://github.com/mozilla-mobile/fenix/issues/18857 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/18895 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - interaction notification_emails: - - fenix-core@mozilla.com + - android-probes@mozilla.com expires: "2021-10-01" toolbar_menu_visible: type: event @@ -244,10 +261,11 @@ events: - https://github.com/mozilla-mobile/fenix/issues/18855 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/18895 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - interaction notification_emails: - - fenix-core@mozilla.com + - android-probes@mozilla.com expires: "2021-10-01" total_uri_count: type: counter @@ -266,10 +284,11 @@ events: - https://github.com/mozilla-mobile/fenix/pull/1785 - https://github.com/mozilla-mobile/fenix/pull/8314 - https://github.com/mozilla-mobile/fenix/pull/15713#issuecomment-703972068 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - interaction notification_emails: - - fenix-core@mozilla.com + - android-probes@mozilla.com expires: "2021-08-01" normal_and_private_uri_count: type: counter @@ -285,10 +304,11 @@ events: - https://github.com/mozilla-mobile/fenix/issues/17089 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/17935 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - interaction notification_emails: - - fenix-core@mozilla.com + - android-probes@mozilla.com expires: "2022-08-01" preference_toggled: type: event @@ -317,6 +337,7 @@ events: - https://github.com/mozilla-mobile/fenix/issues/5586 - https://github.com/mozilla-mobile/fenix/issues/6396 - https://github.com/mozilla-mobile/fenix/issues/6070 + - https://github.com/mozilla-mobile/fenix/issues/19923 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/1896 - https://github.com/mozilla-mobile/fenix/pull/5704 @@ -326,27 +347,30 @@ events: - https://github.com/mozilla-mobile/fenix/pull/6601 - https://github.com/mozilla-mobile/fenix/pull/6746 - https://github.com/mozilla-mobile/fenix/pull/13958#issuecomment-676857877 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - technical - interaction notification_emails: - - fenix-core@mozilla.com - expires: "2021-06-01" + - android-probes@mozilla.com + expires: "2021-12-01" whats_new_tapped: type: event description: | A user opened the "what's new" page button bugs: - https://github.com/mozilla-mobile/fenix/issues/5021 + - https://github.com/mozilla-mobile/fenix/issues/19923 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/5090 - https://github.com/mozilla-mobile/fenix/pull/13958#issuecomment-676857877 - https://github.com/mozilla-mobile/fenix/pull/18143 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - interaction notification_emails: - - fenix-core@mozilla.com - expires: "2021-07-01" + - android-probes@mozilla.com + expires: "2021-12-01" opened_link: type: event description: | @@ -359,15 +383,17 @@ events: https://github.com/mozilla-mobile/fenix/issues/14133 bugs: - https://github.com/mozilla-mobile/fenix/issues/5737 + - https://github.com/mozilla-mobile/fenix/issues/19923 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/5975 - https://github.com/mozilla-mobile/fenix/pull/13958#issuecomment-676857877 - https://github.com/mozilla-mobile/fenix/pull/18143 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - interaction notification_emails: - - fenix-core@mozilla.com - expires: "2021-07-01" + - android-probes@mozilla.com + expires: "2021-12-01" tab_counter_menu_action: type: event description: @@ -381,28 +407,32 @@ events: New tab, New private tab, Close tab bugs: - https://github.com/mozilla-mobile/fenix/issues/11442 + - https://github.com/mozilla-mobile/fenix/issues/19923 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/11533 - https://github.com/mozilla-mobile/fenix/pull/13958#issuecomment-676857877 - https://github.com/mozilla-mobile/fenix/pull/18143 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - interaction notification_emails: - - fenix-core@mozilla.com - expires: "2021-07-01" + - android-probes@mozilla.com + expires: "2021-12-01" synced_tab_opened: type: event description: > An event that indicates that a synced tab was opened. bugs: - https://github.com/mozilla-mobile/fenix/issues/15369 + - https://github.com/mozilla-mobile/fenix/issues/19923 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/16727 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - interaction notification_emails: - - fenix-core@mozilla.com - expires: "2021-05-10" + - android-probes@mozilla.com + expires: "2021-12-10" recently_closed_tabs_opened: type: event description: | @@ -410,13 +440,15 @@ events: has accessed recently closed tabs list. bugs: - https://github.com/mozilla-mobile/fenix/issues/15366 + - https://github.com/mozilla-mobile/fenix/issues/19923 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/16739 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - interaction notification_emails: - - fenix-core@mozilla.com - expires: "2021-05-10" + - android-probes@mozilla.com + expires: "2021-12-10" copy_url_tapped: type: event description: | @@ -424,13 +456,14 @@ events: copy option when long pressing on url bar. bugs: - https://github.com/mozilla-mobile/fenix/issues/16827 + - https://github.com/mozilla-mobile/fenix/issues/19923 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/16915 data_sensitivity: - interaction notification_emails: - - fenix-core@mozilla.com - expires: "2021-05-10" + - android-probes@mozilla.com + expires: "2021-12-10" onboarding: fxa_auto_signin: @@ -442,10 +475,11 @@ onboarding: data_reviews: - https://github.com/mozilla-mobile/fenix/pull/11867 - https://github.com/mozilla-mobile/fenix/pull/15713#issuecomment-703972068 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - interaction notification_emails: - - fenix-core@mozilla.com + - android-probes@mozilla.com - erichards@mozilla.com expires: "2021-08-01" fxa_manual_signin: @@ -457,10 +491,11 @@ onboarding: data_reviews: - https://github.com/mozilla-mobile/fenix/pull/11867 - https://github.com/mozilla-mobile/fenix/pull/15713#issuecomment-703972068 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - interaction notification_emails: - - fenix-core@mozilla.com + - android-probes@mozilla.com - erichards@mozilla.com expires: "2021-08-01" privacy_notice: @@ -472,10 +507,11 @@ onboarding: data_reviews: - https://github.com/mozilla-mobile/fenix/pull/11867 - https://github.com/mozilla-mobile/fenix/pull/15713#issuecomment-703972068 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - interaction notification_emails: - - fenix-core@mozilla.com + - android-probes@mozilla.com - erichards@mozilla.com expires: "2021-08-01" pref_toggled_private_browsing: @@ -487,10 +523,11 @@ onboarding: data_reviews: - https://github.com/mozilla-mobile/fenix/pull/11867 - https://github.com/mozilla-mobile/fenix/pull/15713#issuecomment-703972068 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - interaction notification_emails: - - fenix-core@mozilla.com + - android-probes@mozilla.com - erichards@mozilla.com expires: "2021-08-01" pref_toggled_toolbar_position: @@ -507,10 +544,11 @@ onboarding: data_reviews: - https://github.com/mozilla-mobile/fenix/pull/11867 - https://github.com/mozilla-mobile/fenix/pull/15713#issuecomment-703972068 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - interaction notification_emails: - - fenix-core@mozilla.com + - android-probes@mozilla.com - erichards@mozilla.com expires: "2021-08-01" pref_toggled_tracking_prot: @@ -527,10 +565,11 @@ onboarding: data_reviews: - https://github.com/mozilla-mobile/fenix/pull/11867 - https://github.com/mozilla-mobile/fenix/pull/15713#issuecomment-703972068 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - interaction notification_emails: - - fenix-core@mozilla.com + - android-probes@mozilla.com - erichards@mozilla.com expires: "2021-08-01" pref_toggled_theme_picker: @@ -547,10 +586,11 @@ onboarding: data_reviews: - https://github.com/mozilla-mobile/fenix/pull/11867 - https://github.com/mozilla-mobile/fenix/pull/15713#issuecomment-703972068 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - interaction notification_emails: - - fenix-core@mozilla.com + - android-probes@mozilla.com - erichards@mozilla.com expires: "2021-08-01" finish: @@ -562,10 +602,11 @@ onboarding: data_reviews: - https://github.com/mozilla-mobile/fenix/pull/11867 - https://github.com/mozilla-mobile/fenix/pull/15713#issuecomment-703972068 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - interaction notification_emails: - - fenix-core@mozilla.com + - android-probes@mozilla.com - erichards@mozilla.com expires: "2021-08-01" @@ -583,8 +624,9 @@ search_shortcuts: data_reviews: - https://github.com/mozilla-mobile/fenix/pull/1202#issuecomment-476870449 - https://github.com/mozilla-mobile/fenix/pull/15713#issuecomment-703972068 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 notification_emails: - - fenix-core@mozilla.com + - android-probes@mozilla.com expires: "2021-08-01" experiments_default_browser: @@ -596,10 +638,11 @@ experiments_default_browser: - https://github.com/mozilla-mobile/fenix/issues/18851 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/18895 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - interaction notification_emails: - - fenix-core@mozilla.com + - android-probes@mozilla.com expires: "2021-10-01" toolbar_settings: changed_position: @@ -615,10 +658,11 @@ toolbar_settings: data_reviews: - https://github.com/mozilla-mobile/fenix/pull/6608 - https://github.com/mozilla-mobile/fenix/pull/15713#issuecomment-703972068 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - interaction notification_emails: - - fenix-core@mozilla.com + - android-probes@mozilla.com expires: "2021-08-01" crash_reporter: @@ -628,15 +672,17 @@ crash_reporter: The crash reporter was displayed bugs: - https://github.com/mozilla-mobile/fenix/issues/1040 + - https://github.com/mozilla-mobile/fenix/issues/19923 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/1214#issue-264756708 - https://github.com/mozilla-mobile/fenix/pull/13958#issuecomment-676857877 - https://github.com/mozilla-mobile/fenix/pull/18143 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - interaction notification_emails: - - fenix-core@mozilla.com - expires: "2021-07-01" + - android-probes@mozilla.com + expires: "2021-12-01" closed: type: event description: | @@ -648,15 +694,17 @@ crash_reporter: report bugs: - https://github.com/mozilla-mobile/fenix/issues/1040 + - https://github.com/mozilla-mobile/fenix/issues/19923 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/1214#issue-264756708 - https://github.com/mozilla-mobile/fenix/pull/13958#issuecomment-676857877 - https://github.com/mozilla-mobile/fenix/pull/18143 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - interaction notification_emails: - - fenix-core@mozilla.com - expires: "2021-07-01" + - android-probes@mozilla.com + expires: "2021-12-01" context_menu: item_tapped: @@ -675,16 +723,18 @@ context_menu: bugs: - https://github.com/mozilla-mobile/fenix/issues/957 - https://github.com/mozilla-mobile/fenix/issues/16076 + - https://github.com/mozilla-mobile/fenix/issues/19923 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/1344#issuecomment-479285010 - https://github.com/mozilla-mobile/fenix/pull/13958#issuecomment-676857877 - https://github.com/mozilla-mobile/fenix/issues/16076#issuecomment-726216734 - https://github.com/mozilla-mobile/fenix/pull/18143 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - interaction notification_emails: - - fenix-core@mozilla.com - expires: "2021-07-01" + - android-probes@mozilla.com + expires: "2021-12-01" login_dialog: displayed: @@ -695,10 +745,11 @@ login_dialog: - https://github.com/mozilla-mobile/fenix/issues/9730 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/13050 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - interaction notification_emails: - - fenix-core@mozilla.com + - android-probes@mozilla.com expires: "2021-08-01" cancelled: type: event @@ -708,10 +759,11 @@ login_dialog: - https://github.com/mozilla-mobile/fenix/issues/9730 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/13050 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - interaction notification_emails: - - fenix-core@mozilla.com + - android-probes@mozilla.com expires: "2021-08-01" saved: type: event @@ -721,10 +773,11 @@ login_dialog: - https://github.com/mozilla-mobile/fenix/issues/9730 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/13050 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - interaction notification_emails: - - fenix-core@mozilla.com + - android-probes@mozilla.com expires: "2021-08-01" never_save: type: event @@ -734,10 +787,11 @@ login_dialog: - https://github.com/mozilla-mobile/fenix/issues/9730 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/13050 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - interaction notification_emails: - - fenix-core@mozilla.com + - android-probes@mozilla.com expires: "2021-08-01" find_in_page: @@ -750,10 +804,11 @@ find_in_page: data_reviews: - https://github.com/mozilla-mobile/fenix/pull/1344#issuecomment-479285010 - https://github.com/mozilla-mobile/fenix/pull/15713#issuecomment-703972068 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - interaction notification_emails: - - fenix-core@mozilla.com + - android-probes@mozilla.com expires: "2021-08-01" closed: type: event @@ -764,10 +819,11 @@ find_in_page: data_reviews: - https://github.com/mozilla-mobile/fenix/pull/1344#issuecomment-479285010 - https://github.com/mozilla-mobile/fenix/pull/15713#issuecomment-703972068 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - interaction notification_emails: - - fenix-core@mozilla.com + - android-probes@mozilla.com expires: "2021-08-01" searched_page: type: event @@ -778,10 +834,11 @@ find_in_page: data_reviews: - https://github.com/mozilla-mobile/fenix/pull/1344#issuecomment-479285010 - https://github.com/mozilla-mobile/fenix/pull/15713#issuecomment-703972068 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - interaction notification_emails: - - fenix-core@mozilla.com + - android-probes@mozilla.com expires: "2021-08-01" metrics: @@ -797,10 +854,11 @@ metrics: data_reviews: - https://github.com/mozilla-mobile/fenix/pull/1067#issuecomment-474598673 - https://github.com/mozilla-mobile/fenix/pull/15713#issuecomment-703972068 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - interaction notification_emails: - - fenix-core@mozilla.com + - android-probes@mozilla.com expires: "2021-08-01" distribution_id: type: string @@ -814,10 +872,11 @@ metrics: - https://github.com/mozilla-mobile/fenix/issues/16075 data_reviews: - https://github.com/mozilla-mobile/fenix/issues/16075 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - technical notification_emails: - - fenix-core@mozilla.com + - android-probes@mozilla.com expires: never mobile_bookmarks_count: type: counter @@ -835,10 +894,11 @@ metrics: data_reviews: - https://github.com/mozilla-mobile/fenix/pull/16942 - https://github.com/mozilla-mobile/fenix/pull/16942#issuecomment-742794701 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - interaction notification_emails: - - fenix-core@mozilla.com + - android-probes@mozilla.com expires: "2021-08-01" has_mobile_bookmarks: type: boolean @@ -852,10 +912,11 @@ metrics: data_reviews: - https://github.com/mozilla-mobile/fenix/pull/16942 - https://github.com/mozilla-mobile/fenix/pull/16942#issuecomment-742794701 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - interaction notification_emails: - - fenix-core@mozilla.com + - android-probes@mozilla.com expires: "2021-08-01" desktop_bookmarks_count: type: counter @@ -873,10 +934,11 @@ metrics: data_reviews: - https://github.com/mozilla-mobile/fenix/pull/16942 - https://github.com/mozilla-mobile/fenix/pull/16942#issuecomment-742794701 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - interaction notification_emails: - - fenix-core@mozilla.com + - android-probes@mozilla.com expires: "2021-08-01" has_desktop_bookmarks: type: boolean @@ -890,10 +952,11 @@ metrics: data_reviews: - https://github.com/mozilla-mobile/fenix/pull/16942 - https://github.com/mozilla-mobile/fenix/pull/16942#issuecomment-742794701 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - interaction notification_emails: - - fenix-core@mozilla.com + - android-probes@mozilla.com expires: "2021-08-01" top_sites_count: type: counter @@ -911,10 +974,11 @@ metrics: data_reviews: - https://github.com/mozilla-mobile/fenix/pull/9556 - https://github.com/mozilla-mobile/fenix/pull/15713#issuecomment-703972068 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - interaction notification_emails: - - fenix-core@mozilla.com + - android-probes@mozilla.com expires: "2021-08-01" has_top_sites: type: boolean @@ -928,10 +992,11 @@ metrics: data_reviews: - https://github.com/mozilla-mobile/fenix/pull/9556 - https://github.com/mozilla-mobile/fenix/pull/15713#issuecomment-703972068 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - interaction notification_emails: - - fenix-core@mozilla.com + - android-probes@mozilla.com expires: "2021-08-01" recently_used_pwa_count: type: counter @@ -953,10 +1018,11 @@ metrics: data_reviews: - https://github.com/mozilla-mobile/fenix/pull/11982#pullrequestreview-437963817 - https://github.com/mozilla-mobile/fenix/pull/15713#issuecomment-703972068 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - interaction notification_emails: - - fenix-core@mozilla.com + - android-probes@mozilla.com expires: "2021-08-01" has_recent_pwas: type: boolean @@ -971,10 +1037,11 @@ metrics: data_reviews: - https://github.com/mozilla-mobile/fenix/pull/11982#pullrequestreview-437963817 - https://github.com/mozilla-mobile/fenix/pull/15713#issuecomment-703972068 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - interaction notification_emails: - - fenix-core@mozilla.com + - android-probes@mozilla.com expires: "2021-08-01" search_count: type: labeled_counter @@ -999,12 +1066,67 @@ metrics: - https://github.com/mozilla-mobile/fenix/pull/5216 - https://github.com/mozilla-mobile/fenix/pull/7310 - https://github.com/mozilla-mobile/fenix/pull/15713#issuecomment-703972068 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - technical - interaction notification_emails: - - fenix-core@mozilla.com + - android-probes@mozilla.com expires: "2021-08-01" + credit_cards_saved_count: + type: counter + lifetime: application + description: | + A counter that indicates the number of credit cards that have been + saved manually by the user. + send_in_pings: + - metrics + bugs: + - https://github.com/mozilla-mobile/fenix/issues/18711 + data_reviews: + - https://github.com/mozilla-mobile/fenix/pull/19548#issuecomment-848811030 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 + data_sensitivity: + - interaction + notification_emails: + - android-probes@mozilla.com + expires: "2021-10-01" + credit_cards_deleted_count: + type: counter + lifetime: application + description: | + A counter that indicates the number of credit cards that have been + deleted by the user. + send_in_pings: + - metrics + bugs: + - https://github.com/mozilla-mobile/fenix/issues/18711 + data_reviews: + - https://github.com/mozilla-mobile/fenix/pull/19548#issuecomment-848811030 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 + data_sensitivity: + - interaction + notification_emails: + - android-probes@mozilla.com + expires: "2021-10-01" + credit_cards_autofill_count: + type: counter + lifetime: application + description: | + A counter that indicates the number of times the user has autofilled + a credit card. + send_in_pings: + - metrics + bugs: + - https://github.com/mozilla-mobile/fenix/issues/18711 + data_reviews: + - https://github.com/mozilla-mobile/fenix/pull/19548#issuecomment-848811030 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 + data_sensitivity: + - interaction + notification_emails: + - android-probes@mozilla.com + expires: "2021-10-01" mozilla_products: type: string_list lifetime: application @@ -1021,11 +1143,12 @@ metrics: - https://github.com/mozilla-mobile/fenix/pull/1953/ - https://github.com/mozilla-mobile/fenix/pull/5216 - https://github.com/mozilla-mobile/fenix/pull/15713#issuecomment-703972068 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - technical - interaction notification_emails: - - fenix-core@mozilla.com + - android-probes@mozilla.com expires: "2021-08-01" default_moz_browser: type: string @@ -1041,11 +1164,12 @@ metrics: - https://github.com/mozilla-mobile/fenix/pull/1953/ - https://github.com/mozilla-mobile/fenix/pull/5216 - https://github.com/mozilla-mobile/fenix/pull/15713#issuecomment-703972068 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - technical - interaction notification_emails: - - fenix-core@mozilla.com + - android-probes@mozilla.com expires: "2021-08-01" adjust_campaign: type: string @@ -1062,10 +1186,11 @@ metrics: data_reviews: - https://github.com/mozilla-mobile/fenix/pull/5579 - https://github.com/mozilla-mobile/fenix/pull/15713#issuecomment-703972068 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - technical notification_emails: - - fenix-core@mozilla.com + - android-probes@mozilla.com expires: "2021-08-01" adjust_ad_group: type: string @@ -1082,10 +1207,11 @@ metrics: data_reviews: - https://github.com/mozilla-mobile/fenix/pull/9253 - https://github.com/mozilla-mobile/fenix/pull/15713#issuecomment-703972068 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - interaction notification_emails: - - fenix-core@mozilla.com + - android-probes@mozilla.com expires: "2021-08-01" adjust_creative: type: string @@ -1102,10 +1228,11 @@ metrics: data_reviews: - https://github.com/mozilla-mobile/fenix/pull/9253 - https://github.com/mozilla-mobile/fenix/pull/15713#issuecomment-703972068 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - interaction notification_emails: - - fenix-core@mozilla.com + - android-probes@mozilla.com expires: "2021-08-01" adjust_network: type: string @@ -1122,10 +1249,11 @@ metrics: data_reviews: - https://github.com/mozilla-mobile/fenix/pull/9253 - https://github.com/mozilla-mobile/fenix/pull/15713#issuecomment-703972068 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - interaction notification_emails: - - fenix-core@mozilla.com + - android-probes@mozilla.com expires: "2021-08-01" toolbar_position: type: string @@ -1139,10 +1267,11 @@ metrics: data_reviews: - https://github.com/mozilla-mobile/fenix/pull/6608 - https://github.com/mozilla-mobile/fenix/pull/15713#issuecomment-703972068 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - interaction notification_emails: - - fenix-core@mozilla.com + - android-probes@mozilla.com expires: "2021-08-01" close_tab_setting: type: string @@ -1156,10 +1285,11 @@ metrics: - https://github.com/mozilla-mobile/fenix/issues/15347#issue-707408975 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/15811#issuecomment-706402952 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - interaction notification_emails: - - fenix-core@mozilla.com + - android-probes@mozilla.com expires: "2021-08-01" tab_view_setting: type: string @@ -1173,10 +1303,11 @@ metrics: - https://github.com/mozilla-mobile/fenix/issues/15347#issue-707408975 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/15811#issuecomment-706402952 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - interaction notification_emails: - - fenix-core@mozilla.com + - android-probes@mozilla.com expires: "2021-08-01" search_widget_installed: type: boolean @@ -1190,10 +1321,11 @@ metrics: data_reviews: - https://github.com/mozilla-mobile/fenix/pull/10958 - https://github.com/mozilla-mobile/fenix/pull/15713#issuecomment-703972068 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - interaction notification_emails: - - fenix-core@mozilla.com + - android-probes@mozilla.com expires: "2021-08-01" tabs_open_count: type: counter @@ -1211,10 +1343,11 @@ metrics: data_reviews: - https://github.com/mozilla-mobile/fenix/pull/12024 - https://github.com/mozilla-mobile/fenix/pull/15713#issuecomment-703972068 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - interaction notification_emails: - - fenix-core@mozilla.com + - android-probes@mozilla.com expires: "2021-08-01" has_open_tabs: type: boolean @@ -1228,10 +1361,11 @@ metrics: data_reviews: - https://github.com/mozilla-mobile/fenix/pull/12024 - https://github.com/mozilla-mobile/fenix/pull/15713#issuecomment-703972068 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - interaction notification_emails: - - fenix-core@mozilla.com + - android-probes@mozilla.com expires: "2021-08-01" start_reason_process_error: type: boolean @@ -1269,8 +1403,8 @@ metrics: expires: "2021-08-11" preferences: - show_search_suggestions: - type: string_list + search_suggestions_enabled: + type: boolean description: > Whether or not the user has search suggestions enabled default: true @@ -1281,13 +1415,14 @@ preferences: data_reviews: - https://github.com/mozilla-mobile/fenix/pull/11211 - https://github.com/mozilla-mobile/fenix/pull/15713#issuecomment-703972068 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - interaction notification_emails: - - fenix-core@mozilla.com + - android-probes@mozilla.com expires: "2021-08-01" - remote_debugging: - type: string_list + remote_debugging_enabled: + type: boolean description: > Whether or not the user has remote debugging enabled default: false @@ -1298,13 +1433,14 @@ preferences: data_reviews: - https://github.com/mozilla-mobile/fenix/pull/11211 - https://github.com/mozilla-mobile/fenix/pull/15713#issuecomment-703972068 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - interaction notification_emails: - - fenix-core@mozilla.com + - android-probes@mozilla.com expires: "2021-08-01" - telemetry: - type: string_list + telemetry_enabled: + type: boolean description: > Whether or not the user has telemetry enabled. Note we should never receive a "false" value for this since telemetry would @@ -1317,13 +1453,14 @@ preferences: data_reviews: - https://github.com/mozilla-mobile/fenix/pull/11211 - https://github.com/mozilla-mobile/fenix/pull/15713#issuecomment-703972068 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - interaction notification_emails: - - fenix-core@mozilla.com + - android-probes@mozilla.com expires: "2021-08-01" - tracking_protection: - type: string_list + enhanced_tracking_protection: + type: string description: > What type of enhanced tracking protection the user has enabled. "standard," "strict," "custom," or "" (if disabled) @@ -1335,13 +1472,14 @@ preferences: data_reviews: - https://github.com/mozilla-mobile/fenix/pull/11211 - https://github.com/mozilla-mobile/fenix/pull/15713#issuecomment-703972068 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - interaction notification_emails: - - fenix-core@mozilla.com + - android-probes@mozilla.com expires: "2021-08-01" - search_bookmarks: - type: string_list + bookmarks_suggestion: + type: boolean description: > Whether or not the user has enabled bookmark search suggestions default: true @@ -1352,13 +1490,14 @@ preferences: data_reviews: - https://github.com/mozilla-mobile/fenix/pull/11211 - https://github.com/mozilla-mobile/fenix/pull/15713#issuecomment-703972068 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - interaction notification_emails: - - fenix-core@mozilla.com + - android-probes@mozilla.com expires: "2021-08-01" - search_browsing_history: - type: string_list + browsing_history_suggestion: + type: boolean description: > Whether or not the user has enabled browsing history suggestions. default: true @@ -1369,13 +1508,14 @@ preferences: data_reviews: - https://github.com/mozilla-mobile/fenix/pull/11211 - https://github.com/mozilla-mobile/fenix/pull/15713#issuecomment-703972068 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - interaction notification_emails: - - fenix-core@mozilla.com + - android-probes@mozilla.com expires: "2021-08-01" - show_clipboard_suggestions: - type: string_list + clipboard_suggestions_enabled: + type: boolean description: > Whether or not the user has enabled clipboard search suggestions. default: true @@ -1386,13 +1526,14 @@ preferences: data_reviews: - https://github.com/mozilla-mobile/fenix/pull/11211 - https://github.com/mozilla-mobile/fenix/pull/15713#issuecomment-703972068 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - interaction notification_emails: - - fenix-core@mozilla.com + - android-probes@mozilla.com expires: "2021-08-01" - show_search_shortcuts: - type: string_list + search_shortcuts_enabled: + type: boolean description: > Whether or not the user has enabled search shortcuts. default: true @@ -1403,13 +1544,14 @@ preferences: data_reviews: - https://github.com/mozilla-mobile/fenix/pull/11211 - https://github.com/mozilla-mobile/fenix/pull/15713#issuecomment-703972068 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - interaction notification_emails: - - fenix-core@mozilla.com + - android-probes@mozilla.com expires: "2021-08-01" - open_links_in_a_private_tab: - type: string_list + open_links_in_private: + type: boolean description: > Whether or not the user has enabled open links in a private tab. default: false @@ -1420,13 +1562,14 @@ preferences: data_reviews: - https://github.com/mozilla-mobile/fenix/pull/11211 - https://github.com/mozilla-mobile/fenix/pull/15713#issuecomment-703972068 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - interaction notification_emails: - - fenix-core@mozilla.com + - android-probes@mozilla.com expires: "2021-08-01" - sync: - type: string_list + signed_in_sync: + type: boolean description: > Whether or not the user is signed into FxA default: false @@ -1437,10 +1580,11 @@ preferences: data_reviews: - https://github.com/mozilla-mobile/fenix/pull/11211 - https://github.com/mozilla-mobile/fenix/pull/15713#issuecomment-703972068 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - interaction notification_emails: - - fenix-core@mozilla.com + - android-probes@mozilla.com expires: "2021-08-01" sync_items: type: string_list @@ -1456,13 +1600,14 @@ preferences: data_reviews: - https://github.com/mozilla-mobile/fenix/pull/11211 - https://github.com/mozilla-mobile/fenix/pull/15713#issuecomment-703972068 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - interaction notification_emails: - - fenix-core@mozilla.com + - android-probes@mozilla.com expires: "2021-08-01" - show_voice_search: - type: string_list + voice_search_enabled: + type: boolean description: > Whether or not the user has enabled the voice search button. default: true @@ -1473,13 +1618,14 @@ preferences: data_reviews: - https://github.com/mozilla-mobile/fenix/pull/11211 - https://github.com/mozilla-mobile/fenix/pull/15713#issuecomment-703972068 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - interaction notification_emails: - - fenix-core@mozilla.com + - android-probes@mozilla.com expires: "2021-08-01" - search_suggestions_private: - type: string_list + private_search_suggestions: + type: boolean description: > Whether or not the user has enabled showing search suggestions in private mode. @@ -1491,13 +1637,14 @@ preferences: data_reviews: - https://github.com/mozilla-mobile/fenix/pull/11211 - https://github.com/mozilla-mobile/fenix/pull/15713#issuecomment-703972068 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - interaction notification_emails: - - fenix-core@mozilla.com + - android-probes@mozilla.com expires: "2021-08-01" - toolbar_position: - type: string_list + toolbar_position_setting: + type: string description: > The position of the toolbar default: bottom (defaults to top if the user has accessibility services) @@ -1508,10 +1655,11 @@ preferences: data_reviews: - https://github.com/mozilla-mobile/fenix/pull/11211 - https://github.com/mozilla-mobile/fenix/pull/15713#issuecomment-703972068 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - interaction notification_emails: - - fenix-core@mozilla.com + - android-probes@mozilla.com expires: "2021-08-01" accessibility_services: type: string_list @@ -1526,13 +1674,14 @@ preferences: data_reviews: - https://github.com/mozilla-mobile/fenix/pull/11211 - https://github.com/mozilla-mobile/fenix/pull/15713#issuecomment-703972068 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - interaction notification_emails: - - fenix-core@mozilla.com + - android-probes@mozilla.com expires: "2021-08-01" - open_links_in_app: - type: string_list + open_links_in_app_enabled: + type: boolean description: > Whether or not the user has the open links in apps feature enabled. default: false @@ -1543,13 +1692,14 @@ preferences: data_reviews: - https://github.com/mozilla-mobile/fenix/pull/11446 - https://github.com/mozilla-mobile/fenix/pull/15713#issuecomment-703972068 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - interaction notification_emails: - - fenix-core@mozilla.com + - android-probes@mozilla.com expires: "2021-08-01" - theme: - type: string_list + user_theme: + type: string description: > The theme the user has enabled. "light," "dark," "system," or "battery" default: "system" for API 28+, else "light" @@ -1560,10 +1710,11 @@ preferences: data_reviews: - https://github.com/mozilla-mobile/fenix/pull/11446 - https://github.com/mozilla-mobile/fenix/pull/15713#issuecomment-703972068 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - interaction notification_emails: - - fenix-core@mozilla.com + - android-probes@mozilla.com expires: "2021-08-01" search.default_engine: @@ -1583,11 +1734,12 @@ search.default_engine: - https://github.com/mozilla-mobile/fenix/pull/1606 - https://github.com/mozilla-mobile/fenix/pull/5216 - https://github.com/mozilla-mobile/fenix/pull/15713#issuecomment-703972068 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - technical - interaction notification_emails: - - fenix-core@mozilla.com + - android-probes@mozilla.com expires: "2021-08-01" name: type: string @@ -1605,11 +1757,12 @@ search.default_engine: - https://github.com/mozilla-mobile/fenix/pull/1606 - https://github.com/mozilla-mobile/fenix/pull/5216 - https://github.com/mozilla-mobile/fenix/pull/15713#issuecomment-703972068 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - technical - interaction notification_emails: - - fenix-core@mozilla.com + - android-probes@mozilla.com expires: "2021-08-01" submission_url: type: string @@ -1628,11 +1781,12 @@ search.default_engine: - https://github.com/mozilla-mobile/fenix/pull/1606 - https://github.com/mozilla-mobile/fenix/pull/5216 - https://github.com/mozilla-mobile/fenix/pull/15713#issuecomment-703972068 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - technical - interaction notification_emails: - - fenix-core@mozilla.com + - android-probes@mozilla.com expires: "2021-08-01" bookmarks_management: @@ -1644,10 +1798,11 @@ bookmarks_management: - https://github.com/mozilla-mobile/fenix/issues/18173 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/18174 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - interaction notification_emails: - - fenix-core@mozilla.com + - android-probes@mozilla.com expires: "2022-08-01" open_in_new_tab: type: event @@ -1659,11 +1814,12 @@ bookmarks_management: - https://github.com/mozilla-mobile/fenix/pull/1708 - https://github.com/mozilla-mobile/fenix/pull/13958#issuecomment-676857877 - https://github.com/mozilla-mobile/fenix/pull/18143 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - interaction notification_emails: - - fenix-core@mozilla.com - expires: "2021-07-01" + - android-probes@mozilla.com + expires: "2021-12-01" open_in_new_tabs: type: event description: | @@ -1674,161 +1830,182 @@ bookmarks_management: - https://github.com/mozilla-mobile/fenix/pull/1708 - https://github.com/mozilla-mobile/fenix/pull/13958#issuecomment-676857877 - https://github.com/mozilla-mobile/fenix/pull/18143 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - interaction notification_emails: - - fenix-core@mozilla.com - expires: "2021-07-01" + - android-probes@mozilla.com + expires: "2021-12-01" open_in_private_tab: type: event description: | A user opened a bookmark in a new private tab. bugs: - https://github.com/mozilla-mobile/fenix/issues/974 + - https://github.com/mozilla-mobile/fenix/issues/19923 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/1708 - https://github.com/mozilla-mobile/fenix/pull/13958#issuecomment-676857877 - https://github.com/mozilla-mobile/fenix/pull/18143 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - interaction notification_emails: - - fenix-core@mozilla.com - expires: "2021-07-01" + - android-probes@mozilla.com + expires: "2021-12-01" open_in_private_tabs: type: event description: | A user opened multiple bookmarks at once in new private tabs. bugs: - https://github.com/mozilla-mobile/fenix/issues/974 + - https://github.com/mozilla-mobile/fenix/issues/19923 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/1708 - https://github.com/mozilla-mobile/fenix/pull/13958#issuecomment-676857877 - https://github.com/mozilla-mobile/fenix/pull/18143 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - interaction notification_emails: - - fenix-core@mozilla.com - expires: "2021-07-01" + - android-probes@mozilla.com + expires: "2021-12-01" edited: type: event description: | A user edited the title and/or URL of an existing bookmark. bugs: - https://github.com/mozilla-mobile/fenix/issues/974 + - https://github.com/mozilla-mobile/fenix/issues/19923 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/1708 - https://github.com/mozilla-mobile/fenix/pull/13958#issuecomment-676857877 - https://github.com/mozilla-mobile/fenix/pull/18143 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - interaction notification_emails: - - fenix-core@mozilla.com - expires: "2021-07-01" + - android-probes@mozilla.com + expires: "2021-12-01" moved: type: event description: | A user moved an existing bookmark or folder to another folder. bugs: - https://github.com/mozilla-mobile/fenix/issues/974 + - https://github.com/mozilla-mobile/fenix/issues/19923 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/1708 - https://github.com/mozilla-mobile/fenix/pull/13958#issuecomment-676857877 - https://github.com/mozilla-mobile/fenix/pull/18143 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - interaction notification_emails: - - fenix-core@mozilla.com - expires: "2021-07-01" + - android-probes@mozilla.com + expires: "2021-12-01" removed: type: event description: | A user removed a bookmark item. bugs: - https://github.com/mozilla-mobile/fenix/issues/974 + - https://github.com/mozilla-mobile/fenix/issues/19923 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/1708 - https://github.com/mozilla-mobile/fenix/pull/13958#issuecomment-676857877 - https://github.com/mozilla-mobile/fenix/pull/18143 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - interaction notification_emails: - - fenix-core@mozilla.com - expires: "2021-07-01" + - android-probes@mozilla.com + expires: "2021-12-01" multi_removed: type: event description: | A user removed multiple bookmarks at once. bugs: - https://github.com/mozilla-mobile/fenix/issues/974 + - https://github.com/mozilla-mobile/fenix/issues/19923 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/1708 - https://github.com/mozilla-mobile/fenix/pull/13958#issuecomment-676857877 - https://github.com/mozilla-mobile/fenix/pull/18143 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - interaction notification_emails: - - fenix-core@mozilla.com - expires: "2021-07-01" + - android-probes@mozilla.com + expires: "2021-12-01" shared: type: event description: | A user shared a bookmark. bugs: - https://github.com/mozilla-mobile/fenix/issues/974 + - https://github.com/mozilla-mobile/fenix/issues/19923 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/1708 - https://github.com/mozilla-mobile/fenix/pull/13958#issuecomment-676857877 - https://github.com/mozilla-mobile/fenix/pull/18143 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - interaction notification_emails: - - fenix-core@mozilla.com - expires: "2021-07-01" + - android-probes@mozilla.com + expires: "2021-12-01" copied: type: event description: | A user copied a bookmark. bugs: - https://github.com/mozilla-mobile/fenix/issues/974 + - https://github.com/mozilla-mobile/fenix/issues/19923 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/1708 - https://github.com/mozilla-mobile/fenix/pull/13958#issuecomment-676857877 - https://github.com/mozilla-mobile/fenix/pull/18143 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - interaction notification_emails: - - fenix-core@mozilla.com - expires: "2021-07-01" + - android-probes@mozilla.com + expires: "2021-12-01" folder_add: type: event description: | A user added a new bookmark folder. bugs: - https://github.com/mozilla-mobile/fenix/issues/974 + - https://github.com/mozilla-mobile/fenix/issues/19923 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/1708 - https://github.com/mozilla-mobile/fenix/pull/13958#issuecomment-676857877 - https://github.com/mozilla-mobile/fenix/pull/18143 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - interaction notification_emails: - - fenix-core@mozilla.com - expires: "2021-07-01" + - android-probes@mozilla.com + expires: "2021-12-01" folder_remove: type: event description: | A user removed a bookmark folder. bugs: - https://github.com/mozilla-mobile/fenix/issues/3174 + - https://github.com/mozilla-mobile/fenix/issues/19923 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/3724 - https://github.com/mozilla-mobile/fenix/pull/13958#issuecomment-676857877 - https://github.com/mozilla-mobile/fenix/pull/18143 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - interaction notification_emails: - - fenix-core@mozilla.com - expires: "2021-07-01" + - android-probes@mozilla.com + expires: "2021-12-01" custom_tab: closed: @@ -1837,45 +2014,51 @@ custom_tab: A user closed the custom tab bugs: - https://github.com/mozilla-mobile/fenix/issues/977 + - https://github.com/mozilla-mobile/fenix/issues/19923 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/1697 - https://github.com/mozilla-mobile/fenix/pull/13958#issuecomment-676857877 - https://github.com/mozilla-mobile/fenix/pull/18143 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - interaction notification_emails: - - fenix-core@mozilla.com - expires: "2021-07-01" + - android-probes@mozilla.com + expires: "2021-12-01" action_button: type: event description: | A user pressed the action button provided by the launching app bugs: - https://github.com/mozilla-mobile/fenix/issues/977 + - https://github.com/mozilla-mobile/fenix/issues/19923 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/1697 - https://github.com/mozilla-mobile/fenix/pull/13958#issuecomment-676857877 - https://github.com/mozilla-mobile/fenix/pull/18143 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - interaction notification_emails: - - fenix-core@mozilla.com - expires: "2021-07-01" + - android-probes@mozilla.com + expires: "2021-12-01" menu: type: event description: | A user opened the custom tabs menu bugs: - https://github.com/mozilla-mobile/fenix/issues/977 + - https://github.com/mozilla-mobile/fenix/issues/19923 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/1697 - https://github.com/mozilla-mobile/fenix/pull/13958#issuecomment-676857877 - https://github.com/mozilla-mobile/fenix/pull/18143 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - interaction notification_emails: - - fenix-core@mozilla.com - expires: "2021-07-01" + - android-probes@mozilla.com + expires: "2021-12-01" activation: identifier: @@ -1889,15 +2072,17 @@ activation: bugs: - https://bugzilla.mozilla.org/1538011 - https://bugzilla.mozilla.org/1501822 + - https://github.com/mozilla-mobile/fenix/issues/19923 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/1707#issuecomment-486972209 - https://github.com/mozilla-mobile/fenix/pull/13958#issuecomment-676857877 - https://github.com/mozilla-mobile/fenix/pull/18143 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - highly_sensitive notification_emails: - - fenix-core@mozilla.com - expires: "2021-07-01" + - android-probes@mozilla.com + expires: "2021-12-01" activation_id: type: uuid lifetime: user @@ -1908,15 +2093,17 @@ activation: - activation bugs: - https://bugzilla.mozilla.org/1538011 + - https://github.com/mozilla-mobile/fenix/issues/19923 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/1707#issuecomment-486972209 - https://github.com/mozilla-mobile/fenix/pull/13958#issuecomment-676857877 - https://github.com/mozilla-mobile/fenix/pull/18143 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - highly_sensitive notification_emails: - - fenix-core@mozilla.com - expires: "2021-07-01" + - android-probes@mozilla.com + expires: "2021-12-01" no_lint: - USER_LIFETIME_EXPIRATION @@ -1930,15 +2117,17 @@ error_page: description: "The error type of the error page encountered" bugs: - https://github.com/mozilla-mobile/fenix/issues/1242 + - https://github.com/mozilla-mobile/fenix/issues/19923 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/2491#issuecomment-492414486 - https://github.com/mozilla-mobile/fenix/pull/13958#issuecomment-676857877 - https://github.com/mozilla-mobile/fenix/pull/18143 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - interaction notification_emails: - - fenix-core@mozilla.com - expires: "2021-07-01" + - android-probes@mozilla.com + expires: "2021-12-01" sync_auth: opened: @@ -1950,10 +2139,11 @@ sync_auth: data_reviews: - https://github.com/mozilla-mobile/fenix/pull/2745#issuecomment-494918532 - https://github.com/mozilla-mobile/fenix/pull/15713#issuecomment-703972068 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - interaction notification_emails: - - fenix-core@mozilla.com + - android-probes@mozilla.com expires: "2021-08-01" closed: type: event @@ -1964,10 +2154,11 @@ sync_auth: data_reviews: - https://github.com/mozilla-mobile/fenix/pull/2745#issuecomment-494918532 - https://github.com/mozilla-mobile/fenix/pull/15713#issuecomment-703972068 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - interaction notification_emails: - - fenix-core@mozilla.com + - android-probes@mozilla.com expires: "2021-08-01" use_email: type: event @@ -1979,10 +2170,11 @@ sync_auth: data_reviews: - https://github.com/mozilla-mobile/fenix/pull/9835#pullrequestreview-398641844 - https://github.com/mozilla-mobile/fenix/pull/15713#issuecomment-703972068 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - interaction notification_emails: - - fenix-core@mozilla.com + - android-probes@mozilla.com expires: "2021-08-01" use_email_problem: type: event @@ -1993,10 +2185,11 @@ sync_auth: data_reviews: - https://github.com/mozilla-mobile/fenix/pull/9835#pullrequestreview-398641844 - https://github.com/mozilla-mobile/fenix/pull/15713#issuecomment-703972068 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - interaction notification_emails: - - fenix-core@mozilla.com + - android-probes@mozilla.com expires: "2021-08-01" sign_in: type: event @@ -2008,10 +2201,11 @@ sync_auth: data_reviews: - https://github.com/mozilla-mobile/fenix/pull/2745#issuecomment-494918532 - https://github.com/mozilla-mobile/fenix/pull/15713#issuecomment-703972068 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - interaction notification_emails: - - fenix-core@mozilla.com + - android-probes@mozilla.com expires: "2021-08-01" sign_out: type: event @@ -2023,10 +2217,11 @@ sync_auth: data_reviews: - https://github.com/mozilla-mobile/fenix/pull/2745#issuecomment-494918532 - https://github.com/mozilla-mobile/fenix/pull/15713#issuecomment-703972068 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - interaction notification_emails: - - fenix-core@mozilla.com + - android-probes@mozilla.com expires: "2021-08-01" sign_up: type: event @@ -2037,11 +2232,12 @@ sync_auth: data_reviews: - https://github.com/mozilla-mobile/fenix/pull/4931#issuecomment-529740300 - https://github.com/mozilla-mobile/fenix/pull/15713#issuecomment-703972068 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - technical - interaction notification_emails: - - fenix-core@mozilla.com + - android-probes@mozilla.com expires: "2021-08-01" paired: type: event @@ -2053,11 +2249,12 @@ sync_auth: data_reviews: - https://github.com/mozilla-mobile/fenix/pull/4931#issuecomment-529740300 - https://github.com/mozilla-mobile/fenix/pull/15713#issuecomment-703972068 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - technical - interaction notification_emails: - - fenix-core@mozilla.com + - android-probes@mozilla.com expires: "2021-08-01" recovered: type: event @@ -2069,11 +2266,12 @@ sync_auth: data_reviews: - https://github.com/mozilla-mobile/fenix/pull/4931#issuecomment-529740300 - https://github.com/mozilla-mobile/fenix/pull/15713#issuecomment-703972068 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - technical - interaction notification_emails: - - fenix-core@mozilla.com + - android-probes@mozilla.com expires: "2021-08-01" other_external: type: event @@ -2085,11 +2283,12 @@ sync_auth: data_reviews: - https://github.com/mozilla-mobile/fenix/pull/4931#issuecomment-529740300 - https://github.com/mozilla-mobile/fenix/pull/15713#issuecomment-703972068 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - technical - interaction notification_emails: - - fenix-core@mozilla.com + - android-probes@mozilla.com expires: "2021-08-01" scan_pairing: type: event @@ -2100,10 +2299,11 @@ sync_auth: data_reviews: - https://github.com/mozilla-mobile/fenix/pull/2745#issuecomment-494918532 - https://github.com/mozilla-mobile/fenix/pull/15713#issuecomment-703972068 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - interaction notification_emails: - - fenix-core@mozilla.com + - android-probes@mozilla.com expires: "2021-08-01" sync_account: @@ -2116,10 +2316,11 @@ sync_account: data_reviews: - https://github.com/mozilla-mobile/fenix/pull/2745#issuecomment-494918532 - https://github.com/mozilla-mobile/fenix/pull/15713#issuecomment-703972068 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - interaction notification_emails: - - fenix-core@mozilla.com + - android-probes@mozilla.com expires: "2021-08-01" sync_now: type: event @@ -2130,10 +2331,11 @@ sync_account: data_reviews: - https://github.com/mozilla-mobile/fenix/pull/2745#issuecomment-494918532 - https://github.com/mozilla-mobile/fenix/pull/15713#issuecomment-703972068 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - interaction notification_emails: - - fenix-core@mozilla.com + - android-probes@mozilla.com expires: "2021-08-01" send_tab: type: event @@ -2144,10 +2346,11 @@ sync_account: data_reviews: - https://github.com/mozilla-mobile/fenix/pull/5106 - https://github.com/mozilla-mobile/fenix/pull/15713#issuecomment-703972068 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - interaction notification_emails: - - fenix-core@mozilla.com + - android-probes@mozilla.com expires: "2021-08-01" sign_in_to_send_tab: type: event @@ -2158,10 +2361,11 @@ sync_account: data_reviews: - https://github.com/mozilla-mobile/fenix/pull/5106 - https://github.com/mozilla-mobile/fenix/pull/15713#issuecomment-703972068 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - interaction notification_emails: - - fenix-core@mozilla.com + - android-probes@mozilla.com expires: "2021-08-01" history: @@ -2174,10 +2378,11 @@ history: data_reviews: - https://github.com/mozilla-mobile/fenix/pull/3940 - https://github.com/mozilla-mobile/fenix/pull/15713#issuecomment-703972068 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - interaction notification_emails: - - fenix-core@mozilla.com + - android-probes@mozilla.com expires: "2021-08-01" removed: type: event @@ -2188,10 +2393,11 @@ history: data_reviews: - https://github.com/mozilla-mobile/fenix/pull/3940 - https://github.com/mozilla-mobile/fenix/pull/15713#issuecomment-703972068 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - interaction notification_emails: - - fenix-core@mozilla.com + - android-probes@mozilla.com expires: "2021-08-01" removed_all: type: event @@ -2202,10 +2408,11 @@ history: data_reviews: - https://github.com/mozilla-mobile/fenix/pull/3940 - https://github.com/mozilla-mobile/fenix/pull/15713#issuecomment-703972068 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - interaction notification_emails: - - fenix-core@mozilla.com + - android-probes@mozilla.com expires: "2021-08-01" shared: type: event @@ -2216,10 +2423,11 @@ history: data_reviews: - https://github.com/mozilla-mobile/fenix/pull/3940 - https://github.com/mozilla-mobile/fenix/pull/15713#issuecomment-703972068 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - interaction notification_emails: - - fenix-core@mozilla.com + - android-probes@mozilla.com expires: "2021-08-01" opened_item: type: event @@ -2229,10 +2437,11 @@ history: - https://github.com/mozilla-mobile/fenix/issues/18178 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/18261 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - interaction notification_emails: - - fenix-core@mozilla.com + - android-probes@mozilla.com expires: "2022-08-01" opened_item_in_new_tab: type: event @@ -2242,10 +2451,11 @@ history: - https://github.com/mozilla-mobile/fenix/issues/18178 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/18261 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - interaction notification_emails: - - fenix-core@mozilla.com + - android-probes@mozilla.com expires: "2022-08-01" opened_items_in_new_tabs: type: event @@ -2253,12 +2463,14 @@ history: A user opened multiple history items in new tabs bugs: - https://github.com/mozilla-mobile/fenix/issues/18178 + - https://github.com/mozilla-mobile/fenix/issues/19923 data_reviews: - - https://gith ub.com/mozilla-mobile/fenix/pull/18261 + - https://github.com/mozilla-mobile/fenix/pull/18261 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - interaction notification_emails: - - fenix-core@mozilla.com + - android-probes@mozilla.com expires: "2022-08-01" opened_item_in_private_tab: type: event @@ -2268,10 +2480,11 @@ history: - https://github.com/mozilla-mobile/fenix/issues/18178 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/18261 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - interaction notification_emails: - - fenix-core@mozilla.com + - android-probes@mozilla.com expires: "2022-08-01" opened_items_in_private_tabs: type: event @@ -2281,10 +2494,11 @@ history: - https://github.com/mozilla-mobile/fenix/issues/18178 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/18261 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - interaction notification_emails: - - fenix-core@mozilla.com + - android-probes@mozilla.com expires: "2022-08-01" tip: @@ -2300,10 +2514,11 @@ tip: data_reviews: - https://github.com/mozilla-mobile/fenix/pull/9836 - https://github.com/mozilla-mobile/fenix/pull/15713#issuecomment-703972068 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - interaction notification_emails: - - fenix-core@mozilla.com + - android-probes@mozilla.com expires: "2021-08-01" pressed: type: event @@ -2317,10 +2532,11 @@ tip: data_reviews: - https://github.com/mozilla-mobile/fenix/pull/9836 - https://github.com/mozilla-mobile/fenix/pull/15713#issuecomment-703972068 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - interaction notification_emails: - - fenix-core@mozilla.com + - android-probes@mozilla.com expires: "2021-08-01" closed: type: event @@ -2334,10 +2550,11 @@ tip: data_reviews: - https://github.com/mozilla-mobile/fenix/pull/9836 - https://github.com/mozilla-mobile/fenix/pull/15713#issuecomment-703972068 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - interaction notification_emails: - - fenix-core@mozilla.com + - android-probes@mozilla.com expires: "2021-08-01" reader_mode: @@ -2350,10 +2567,11 @@ reader_mode: data_reviews: - https://github.com/mozilla-mobile/fenix/pull/3941 - https://github.com/mozilla-mobile/fenix/pull/15713#issuecomment-703972068 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - interaction notification_emails: - - fenix-core@mozilla.com + - android-probes@mozilla.com expires: "2021-08-01" opened: type: event @@ -2364,10 +2582,11 @@ reader_mode: data_reviews: - https://github.com/mozilla-mobile/fenix/pull/3941 - https://github.com/mozilla-mobile/fenix/pull/15713#issuecomment-703972068 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - interaction notification_emails: - - fenix-core@mozilla.com + - android-probes@mozilla.com expires: "2021-08-01" closed: type: event @@ -2378,10 +2597,11 @@ reader_mode: data_reviews: - https://github.com/mozilla-mobile/fenix/pull/4328 - https://github.com/mozilla-mobile/fenix/pull/15713#issuecomment-703972068 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - interaction notification_emails: - - fenix-core@mozilla.com + - android-probes@mozilla.com expires: "2021-08-01" appearance: type: event @@ -2392,10 +2612,11 @@ reader_mode: data_reviews: - https://github.com/mozilla-mobile/fenix/pull/3941 - https://github.com/mozilla-mobile/fenix/pull/15713#issuecomment-703972068 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - interaction notification_emails: - - fenix-core@mozilla.com + - android-probes@mozilla.com expires: "2021-08-01" tabs_tray.cfr: @@ -2408,10 +2629,11 @@ tabs_tray.cfr: data_reviews: - https://github.com/mozilla-mobile/fenix/pull/17442 - https://github.com/mozilla-mobile/fenix/issues/16485#issuecomment-759641324 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - interaction notification_emails: - - fenix-core@mozilla.com + - android-probes@mozilla.com expires: "2021-08-01" go_to_settings: type: event @@ -2422,10 +2644,11 @@ tabs_tray.cfr: data_reviews: - https://github.com/mozilla-mobile/fenix/pull/17442 - https://github.com/mozilla-mobile/fenix/issues/16485#issuecomment-759641324 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - interaction notification_emails: - - fenix-core@mozilla.com + - android-probes@mozilla.com expires: "2021-08-01" tabs_tray: @@ -2438,10 +2661,11 @@ tabs_tray: data_reviews: - https://github.com/mozilla-mobile/fenix/pull/12036 - https://github.com/mozilla-mobile/fenix/pull/15713#issuecomment-703972068 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - interaction notification_emails: - - fenix-core@mozilla.com + - android-probes@mozilla.com expires: "2021-08-01" closed: type: event @@ -2452,10 +2676,11 @@ tabs_tray: data_reviews: - https://github.com/mozilla-mobile/fenix/pull/12036 - https://github.com/mozilla-mobile/fenix/pull/15713#issuecomment-703972068 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - interaction notification_emails: - - fenix-core@mozilla.com + - android-probes@mozilla.com expires: "2021-08-01" opened_existing_tab: type: event @@ -2466,10 +2691,11 @@ tabs_tray: data_reviews: - https://github.com/mozilla-mobile/fenix/pull/12036 - https://github.com/mozilla-mobile/fenix/pull/15713#issuecomment-703972068 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - interaction notification_emails: - - fenix-core@mozilla.com + - android-probes@mozilla.com expires: "2021-08-01" closed_existing_tab: type: event @@ -2480,10 +2706,11 @@ tabs_tray: data_reviews: - https://github.com/mozilla-mobile/fenix/pull/12036 - https://github.com/mozilla-mobile/fenix/pull/15713#issuecomment-703972068 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - interaction notification_emails: - - fenix-core@mozilla.com + - android-probes@mozilla.com expires: "2021-08-01" private_mode_tapped: type: event @@ -2494,10 +2721,11 @@ tabs_tray: data_reviews: - https://github.com/mozilla-mobile/fenix/pull/12036 - https://github.com/mozilla-mobile/fenix/pull/15713#issuecomment-703972068 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - interaction notification_emails: - - fenix-core@mozilla.com + - android-probes@mozilla.com expires: "2021-08-01" normal_mode_tapped: type: event @@ -2508,10 +2736,11 @@ tabs_tray: data_reviews: - https://github.com/mozilla-mobile/fenix/pull/12036 - https://github.com/mozilla-mobile/fenix/pull/15713#issuecomment-703972068 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - interaction notification_emails: - - fenix-core@mozilla.com + - android-probes@mozilla.com expires: "2021-08-01" synced_mode_tapped: type: event @@ -2521,10 +2750,11 @@ tabs_tray: - https://github.com/mozilla-mobile/fenix/issues/18948 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/19004 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - interaction notification_emails: - - fenix-core@mozilla.com + - android-probes@mozilla.com expires: "2022-08-01" new_tab_tapped: type: event @@ -2535,10 +2765,11 @@ tabs_tray: data_reviews: - https://github.com/mozilla-mobile/fenix/pull/12036 - https://github.com/mozilla-mobile/fenix/pull/15713#issuecomment-703972068 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - interaction notification_emails: - - fenix-core@mozilla.com + - android-probes@mozilla.com expires: "2021-08-01" new_private_tab_tapped: type: event @@ -2549,10 +2780,11 @@ tabs_tray: data_reviews: - https://github.com/mozilla-mobile/fenix/pull/12036 - https://github.com/mozilla-mobile/fenix/pull/15713#issuecomment-703972068 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - interaction notification_emails: - - fenix-core@mozilla.com + - android-probes@mozilla.com expires: "2021-08-01" menu_opened: type: event @@ -2563,10 +2795,11 @@ tabs_tray: data_reviews: - https://github.com/mozilla-mobile/fenix/pull/12036 - https://github.com/mozilla-mobile/fenix/pull/15713#issuecomment-703972068 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - interaction notification_emails: - - fenix-core@mozilla.com + - android-probes@mozilla.com expires: "2021-08-01" save_to_collection: type: event @@ -2577,10 +2810,11 @@ tabs_tray: data_reviews: - https://github.com/mozilla-mobile/fenix/pull/12036 - https://github.com/mozilla-mobile/fenix/pull/15713#issuecomment-703972068 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - interaction notification_emails: - - fenix-core@mozilla.com + - android-probes@mozilla.com expires: "2021-08-01" share_all_tabs: type: event @@ -2592,10 +2826,11 @@ tabs_tray: data_reviews: - https://github.com/mozilla-mobile/fenix/pull/12036 - https://github.com/mozilla-mobile/fenix/pull/15713#issuecomment-703972068 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - interaction notification_emails: - - fenix-core@mozilla.com + - android-probes@mozilla.com expires: "2021-08-01" close_all_tabs: type: event @@ -2607,10 +2842,11 @@ tabs_tray: data_reviews: - https://github.com/mozilla-mobile/fenix/pull/12036 - https://github.com/mozilla-mobile/fenix/pull/15713#issuecomment-703972068 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - interaction notification_emails: - - fenix-core@mozilla.com + - android-probes@mozilla.com expires: "2021-08-01" collections: @@ -2620,96 +2856,108 @@ collections: A user renamed a collection bugs: - https://github.com/mozilla-mobile/fenix/issues/969 + - https://github.com/mozilla-mobile/fenix/issues/19923 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/3935 - https://github.com/mozilla-mobile/fenix/pull/13958#issuecomment-676857877 - https://github.com/mozilla-mobile/fenix/pull/18143 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - technical - interaction notification_emails: - - fenix-core@mozilla.com - expires: "2021-07-01" + - android-probes@mozilla.com + expires: "2021-12-01" tab_restored: type: event description: | A user restored a tab from collection tab list bugs: - https://github.com/mozilla-mobile/fenix/issues/969 + - https://github.com/mozilla-mobile/fenix/issues/19923 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/3935 - https://github.com/mozilla-mobile/fenix/pull/13958#issuecomment-676857877 - https://github.com/mozilla-mobile/fenix/pull/18143 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - technical - interaction notification_emails: - - fenix-core@mozilla.com - expires: "2021-07-01" + - android-probes@mozilla.com + expires: "2021-12-01" all_tabs_restored: type: event description: | A user tapped "open tabs" from collection menu bugs: - https://github.com/mozilla-mobile/fenix/issues/969 + - https://github.com/mozilla-mobile/fenix/issues/19923 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/3935 - https://github.com/mozilla-mobile/fenix/pull/13958#issuecomment-676857877 - https://github.com/mozilla-mobile/fenix/pull/18143 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - technical - interaction notification_emails: - - fenix-core@mozilla.com - expires: "2021-07-01" + - android-probes@mozilla.com + expires: "2021-12-01" tab_removed: type: event description: | A user tapped remove tab from collection tab list bugs: - https://github.com/mozilla-mobile/fenix/issues/969 + - https://github.com/mozilla-mobile/fenix/issues/19923 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/3935 - https://github.com/mozilla-mobile/fenix/pull/13958#issuecomment-676857877 - https://github.com/mozilla-mobile/fenix/pull/18143 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - technical - interaction notification_emails: - - fenix-core@mozilla.com - expires: "2021-07-01" + - android-probes@mozilla.com + expires: "2021-12-01" shared: type: event description: | A user tapped share collection bugs: - https://github.com/mozilla-mobile/fenix/issues/969 + - https://github.com/mozilla-mobile/fenix/issues/19923 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/3935 - https://github.com/mozilla-mobile/fenix/pull/13958#issuecomment-676857877 - https://github.com/mozilla-mobile/fenix/pull/18143 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - technical - interaction notification_emails: - - fenix-core@mozilla.com - expires: "2021-07-01" + - android-probes@mozilla.com + expires: "2021-12-01" removed: type: event description: | A user tapped delete collection from collection menu bugs: - https://github.com/mozilla-mobile/fenix/issues/969 + - https://github.com/mozilla-mobile/fenix/issues/19923 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/3935 - https://github.com/mozilla-mobile/fenix/pull/13958#issuecomment-676857877 - https://github.com/mozilla-mobile/fenix/pull/18143 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - technical - interaction notification_emails: - - fenix-core@mozilla.com - expires: "2021-07-01" + - android-probes@mozilla.com + expires: "2021-12-01" saved: type: event description: | @@ -2721,16 +2969,18 @@ collections: description: "The number of tabs added to the collection" bugs: - https://github.com/mozilla-mobile/fenix/issues/969 + - https://github.com/mozilla-mobile/fenix/issues/19923 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/3935 - https://github.com/mozilla-mobile/fenix/pull/13958#issuecomment-676857877 - https://github.com/mozilla-mobile/fenix/pull/18143 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - technical - interaction notification_emails: - - fenix-core@mozilla.com - expires: "2021-07-01" + - android-probes@mozilla.com + expires: "2021-12-01" tabs_added: type: event description: | @@ -2742,16 +2992,18 @@ collections: description: "The number of tabs added to the collection" bugs: - https://github.com/mozilla-mobile/fenix/issues/969 + - https://github.com/mozilla-mobile/fenix/issues/19923 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/3935 - https://github.com/mozilla-mobile/fenix/pull/13958#issuecomment-676857877 - https://github.com/mozilla-mobile/fenix/pull/18143 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - technical - interaction notification_emails: - - fenix-core@mozilla.com - expires: "2021-07-01" + - android-probes@mozilla.com + expires: "2021-12-01" tab_select_opened: type: event description: | @@ -2759,46 +3011,52 @@ collections: creation flow) bugs: - https://github.com/mozilla-mobile/fenix/issues/969 + - https://github.com/mozilla-mobile/fenix/issues/19923 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/3935 - https://github.com/mozilla-mobile/fenix/pull/13958#issuecomment-676857877 - https://github.com/mozilla-mobile/fenix/pull/18143 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - technical - interaction notification_emails: - - fenix-core@mozilla.com - expires: "2021-07-01" + - android-probes@mozilla.com + expires: "2021-12-01" add_tab_button: type: event description: | A user tapped the "add tab" button in the three dot menu of collections bugs: - https://github.com/mozilla-mobile/fenix/issues/969 + - https://github.com/mozilla-mobile/fenix/issues/19923 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/4358 - https://github.com/mozilla-mobile/fenix/pull/13958#issuecomment-676857877 - https://github.com/mozilla-mobile/fenix/pull/18143 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - interaction notification_emails: - - fenix-core@mozilla.com - expires: "2021-07-01" + - android-probes@mozilla.com + expires: "2021-12-01" long_press: type: event description: | A user long pressed on a tab, triggering the collection creation screen bugs: - https://github.com/mozilla-mobile/fenix/issues/969 + - https://github.com/mozilla-mobile/fenix/issues/19923 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/4358 - https://github.com/mozilla-mobile/fenix/pull/13958#issuecomment-676857877 - https://github.com/mozilla-mobile/fenix/pull/18143 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - interaction notification_emails: - - fenix-core@mozilla.com - expires: "2021-07-01" + - android-probes@mozilla.com + expires: "2021-12-01" save_button: type: event description: | @@ -2807,15 +3065,17 @@ collections: (tab_select_opened) bugs: - https://github.com/mozilla-mobile/fenix/issues/969 + - https://github.com/mozilla-mobile/fenix/issues/19923 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/4358 - https://github.com/mozilla-mobile/fenix/pull/13958#issuecomment-676857877 - https://github.com/mozilla-mobile/fenix/pull/18143 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - interaction notification_emails: - - fenix-core@mozilla.com - expires: "2021-07-01" + - android-probes@mozilla.com + expires: "2021-12-01" extra_keys: from_screen: description: | @@ -2827,15 +3087,17 @@ collections: A user pressed the "rename collection" button in the three dot menu bugs: - https://github.com/mozilla-mobile/fenix/issues/969 + - https://github.com/mozilla-mobile/fenix/issues/19923 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/4539 - https://github.com/mozilla-mobile/fenix/pull/13958#issuecomment-676857877 - https://github.com/mozilla-mobile/fenix/pull/18143 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - interaction notification_emails: - - fenix-core@mozilla.com - expires: "2021-07-01" + - android-probes@mozilla.com + expires: "2021-12-01" search_widget: new_tab_button: @@ -2848,10 +3110,11 @@ search_widget: data_reviews: - https://github.com/mozilla-mobile/fenix/pull/4714 - https://github.com/mozilla-mobile/fenix/pull/15713#issuecomment-703972068 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - interaction notification_emails: - - fenix-core@mozilla.com + - android-probes@mozilla.com expires: "2021-08-01" voice_button: type: event @@ -2862,10 +3125,11 @@ search_widget: data_reviews: - https://github.com/mozilla-mobile/fenix/pull/4714 - https://github.com/mozilla-mobile/fenix/pull/15713#issuecomment-703972068 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - interaction notification_emails: - - fenix-core@mozilla.com + - android-probes@mozilla.com expires: "2021-08-01" private_browsing_mode: @@ -2879,10 +3143,11 @@ private_browsing_mode: data_reviews: - https://github.com/mozilla-mobile/fenix/pull/4968 - https://github.com/mozilla-mobile/fenix/pull/15713#issuecomment-703972068 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - interaction notification_emails: - - fenix-core@mozilla.com + - android-probes@mozilla.com expires: "2021-08-01" notification_tapped: type: event @@ -2893,10 +3158,11 @@ private_browsing_mode: data_reviews: - https://github.com/mozilla-mobile/fenix/pull/4968 - https://github.com/mozilla-mobile/fenix/pull/15713#issuecomment-703972068 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - interaction notification_emails: - - fenix-core@mozilla.com + - android-probes@mozilla.com expires: "2021-08-01" contextual_hint.tracking_protection: @@ -2911,10 +3177,11 @@ contextual_hint.tracking_protection: - https://github.com/mozilla-mobile/fenix/pull/11923 - https://github.com/mozilla-mobile/fenix/pull/13958#issuecomment-676857877 - https://github.com/mozilla-mobile/fenix/pull/18143 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - interaction notification_emails: - - fenix-core@mozilla.com + - android-probes@mozilla.com expires: "2021-07-01" dismiss: type: event @@ -2928,10 +3195,11 @@ contextual_hint.tracking_protection: - https://github.com/mozilla-mobile/fenix/pull/11923 - https://github.com/mozilla-mobile/fenix/pull/13958#issuecomment-676857877 - https://github.com/mozilla-mobile/fenix/pull/18143 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - interaction notification_emails: - - fenix-core@mozilla.com + - android-probes@mozilla.com expires: "2021-07-01" outside_tap: type: event @@ -2944,10 +3212,11 @@ contextual_hint.tracking_protection: - https://github.com/mozilla-mobile/fenix/pull/11923 - https://github.com/mozilla-mobile/fenix/pull/13958#issuecomment-676857877 - https://github.com/mozilla-mobile/fenix/pull/18143 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - interaction notification_emails: - - fenix-core@mozilla.com + - android-probes@mozilla.com expires: "2021-07-01" inside_tap: type: event @@ -2960,10 +3229,11 @@ contextual_hint.tracking_protection: - https://github.com/mozilla-mobile/fenix/pull/11923 - https://github.com/mozilla-mobile/fenix/pull/13958#issuecomment-676857877 - https://github.com/mozilla-mobile/fenix/pull/18143 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - interaction notification_emails: - - fenix-core@mozilla.com + - android-probes@mozilla.com expires: "2021-07-01" tracking_protection: @@ -2977,10 +3247,11 @@ tracking_protection: data_reviews: - https://github.com/mozilla-mobile/fenix/pull/5414#issuecomment-532847188 - https://github.com/mozilla-mobile/fenix/pull/15713#issuecomment-703972068 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - interaction notification_emails: - - fenix-core@mozilla.com + - android-probes@mozilla.com expires: "2021-08-01" panel_settings: type: event @@ -2991,10 +3262,11 @@ tracking_protection: data_reviews: - https://github.com/mozilla-mobile/fenix/pull/5414#issuecomment-532847188 - https://github.com/mozilla-mobile/fenix/pull/15713#issuecomment-703972068 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - interaction notification_emails: - - fenix-core@mozilla.com + - android-probes@mozilla.com expires: "2021-08-01" etp_shield: type: event @@ -3005,10 +3277,11 @@ tracking_protection: data_reviews: - https://github.com/mozilla-mobile/fenix/pull/5414#issuecomment-532847188 - https://github.com/mozilla-mobile/fenix/pull/15713#issuecomment-703972068 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - interaction notification_emails: - - fenix-core@mozilla.com + - android-probes@mozilla.com expires: "2021-08-01" etp_tracker_list: type: event @@ -3020,10 +3293,11 @@ tracking_protection: data_reviews: - https://github.com/mozilla-mobile/fenix/pull/5414#issuecomment-532847188 - https://github.com/mozilla-mobile/fenix/pull/15713#issuecomment-703972068 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - interaction notification_emails: - - fenix-core@mozilla.com + - android-probes@mozilla.com expires: "2021-08-01" etp_settings: type: event @@ -3034,10 +3308,11 @@ tracking_protection: data_reviews: - https://github.com/mozilla-mobile/fenix/pull/5414#issuecomment-532847188 - https://github.com/mozilla-mobile/fenix/pull/15713#issuecomment-703972068 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - interaction notification_emails: - - fenix-core@mozilla.com + - android-probes@mozilla.com expires: "2021-08-01" etp_setting_changed: type: event @@ -3054,10 +3329,11 @@ tracking_protection: - https://github.com/mozilla-mobile/fenix/pull/5414#issuecomment-532847188 - https://github.com/mozilla-mobile/fenix/pull/11383 - https://github.com/mozilla-mobile/fenix/pull/15713#issuecomment-703972068 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - interaction notification_emails: - - fenix-core@mozilla.com + - android-probes@mozilla.com expires: "2021-08-01" private_browsing_shortcut: @@ -3070,10 +3346,11 @@ private_browsing_shortcut: data_reviews: - https://github.com/mozilla-mobile/fenix/pull/5194 - https://github.com/mozilla-mobile/fenix/pull/15713#issuecomment-703972068 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - interaction notification_emails: - - fenix-core@mozilla.com + - android-probes@mozilla.com expires: "2021-08-01" cfr_add_shortcut: type: event @@ -3085,10 +3362,11 @@ private_browsing_shortcut: data_reviews: - https://github.com/mozilla-mobile/fenix/pull/5194 - https://github.com/mozilla-mobile/fenix/pull/15713#issuecomment-703972068 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - interaction notification_emails: - - fenix-core@mozilla.com + - android-probes@mozilla.com expires: "2021-08-01" cfr_cancel: type: event @@ -3100,10 +3378,11 @@ private_browsing_shortcut: data_reviews: - https://github.com/mozilla-mobile/fenix/pull/5194 - https://github.com/mozilla-mobile/fenix/pull/15713#issuecomment-703972068 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - interaction notification_emails: - - fenix-core@mozilla.com + - android-probes@mozilla.com expires: "2021-08-01" pinned_shortcut_priv: type: event @@ -3115,10 +3394,11 @@ private_browsing_shortcut: data_reviews: - https://github.com/mozilla-mobile/fenix/pull/5194 - https://github.com/mozilla-mobile/fenix/pull/15713#issuecomment-703972068 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - interaction notification_emails: - - fenix-core@mozilla.com + - android-probes@mozilla.com expires: "2021-08-01" static_shortcut_tab: type: event @@ -3130,10 +3410,11 @@ private_browsing_shortcut: data_reviews: - https://github.com/mozilla-mobile/fenix/pull/5194 - https://github.com/mozilla-mobile/fenix/pull/15713#issuecomment-703972068 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - interaction notification_emails: - - fenix-core@mozilla.com + - android-probes@mozilla.com expires: "2021-08-01" static_shortcut_priv: type: event @@ -3145,10 +3426,11 @@ private_browsing_shortcut: data_reviews: - https://github.com/mozilla-mobile/fenix/pull/5194 - https://github.com/mozilla-mobile/fenix/pull/15713#issuecomment-703972068 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - interaction notification_emails: - - fenix-core@mozilla.com + - android-probes@mozilla.com expires: "2021-08-01" tab: @@ -3161,10 +3443,11 @@ tab: data_reviews: - https://github.com/mozilla-mobile/fenix/pull/5266 - https://github.com/mozilla-mobile/fenix/pull/15713#issuecomment-703972068 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - interaction notification_emails: - - fenix-core@mozilla.com + - android-probes@mozilla.com expires: "2021-08-01" no_lint: - COMMON_PREFIX @@ -3177,10 +3460,11 @@ tab: data_reviews: - https://github.com/mozilla-mobile/fenix/pull/5266 - https://github.com/mozilla-mobile/fenix/pull/15713#issuecomment-703972068 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - interaction notification_emails: - - fenix-core@mozilla.com + - android-probes@mozilla.com expires: "2021-08-01" media_notification: @@ -3193,10 +3477,11 @@ media_notification: data_reviews: - https://github.com/mozilla-mobile/fenix/pull/5520 - https://github.com/mozilla-mobile/fenix/pull/15713#issuecomment-703972068 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - interaction notification_emails: - - fenix-core@mozilla.com + - android-probes@mozilla.com expires: "2021-08-01" pause: type: event @@ -3207,10 +3492,11 @@ media_notification: data_reviews: - https://github.com/mozilla-mobile/fenix/pull/5520 - https://github.com/mozilla-mobile/fenix/pull/15713#issuecomment-703972068 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - interaction notification_emails: - - fenix-core@mozilla.com + - android-probes@mozilla.com expires: "2021-08-01" media_state: @@ -3223,10 +3509,11 @@ media_state: data_reviews: - https://github.com/mozilla-mobile/fenix/pull/6463 - https://github.com/mozilla-mobile/fenix/pull/15713#issuecomment-703972068 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - interaction notification_emails: - - fenix-core@mozilla.com + - android-probes@mozilla.com expires: "2021-08-01" pause: type: event @@ -3237,10 +3524,11 @@ media_state: data_reviews: - https://github.com/mozilla-mobile/fenix/pull/6463 - https://github.com/mozilla-mobile/fenix/pull/15713#issuecomment-703972068 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - interaction notification_emails: - - fenix-core@mozilla.com + - android-probes@mozilla.com expires: "2021-08-01" stop: type: event @@ -3251,10 +3539,11 @@ media_state: data_reviews: - https://github.com/mozilla-mobile/fenix/pull/6463 - https://github.com/mozilla-mobile/fenix/pull/15713#issuecomment-703972068 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - interaction notification_emails: - - fenix-core@mozilla.com + - android-probes@mozilla.com expires: "2021-08-01" fullscreen: type: event @@ -3264,10 +3553,11 @@ media_state: - https://github.com/mozilla-mobile/fenix/issues/15368 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/16833 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - interaction notification_emails: - - fenix-core@mozilla.com + - android-probes@mozilla.com expires: "2021-08-01" picture_in_picture: type: event @@ -3277,10 +3567,11 @@ media_state: - https://github.com/mozilla-mobile/fenix/issues/15368 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/16833 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - interaction notification_emails: - - fenix-core@mozilla.com + - android-probes@mozilla.com expires: "2021-08-01" logins: @@ -3293,10 +3584,11 @@ logins: data_reviews: - https://github.com/mozilla-mobile/fenix/pull/6352 - https://github.com/mozilla-mobile/fenix/pull/15713#issuecomment-703972068 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - interaction notification_emails: - - fenix-core@mozilla.com + - android-probes@mozilla.com expires: "2021-08-01" open_individual_login: type: event @@ -3307,10 +3599,11 @@ logins: data_reviews: - https://github.com/mozilla-mobile/fenix/pull/6352 - https://github.com/mozilla-mobile/fenix/pull/15713#issuecomment-703972068 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - interaction notification_emails: - - fenix-core@mozilla.com + - android-probes@mozilla.com expires: "2021-08-01" copy_login: type: event @@ -3321,10 +3614,11 @@ logins: data_reviews: - https://github.com/mozilla-mobile/fenix/pull/6352 - https://github.com/mozilla-mobile/fenix/pull/15713#issuecomment-703972068 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - interaction notification_emails: - - fenix-core@mozilla.com + - android-probes@mozilla.com expires: "2021-08-01" view_password_login: type: event @@ -3335,10 +3629,11 @@ logins: data_reviews: - https://github.com/mozilla-mobile/fenix/pull/6352 - https://github.com/mozilla-mobile/fenix/pull/15713#issuecomment-703972068 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - interaction notification_emails: - - fenix-core@mozilla.com + - android-probes@mozilla.com expires: "2021-08-01" save_logins_setting_changed: type: event @@ -3354,10 +3649,11 @@ logins: data_reviews: - https://github.com/mozilla-mobile/fenix/pull/7767 - https://github.com/mozilla-mobile/fenix/pull/15713#issuecomment-703972068 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - interaction notification_emails: - - fenix-core@mozilla.com + - android-probes@mozilla.com expires: "2021-08-01" open_login_editor: type: event @@ -3368,10 +3664,11 @@ logins: data_reviews: - https://github.com/mozilla-mobile/fenix/issues/11208 - https://github.com/mozilla-mobile/fenix/pull/15713#issuecomment-703972068 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - interaction notification_emails: - - fenix-core@mozilla.com + - android-probes@mozilla.com expires: "2021-08-01" delete_saved_login: type: event @@ -3382,10 +3679,11 @@ logins: data_reviews: - https://github.com/mozilla-mobile/fenix/issues/11208 - https://github.com/mozilla-mobile/fenix/pull/15713#issuecomment-703972068 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - interaction notification_emails: - - fenix-core@mozilla.com + - android-probes@mozilla.com expires: "2021-08-01" save_edited_login: type: event @@ -3396,10 +3694,11 @@ logins: data_reviews: - https://github.com/mozilla-mobile/fenix/issues/11208 - https://github.com/mozilla-mobile/fenix/pull/15713#issuecomment-703972068 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - interaction notification_emails: - - fenix-core@mozilla.com + - android-probes@mozilla.com expires: "2021-08-01" download_notification: @@ -3413,10 +3712,11 @@ download_notification: - https://github.com/mozilla-mobile/fenix/pull/6554 - https://github.com/mozilla-mobile/fenix/pull/13958#issuecomment-676857877 - https://github.com/mozilla-mobile/fenix/pull/18143 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - interaction notification_emails: - - fenix-core@mozilla.com + - android-probes@mozilla.com expires: "2021-07-01" pause: type: event @@ -3428,10 +3728,11 @@ download_notification: - https://github.com/mozilla-mobile/fenix/pull/6554 - https://github.com/mozilla-mobile/fenix/pull/13958#issuecomment-676857877 - https://github.com/mozilla-mobile/fenix/pull/18143 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - interaction notification_emails: - - fenix-core@mozilla.com + - android-probes@mozilla.com expires: "2021-07-01" cancel: type: event @@ -3443,10 +3744,11 @@ download_notification: - https://github.com/mozilla-mobile/fenix/pull/6554 - https://github.com/mozilla-mobile/fenix/pull/13958#issuecomment-676857877 - https://github.com/mozilla-mobile/fenix/pull/18143 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - interaction notification_emails: - - fenix-core@mozilla.com + - android-probes@mozilla.com expires: "2021-07-01" try_again: type: event @@ -3459,10 +3761,11 @@ download_notification: - https://github.com/mozilla-mobile/fenix/pull/6554 - https://github.com/mozilla-mobile/fenix/pull/13958#issuecomment-676857877 - https://github.com/mozilla-mobile/fenix/pull/18143 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - interaction notification_emails: - - fenix-core@mozilla.com + - android-probes@mozilla.com expires: "2021-07-01" open: type: event @@ -3474,10 +3777,11 @@ download_notification: - https://github.com/mozilla-mobile/fenix/pull/6554 - https://github.com/mozilla-mobile/fenix/pull/13958#issuecomment-676857877 - https://github.com/mozilla-mobile/fenix/pull/18143 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - interaction notification_emails: - - fenix-core@mozilla.com + - android-probes@mozilla.com expires: "2021-07-01" in_app_open: type: event @@ -3489,10 +3793,11 @@ download_notification: - https://github.com/mozilla-mobile/fenix/pull/6554 - https://github.com/mozilla-mobile/fenix/pull/13958#issuecomment-676857877 - https://github.com/mozilla-mobile/fenix/pull/18143 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - interaction notification_emails: - - fenix-core@mozilla.com + - android-probes@mozilla.com expires: "2021-07-01" in_app_try_again: type: event @@ -3505,10 +3810,11 @@ download_notification: - https://github.com/mozilla-mobile/fenix/pull/6554 - https://github.com/mozilla-mobile/fenix/pull/13958#issuecomment-676857877 - https://github.com/mozilla-mobile/fenix/pull/18143 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - interaction notification_emails: - - fenix-core@mozilla.com + - android-probes@mozilla.com expires: "2021-07-01" downloads_misc: @@ -3521,8 +3827,9 @@ downloads_misc: data_reviews: - https://github.com/mozilla-mobile/fenix/pull/16730 - https://github.com/mozilla-mobile/fenix/pull/18143 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 notification_emails: - - fenix-core@mozilla.com + - android-probes@mozilla.com expires: "2021-07-01" downloads_management: @@ -3536,8 +3843,9 @@ downloads_management: data_reviews: - https://github.com/mozilla-mobile/fenix/pull/16728 - https://github.com/mozilla-mobile/fenix/pull/18143 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 notification_emails: - - fenix-core@mozilla.com + - android-probes@mozilla.com expires: "2021-07-01" item_opened: @@ -3547,12 +3855,14 @@ downloads_management: "Downloads" folder. bugs: - https://github.com/mozilla-mobile/fenix/issues/15367 + - https://github.com/mozilla-mobile/fenix/issues/19923 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/16728 - https://github.com/mozilla-mobile/fenix/pull/18143 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 notification_emails: - - fenix-core@mozilla.com - expires: "2021-07-01" + - android-probes@mozilla.com + expires: "2021-12-01" item_deleted: type: event @@ -3560,12 +3870,14 @@ downloads_management: A counter for how often a user deletes one / more downloads at a time. bugs: - https://github.com/mozilla-mobile/fenix/issues/15367 + - https://github.com/mozilla-mobile/fenix/issues/19923 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/16728 - https://github.com/mozilla-mobile/fenix/pull/18143 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 notification_emails: - - fenix-core@mozilla.com - expires: "2021-07-01" + - android-probes@mozilla.com + expires: "2021-12-01" user_specified_search_engines: custom_engine_added: @@ -3577,10 +3889,11 @@ user_specified_search_engines: data_reviews: - https://github.com/mozilla-mobile/fenix/pull/6918 - https://github.com/mozilla-mobile/fenix/pull/15713#issuecomment-703972068 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - interaction notification_emails: - - fenix-core@mozilla.com + - android-probes@mozilla.com expires: "2021-08-01" no_lint: - COMMON_PREFIX @@ -3594,10 +3907,11 @@ user_specified_search_engines: data_reviews: - https://github.com/mozilla-mobile/fenix/pull/6918 - https://github.com/mozilla-mobile/fenix/pull/15713#issuecomment-703972068 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - interaction notification_emails: - - fenix-core@mozilla.com + - android-probes@mozilla.com expires: "2021-08-01" search_suggestions: @@ -3610,11 +3924,12 @@ search_suggestions: data_reviews: - https://github.com/mozilla-mobile/fenix/pull/6746 - https://github.com/mozilla-mobile/fenix/pull/15713#issuecomment-703972068 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - technical - interaction notification_emails: - - fenix-core@mozilla.com + - android-probes@mozilla.com expires: "2021-08-01" voice_search: @@ -3627,10 +3942,11 @@ voice_search: data_reviews: - https://github.com/mozilla-mobile/fenix/pull/10785 - https://github.com/mozilla-mobile/fenix/pull/15713#issuecomment-703972068 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - interaction notification_emails: - - fenix-core@mozilla.com + - android-probes@mozilla.com expires: "2021-08-01" top_sites: @@ -3643,10 +3959,11 @@ top_sites: data_reviews: - https://github.com/mozilla-mobile/fenix/pull/10752 - https://github.com/mozilla-mobile/fenix/pull/15713#issuecomment-703972068 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - interaction notification_emails: - - fenix-core@mozilla.com + - android-probes@mozilla.com expires: "2021-08-01" open_google_search_attribution: type: event @@ -3656,10 +3973,11 @@ top_sites: - https://github.com/mozilla-mobile/fenix/issues/17418 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/17637 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - interaction notification_emails: - - fenix-core@mozilla.com + - android-probes@mozilla.com expires: "2021-08-01" open_frecency: type: event @@ -3670,10 +3988,11 @@ top_sites: data_reviews: - https://github.com/mozilla-mobile/fenix/pull/15136 - https://github.com/mozilla-mobile/fenix/pull/15713#issuecomment-703972068 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - interaction notification_emails: - - fenix-core@mozilla.com + - android-probes@mozilla.com expires: "2021-08-01" open_pinned: type: event @@ -3684,10 +4003,11 @@ top_sites: data_reviews: - https://github.com/mozilla-mobile/fenix/pull/15136 - https://github.com/mozilla-mobile/fenix/pull/15713#issuecomment-703972068 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - interaction notification_emails: - - fenix-core@mozilla.com + - android-probes@mozilla.com expires: "2021-08-01" swipe_carousel: type: event @@ -3702,10 +4022,11 @@ top_sites: data_reviews: - https://github.com/mozilla-mobile/fenix/pull/15136 - https://github.com/mozilla-mobile/fenix/pull/15713#issuecomment-703972068 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - interaction notification_emails: - - fenix-core@mozilla.com + - android-probes@mozilla.com expires: "2021-08-01" long_press: type: event @@ -3720,10 +4041,11 @@ top_sites: data_reviews: - https://github.com/mozilla-mobile/fenix/pull/15136 - https://github.com/mozilla-mobile/fenix/pull/15713#issuecomment-703972068 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - interaction notification_emails: - - fenix-core@mozilla.com + - android-probes@mozilla.com expires: "2021-08-01" open_in_new_tab: type: event @@ -3734,10 +4056,11 @@ top_sites: data_reviews: - https://github.com/mozilla-mobile/fenix/pull/7523 - https://github.com/mozilla-mobile/fenix/pull/15713#issuecomment-703972068 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - interaction notification_emails: - - fenix-core@mozilla.com + - android-probes@mozilla.com expires: "2021-08-01" open_in_private_tab: type: event @@ -3748,10 +4071,11 @@ top_sites: data_reviews: - https://github.com/mozilla-mobile/fenix/pull/7523 - https://github.com/mozilla-mobile/fenix/pull/15713#issuecomment-703972068 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - interaction notification_emails: - - fenix-core@mozilla.com + - android-probes@mozilla.com expires: "2021-08-01" remove: type: event @@ -3762,10 +4086,11 @@ top_sites: data_reviews: - https://github.com/mozilla-mobile/fenix/pull/7523 - https://github.com/mozilla-mobile/fenix/pull/15713#issuecomment-703972068 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - interaction notification_emails: - - fenix-core@mozilla.com + - android-probes@mozilla.com expires: "2021-08-01" about_page: @@ -3779,10 +4104,11 @@ about_page: - https://github.com/mozilla-mobile/fenix/pull/8047 - https://github.com/mozilla-mobile/fenix/pull/13958#issuecomment-676857877 - https://github.com/mozilla-mobile/fenix/pull/18143 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - interaction notification_emails: - - fenix-core@mozilla.com + - android-probes@mozilla.com expires: "2021-07-01" privacy_notice_tapped: type: event @@ -3794,10 +4120,11 @@ about_page: - https://github.com/mozilla-mobile/fenix/pull/8047 - https://github.com/mozilla-mobile/fenix/pull/13958#issuecomment-676857877 - https://github.com/mozilla-mobile/fenix/pull/18143 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - interaction notification_emails: - - fenix-core@mozilla.com + - android-probes@mozilla.com expires: "2021-07-01" app_theme: @@ -3812,15 +4139,17 @@ app_theme: 'SETTINGS' or 'ONBOARDING' bugs: - https://github.com/mozilla-mobile/fenix/issues/7289 + - https://github.com/mozilla-mobile/fenix/issues/19923 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/7968 - https://github.com/mozilla-mobile/fenix/pull/13958#issuecomment-676857877 - https://github.com/mozilla-mobile/fenix/pull/18143 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - interaction notification_emails: - - fenix-core@mozilla.com - expires: "2021-07-01" + - android-probes@mozilla.com + expires: "2021-12-01" pocket: pocket_top_site_clicked: @@ -3832,10 +4161,11 @@ pocket: data_reviews: - https://github.com/mozilla-mobile/fenix/pull/8098 - https://github.com/mozilla-mobile/fenix/pull/15713#issuecomment-703972068 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - interaction notification_emails: - - fenix-core@mozilla.com + - android-probes@mozilla.com expires: "2021-08-01" no_lint: - COMMON_PREFIX @@ -3849,10 +4179,11 @@ pocket: data_reviews: - https://github.com/mozilla-mobile/fenix/pull/8098 - https://github.com/mozilla-mobile/fenix/pull/15713#issuecomment-703972068 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - interaction notification_emails: - - fenix-core@mozilla.com + - android-probes@mozilla.com expires: "2021-08-01" first_session: @@ -3867,11 +4198,12 @@ first_session: data_reviews: - https://github.com/mozilla-mobile/fenix/pull/8074#issuecomment-586512202 - https://github.com/mozilla-mobile/fenix/pull/15713#issuecomment-703972068 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - technical - interaction notification_emails: - - fenix-core@mozilla.com + - android-probes@mozilla.com expires: "2021-08-01" network: type: string @@ -3884,11 +4216,12 @@ first_session: data_reviews: - https://github.com/mozilla-mobile/fenix/pull/8074#issuecomment-586512202 - https://github.com/mozilla-mobile/fenix/pull/15713#issuecomment-703972068 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - technical - interaction notification_emails: - - fenix-core@mozilla.com + - android-probes@mozilla.com expires: "2021-08-01" adgroup: type: string @@ -3901,11 +4234,12 @@ first_session: data_reviews: - https://github.com/mozilla-mobile/fenix/pull/8074#issuecomment-586480836 - https://github.com/mozilla-mobile/fenix/pull/15713#issuecomment-703972068 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - technical - interaction notification_emails: - - fenix-core@mozilla.com + - android-probes@mozilla.com expires: "2021-08-01" creative: send_in_pings: @@ -3918,11 +4252,12 @@ first_session: data_reviews: - https://github.com/mozilla-mobile/fenix/pull/8074#issuecomment-586512202 - https://github.com/mozilla-mobile/fenix/pull/15713#issuecomment-703972068 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - technical - interaction notification_emails: - - fenix-core@mozilla.com + - android-probes@mozilla.com expires: "2021-08-01" timestamp: send_in_pings: @@ -3937,11 +4272,12 @@ first_session: data_reviews: - https://github.com/mozilla-mobile/fenix/pull/8074#issuecomment-586512202 - https://github.com/mozilla-mobile/fenix/pull/15713#issuecomment-703972068 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - technical - interaction notification_emails: - - fenix-core@mozilla.com + - android-probes@mozilla.com expires: "2021-08-01" browser.search: @@ -3949,7 +4285,7 @@ browser.search: type: labeled_counter description: | Records counts of SERP pages with adverts displayed. - The key format is ‘’. + The key format is ``. send_in_pings: - metrics bugs: @@ -3957,16 +4293,17 @@ browser.search: data_reviews: - https://github.com/mozilla-mobile/fenix/pull/10112 - https://github.com/mozilla-mobile/fenix/pull/15713#issuecomment-703972068 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - interaction notification_emails: - - fenix-core@mozilla.com + - android-probes@mozilla.com expires: "2021-08-01" ad_clicks: type: labeled_counter description: | Records clicks of adverts on SERP pages. - The key format is ‘’. + The key format is ``. send_in_pings: - metrics bugs: @@ -3974,10 +4311,11 @@ browser.search: data_reviews: - https://github.com/mozilla-mobile/fenix/pull/10112 - https://github.com/mozilla-mobile/fenix/pull/15713#issuecomment-703972068 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - interaction notification_emails: - - fenix-core@mozilla.com + - android-probes@mozilla.com expires: "2021-08-01" in_content: type: labeled_counter @@ -3990,10 +4328,11 @@ browser.search: data_reviews: - https://github.com/mozilla-mobile/fenix/pull/10167 - https://github.com/mozilla-mobile/fenix/pull/15713#issuecomment-703972068 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - interaction notification_emails: - - fenix-core@mozilla.com + - android-probes@mozilla.com expires: "2021-08-01" addons: @@ -4003,15 +4342,17 @@ addons: A user accessed "Add-ons" from the Settings bugs: - https://github.com/mozilla-mobile/fenix/issues/6174 + - https://github.com/mozilla-mobile/fenix/issues/19923 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/8318 - https://github.com/mozilla-mobile/fenix/pull/13958#issuecomment-676857877 - https://github.com/mozilla-mobile/fenix/pull/18143 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - interaction notification_emails: - - fenix-core@mozilla.com - expires: "2021-07-01" + - android-probes@mozilla.com + expires: "2021-12-01" open_addon_in_toolbar_menu: type: event description: | @@ -4022,15 +4363,17 @@ addons: The id of the add-on that was interacted with in the toolbar menu bugs: - https://github.com/mozilla-mobile/fenix/issues/6174 + - https://github.com/mozilla-mobile/fenix/issues/19923 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/8318 - https://github.com/mozilla-mobile/fenix/pull/13958#issuecomment-676857877 - https://github.com/mozilla-mobile/fenix/pull/18143 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - interaction notification_emails: - - fenix-core@mozilla.com - expires: "2021-07-01" + - android-probes@mozilla.com + expires: "2021-12-01" open_addon_setting: type: event description: | @@ -4043,10 +4386,11 @@ addons: - https://github.com/mozilla-mobile/fenix/issues/17644 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/18504 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - interaction notification_emails: - - fenix-core@mozilla.com + - android-probes@mozilla.com expires: "2022-08-01" has_installed_addons: type: boolean @@ -4056,15 +4400,17 @@ addons: - metrics bugs: - https://github.com/mozilla-mobile/fenix/issues/6174 + - https://github.com/mozilla-mobile/fenix/issues/19923 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/8318 - https://github.com/mozilla-mobile/fenix/pull/13958#issuecomment-676857877 - https://github.com/mozilla-mobile/fenix/pull/18143 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - interaction notification_emails: - - fenix-core@mozilla.com - expires: "2021-07-01" + - android-probes@mozilla.com + expires: "2021-12-01" has_enabled_addons: type: boolean description: | @@ -4073,15 +4419,17 @@ addons: - metrics bugs: - https://github.com/mozilla-mobile/fenix/issues/6174 + - https://github.com/mozilla-mobile/fenix/issues/19923 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/8318 - https://github.com/mozilla-mobile/fenix/pull/13958#issuecomment-676857877 - https://github.com/mozilla-mobile/fenix/pull/18143 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - interaction notification_emails: - - fenix-core@mozilla.com - expires: "2021-07-01" + - android-probes@mozilla.com + expires: "2021-12-01" installed_addons: type: string_list description: | @@ -4090,15 +4438,17 @@ addons: - metrics bugs: - https://github.com/mozilla-mobile/fenix/issues/8920 + - https://github.com/mozilla-mobile/fenix/issues/19923 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/11080 - https://github.com/mozilla-mobile/fenix/pull/13958#issuecomment-676857877 - https://github.com/mozilla-mobile/fenix/pull/18143 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - interaction notification_emails: - - fenix-core@mozilla.com - expires: "2021-07-01" + - android-probes@mozilla.com + expires: "2021-12-01" enabled_addons: type: string_list description: | @@ -4107,15 +4457,17 @@ addons: - metrics bugs: - https://github.com/mozilla-mobile/fenix/issues/8920 + - https://github.com/mozilla-mobile/fenix/issues/19923 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/11080 - https://github.com/mozilla-mobile/fenix/pull/13958#issuecomment-676857877 - https://github.com/mozilla-mobile/fenix/pull/18143 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - interaction notification_emails: - - fenix-core@mozilla.com - expires: "2021-07-01" + - android-probes@mozilla.com + expires: "2021-12-01" startup.timeline: framework_primary: @@ -4580,11 +4932,12 @@ perf.awesomebar: - https://github.com/mozilla-mobile/android-components/issues/4992 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/10276#pullrequestreview-411101979 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - technical - interaction notification_emails: - - fenix-core@mozilla.com + - android-probes@mozilla.com - gkruglov@mozilla.com expires: "2021-11-15" bookmark_suggestions: @@ -4598,11 +4951,12 @@ perf.awesomebar: - https://github.com/mozilla-mobile/android-components/issues/4992 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/10276#pullrequestreview-411101979 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - technical - interaction notification_emails: - - fenix-core@mozilla.com + - android-probes@mozilla.com - gkruglov@mozilla.com expires: "2021-11-15" search_engine_suggestions: @@ -4616,11 +4970,12 @@ perf.awesomebar: - https://github.com/mozilla-mobile/android-components/issues/4992 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/10276#pullrequestreview-411101979 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - technical - interaction notification_emails: - - fenix-core@mozilla.com + - android-probes@mozilla.com - gkruglov@mozilla.com expires: "2021-11-15" session_suggestions: @@ -4634,11 +4989,12 @@ perf.awesomebar: - https://github.com/mozilla-mobile/android-components/issues/4992 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/10276#pullrequestreview-411101979 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - technical - interaction notification_emails: - - fenix-core@mozilla.com + - android-probes@mozilla.com - gkruglov@mozilla.com expires: "2021-11-15" synced_tabs_suggestions: @@ -4652,11 +5008,12 @@ perf.awesomebar: - https://github.com/mozilla-mobile/android-components/issues/4992 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/10276#pullrequestreview-411101979 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - technical - interaction notification_emails: - - fenix-core@mozilla.com + - android-probes@mozilla.com - gkruglov@mozilla.com expires: "2021-11-15" clipboard_suggestions: @@ -4670,11 +5027,12 @@ perf.awesomebar: - https://github.com/mozilla-mobile/android-components/issues/4992 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/10276#pullrequestreview-411101979 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - technical - interaction notification_emails: - - fenix-core@mozilla.com + - android-probes@mozilla.com - gkruglov@mozilla.com expires: "2021-11-15" shortcuts_suggestions: @@ -4688,11 +5046,12 @@ perf.awesomebar: - https://github.com/mozilla-mobile/android-components/issues/4992 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/10276#pullrequestreview-411101979 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - technical - interaction notification_emails: - - fenix-core@mozilla.com + - android-probes@mozilla.com - gkruglov@mozilla.com expires: "2021-11-15" @@ -4704,10 +5063,11 @@ autoplay: - https://github.com/mozilla-mobile/fenix/issues/11579 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/13041#issuecomment-665777411 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - interaction notification_emails: - - fenix-core@mozilla.com + - android-probes@mozilla.com expires: "2021-08-01" setting_changed: type: event @@ -4723,10 +5083,11 @@ autoplay: - https://github.com/mozilla-mobile/fenix/issues/11579 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/13041#issuecomment-665777411 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - interaction notification_emails: - - fenix-core@mozilla.com + - android-probes@mozilla.com expires: "2021-08-01" storage.stats: @@ -4744,11 +5105,12 @@ storage.stats: data_reviews: - https://github.com/mozilla-mobile/fenix/pull/12876#issuecomment-666770732 - https://github.com/mozilla-mobile/fenix/pull/17704#issue-564299127 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - technical - interaction notification_emails: - - fenix-core@mozilla.com + - android-probes@mozilla.com - perf-android-fe@mozilla.com - mcomella@mozilla.com expires: "2021-08-01" @@ -4769,11 +5131,12 @@ storage.stats: data_reviews: - https://github.com/mozilla-mobile/fenix/pull/12876#issuecomment-666770732 - https://github.com/mozilla-mobile/fenix/pull/17704#issue-564299127 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - technical - interaction notification_emails: - - fenix-core@mozilla.com + - android-probes@mozilla.com - perf-android-fe@mozilla.com - mcomella@mozilla.com expires: "2021-08-01" @@ -4791,11 +5154,12 @@ storage.stats: data_reviews: - https://github.com/mozilla-mobile/fenix/pull/12876#issuecomment-666770732 - https://github.com/mozilla-mobile/fenix/pull/17704#issue-564299127 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - technical - interaction notification_emails: - - fenix-core@mozilla.com + - android-probes@mozilla.com - perf-android-fe@mozilla.com - mcomella@mozilla.com expires: "2021-08-01" @@ -4815,11 +5179,12 @@ storage.stats: data_reviews: - https://github.com/mozilla-mobile/fenix/pull/12876#issuecomment-666770732 - https://github.com/mozilla-mobile/fenix/pull/17704#issue-564299127 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - technical - interaction notification_emails: - - fenix-core@mozilla.com + - android-probes@mozilla.com - perf-android-fe@mozilla.com - mcomella@mozilla.com expires: "2021-08-01" @@ -4834,10 +5199,11 @@ progressive_web_app: data_reviews: - https://github.com/mozilla-mobile/fenix/pull/11859 - https://github.com/mozilla-mobile/fenix/pull/18071 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - interaction notification_emails: - - fenix-core@mozilla.com + - android-probes@mozilla.com - erichards@mozilla.com expires: "2021-09-01" install_tap: @@ -4849,10 +5215,11 @@ progressive_web_app: data_reviews: - https://github.com/mozilla-mobile/fenix/pull/11859 - https://github.com/mozilla-mobile/fenix/pull/18071 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - interaction notification_emails: - - fenix-core@mozilla.com + - android-probes@mozilla.com - erichards@mozilla.com expires: "2021-09-01" foreground: @@ -4868,10 +5235,11 @@ progressive_web_app: data_reviews: - https://github.com/mozilla-mobile/fenix/pull/11859 - https://github.com/mozilla-mobile/fenix/pull/18071 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - interaction notification_emails: - - fenix-core@mozilla.com + - android-probes@mozilla.com - erichards@mozilla.com expires: "2021-09-01" background: @@ -4887,10 +5255,11 @@ progressive_web_app: data_reviews: - https://github.com/mozilla-mobile/fenix/pull/11859 - https://github.com/mozilla-mobile/fenix/pull/18071 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - interaction notification_emails: - - fenix-core@mozilla.com + - android-probes@mozilla.com - erichards@mozilla.com expires: "2021-09-01" @@ -4904,10 +5273,11 @@ master_password: data_reviews: - https://github.com/mozilla-mobile/fenix/pull/14468#issuecomment-684114534 - https://github.com/mozilla-mobile/fenix/pull/18071 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - interaction notification_emails: - - fenix-core@mozilla.com + - android-probes@mozilla.com expires: "2021-09-01" migration: type: event @@ -4918,10 +5288,11 @@ master_password: data_reviews: - https://github.com/mozilla-mobile/fenix/pull/14468#issuecomment-684114534 - https://github.com/mozilla-mobile/fenix/pull/18071 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - interaction notification_emails: - - fenix-core@mozilla.com + - android-probes@mozilla.com expires: "2021-09-01" tabs: @@ -4933,10 +5304,11 @@ tabs: - https://github.com/mozilla-mobile/fenix/issues/15347#issue-707408975 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/15811#issuecomment-706402952 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - interaction notification_emails: - - fenix-core@mozilla.com + - android-probes@mozilla.com expires: "2021-08-01" banner_open_in_app: @@ -4948,10 +5320,11 @@ banner_open_in_app: - https://github.com/mozilla-mobile/fenix/issues/16828 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/17049 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - interaction notification_emails: - - fenix-core@mozilla.com + - android-probes@mozilla.com expires: "2021-08-01" dismissed: type: event @@ -4961,10 +5334,11 @@ banner_open_in_app: - https://github.com/mozilla-mobile/fenix/issues/16828 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/17049 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - interaction notification_emails: - - fenix-core@mozilla.com + - android-probes@mozilla.com expires: "2021-08-01" go_to_settings: type: event @@ -4974,10 +5348,11 @@ banner_open_in_app: - https://github.com/mozilla-mobile/fenix/issues/16828 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/17049 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - interaction notification_emails: - - fenix-core@mozilla.com + - android-probes@mozilla.com expires: "2021-08-01" contextual_menu: @@ -4987,52 +5362,60 @@ contextual_menu: The context menu's 'copy' option was used. bugs: - https://github.com/mozilla-mobile/fenix/issues/11580 + - https://github.com/mozilla-mobile/fenix/issues/19923 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/16968 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - interaction notification_emails: - - fenix-core@mozilla.com - expires: "2021-06-01" + - android-probes@mozilla.com + expires: "2021-12-01" search_tapped: type: event description: | The context menu's 'search' option was used. bugs: - https://github.com/mozilla-mobile/fenix/issues/11580 + - https://github.com/mozilla-mobile/fenix/issues/19923 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/16968 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - interaction notification_emails: - - fenix-core@mozilla.com - expires: "2021-06-01" + - android-probes@mozilla.com + expires: "2021-12-01" select_all_tapped: type: event description: | The context menu's 'select all' option was used. bugs: - https://github.com/mozilla-mobile/fenix/issues/11580 + - https://github.com/mozilla-mobile/fenix/issues/19923 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/16968 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - interaction notification_emails: - - fenix-core@mozilla.com - expires: "2021-06-01" + - android-probes@mozilla.com + expires: "2021-12-01" share_tapped: type: event description: | The context menu's 'share' option was used. bugs: - https://github.com/mozilla-mobile/fenix/issues/11580 + - https://github.com/mozilla-mobile/fenix/issues/19923 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/16968 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - interaction notification_emails: - - fenix-core@mozilla.com - expires: "2021-06-01" + - android-probes@mozilla.com + expires: "2021-12-01" engine_tab: kills: @@ -5047,10 +5430,11 @@ engine_tab: - https://github.com/mozilla-mobile/android-components/issues/9366 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/17864 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - technical notification_emails: - - fenix-core@mozilla.com + - android-probes@mozilla.com - skaspari@mozilla.com expires: "2021-12-31" kill_foreground_age: @@ -5063,10 +5447,11 @@ engine_tab: - https://github.com/mozilla-mobile/android-components/issues/9366 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/17864 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - technical notification_emails: - - fenix-core@mozilla.com + - android-probes@mozilla.com - skaspari@mozilla.com expires: "2021-12-31" kill_background_age: @@ -5079,10 +5464,11 @@ engine_tab: - https://github.com/mozilla-mobile/android-components/issues/9366 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/17864 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - technical notification_emails: - - fenix-core@mozilla.com + - android-probes@mozilla.com - skaspari@mozilla.com expires: "2021-12-31" foreground_metrics: @@ -5094,10 +5480,11 @@ engine_tab: - https://github.com/mozilla-mobile/android-components/issues/9997 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/18747#issuecomment-815731764 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - technical notification_emails: - - fenix-core@mozilla.com + - android-probes@mozilla.com - skaspari@mozilla.com expires: "2021-12-31" extra_keys: @@ -5135,10 +5522,11 @@ synced_tabs: - https://github.com/mozilla-mobile/fenix/issues/18163 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/18172 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - interaction notification_emails: - - fenix-core@mozilla.com + - android-probes@mozilla.com expires: "2021-08-01" awesomebar: @@ -5150,10 +5538,11 @@ awesomebar: - https://github.com/mozilla-mobile/fenix/issues/18068 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/18090 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - interaction notification_emails: - - fenix-core@mozilla.com + - android-probes@mozilla.com expires: "2021-08-01" clipboard_suggestion_clicked: type: event @@ -5163,10 +5552,11 @@ awesomebar: - https://github.com/mozilla-mobile/fenix/issues/18068 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/18090 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - interaction notification_emails: - - fenix-core@mozilla.com + - android-probes@mozilla.com expires: "2021-08-01" history_suggestion_clicked: type: event @@ -5176,10 +5566,11 @@ awesomebar: - https://github.com/mozilla-mobile/fenix/issues/18068 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/18090 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - interaction notification_emails: - - fenix-core@mozilla.com + - android-probes@mozilla.com expires: "2021-08-01" search_action_clicked: type: event @@ -5189,10 +5580,11 @@ awesomebar: - https://github.com/mozilla-mobile/fenix/issues/18068 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/18090 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - interaction notification_emails: - - fenix-core@mozilla.com + - android-probes@mozilla.com expires: "2021-08-01" search_suggestion_clicked: type: event @@ -5202,10 +5594,11 @@ awesomebar: - https://github.com/mozilla-mobile/fenix/issues/18068 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/18090 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - interaction notification_emails: - - fenix-core@mozilla.com + - android-probes@mozilla.com expires: "2021-08-01" opened_tab_suggestion_clicked: type: event @@ -5215,10 +5608,11 @@ awesomebar: - https://github.com/mozilla-mobile/fenix/issues/18068 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/18090 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - interaction notification_emails: - - fenix-core@mozilla.com + - android-probes@mozilla.com expires: "2021-08-01" home_menu: @@ -5229,10 +5623,11 @@ home_menu: - https://github.com/mozilla-mobile/fenix/issues/18856 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/18987 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - interaction notification_emails: - - fenix-core@mozilla.com + - android-probes@mozilla.com expires: "2021-10-01" home_screen: @@ -5243,10 +5638,11 @@ home_screen: - https://github.com/mozilla-mobile/fenix/issues/18856 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/19025 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - interaction notification_emails: - - fenix-core@mozilla.com + - android-probes@mozilla.com expires: "2021-10-01" android_keystore_experiment: @@ -5263,10 +5659,11 @@ android_keystore_experiment: - https://github.com/mozilla-mobile/fenix/issues/17869 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/18333#pullrequestreview-612447395 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - technical notification_emails: - - fenix-core@mozilla.com + - android-probes@mozilla.com expires: "2021-09-01" get_failure: type: event @@ -5281,10 +5678,11 @@ android_keystore_experiment: - https://github.com/mozilla-mobile/fenix/issues/17869 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/18333#pullrequestreview-612447395 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - technical notification_emails: - - fenix-core@mozilla.com + - android-probes@mozilla.com expires: "2021-09-01" get_result: type: event @@ -5299,10 +5697,11 @@ android_keystore_experiment: - https://github.com/mozilla-mobile/fenix/issues/17869 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/18333#pullrequestreview-612447395 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - technical notification_emails: - - fenix-core@mozilla.com + - android-probes@mozilla.com expires: "2021-09-01" write_failure: type: event @@ -5317,10 +5716,11 @@ android_keystore_experiment: - https://github.com/mozilla-mobile/fenix/issues/17869 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/18333#pullrequestreview-612447395 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - technical notification_emails: - - fenix-core@mozilla.com + - android-probes@mozilla.com expires: "2021-09-01" write_success: type: event @@ -5330,10 +5730,11 @@ android_keystore_experiment: - https://github.com/mozilla-mobile/fenix/issues/17869 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/18333#pullrequestreview-612447395 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - technical notification_emails: - - fenix-core@mozilla.com + - android-probes@mozilla.com expires: "2021-09-01" reset: type: event @@ -5344,10 +5745,11 @@ android_keystore_experiment: - https://github.com/mozilla-mobile/fenix/issues/17869 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/18333#pullrequestreview-612447395 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - technical notification_emails: - - fenix-core@mozilla.com + - android-probes@mozilla.com expires: "2021-09-01" set_default_newtab_experiment: @@ -5359,10 +5761,11 @@ set_default_newtab_experiment: - https://github.com/mozilla-mobile/fenix/issues/18853 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/18895 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - interaction notification_emails: - - fenix-core@mozilla.com + - android-probes@mozilla.com expires: "2021-10-01" close_experiment_card_clicked: type: event @@ -5372,10 +5775,27 @@ set_default_newtab_experiment: - https://github.com/mozilla-mobile/fenix/issues/18853 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/18895 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 data_sensitivity: - interaction notification_emails: - - fenix-core@mozilla.com + - android-probes@mozilla.com + expires: "2021-10-01" + +set_default_setting_experiment: + set_default_browser_clicked: + type: event + description: | + Set default browser was clicked from settings screen. + bugs: + - https://github.com/mozilla-mobile/fenix/issues/18852 + data_reviews: + - https://github.com/mozilla-mobile/fenix/pull/19047 + - https://github.com/mozilla-mobile/fenix/pull/19924#issuecomment-861423789 + data_sensitivity: + - interaction + notification_emails: + - android-probes@mozilla.com expires: "2021-10-01" set_default_setting_experiment: diff --git a/app/pings.yaml b/app/pings.yaml index d244af9f0..8839d189f 100644 --- a/app/pings.yaml +++ b/app/pings.yaml @@ -17,7 +17,7 @@ activation: data_reviews: - https://github.com/mozilla-mobile/fenix/pull/1707#issuecomment-486972209 notification_emails: - - fenix-core@mozilla.com + - android-probes@mozilla.com first-session: description: | @@ -29,7 +29,7 @@ first-session: data_reviews: - https://github.com/mozilla-mobile/fenix/pull/8074#issuecomment-586512202 notification_emails: - - fenix-core@mozilla.com + - android-probes@mozilla.com startup-timeline: description: | diff --git a/app/src/androidTest/assets/pages/audioMediaPage.html b/app/src/androidTest/assets/pages/audioMediaPage.html index 1a8720a85..8fd6da11d 100644 --- a/app/src/androidTest/assets/pages/audioMediaPage.html +++ b/app/src/androidTest/assets/pages/audioMediaPage.html @@ -9,18 +9,5 @@ -
-
- \ No newline at end of file diff --git a/app/src/androidTest/assets/pages/videoMediaPage.html b/app/src/androidTest/assets/pages/videoMediaPage.html index 32baa8d78..3de177e2c 100644 --- a/app/src/androidTest/assets/pages/videoMediaPage.html +++ b/app/src/androidTest/assets/pages/videoMediaPage.html @@ -9,18 +9,5 @@ -
-
- \ No newline at end of file diff --git a/app/src/androidTest/java/org/mozilla/fenix/helpers/TestHelper.kt b/app/src/androidTest/java/org/mozilla/fenix/helpers/TestHelper.kt index ec9b3d70e..30db0383c 100644 --- a/app/src/androidTest/java/org/mozilla/fenix/helpers/TestHelper.kt +++ b/app/src/androidTest/java/org/mozilla/fenix/helpers/TestHelper.kt @@ -4,12 +4,17 @@ package org.mozilla.fenix.helpers +import android.app.PendingIntent import android.content.ActivityNotFoundException import android.content.Context import android.content.Intent +import android.graphics.Bitmap +import android.graphics.Canvas +import android.graphics.Color import android.net.Uri import android.os.Build import android.os.Environment +import androidx.browser.customtabs.CustomTabsIntent import androidx.preference.PreferenceManager import androidx.test.espresso.Espresso import androidx.test.espresso.Espresso.onView @@ -153,4 +158,32 @@ object TestHelper { } } } + + fun createCustomTabIntent( + pageUrl: String, + customMenuItemLabel: String = "", + customActionButtonDescription: String = "" + ): Intent { + val appContext = InstrumentationRegistry.getInstrumentation() + .targetContext + .applicationContext + val pendingIntent = PendingIntent.getActivity(appContext, 0, Intent(), 0) + val customTabsIntent = CustomTabsIntent.Builder() + .addMenuItem(customMenuItemLabel, pendingIntent) + .setShareState(CustomTabsIntent.SHARE_STATE_ON) + .setActionButton( + createTestBitmap(), + customActionButtonDescription, pendingIntent, true + ) + .build() + customTabsIntent.intent.data = Uri.parse(pageUrl) + return customTabsIntent.intent + } + + private fun createTestBitmap(): Bitmap { + val bitmap = Bitmap.createBitmap(100, 100, Bitmap.Config.ARGB_8888) + val canvas = Canvas(bitmap) + canvas.drawColor(Color.GREEN) + return bitmap + } } diff --git a/app/src/androidTest/java/org/mozilla/fenix/screenshots/MenuScreenShotTest.kt b/app/src/androidTest/java/org/mozilla/fenix/screenshots/MenuScreenShotTest.kt index d058bc8c7..ab2465a79 100644 --- a/app/src/androidTest/java/org/mozilla/fenix/screenshots/MenuScreenShotTest.kt +++ b/app/src/androidTest/java/org/mozilla/fenix/screenshots/MenuScreenShotTest.kt @@ -68,47 +68,38 @@ class MenuScreenShotTest : ScreenshotTest() { }.openThreeDotMenu { }.openSettings { Screengrab.screenshot("SettingsRobot_settings-menu") - settingsAccountPreferences() + }.openTurnOnSyncMenu { Screengrab.screenshot("AccountSettingsRobot_settings-account") - mDevice.pressBack() - - settingsSearch() + }.goBack { + }.openSearchSubMenu { Screengrab.screenshot("SettingsSubMenuSearchRobot_settings-search") - mDevice.pressBack() - - settingsTheme() + }.goBack { + }.openCustomizeSubMenu { Screengrab.screenshot("SettingsSubMenuThemeRobot_settings-theme") - mDevice.pressBack() - - settingsAccessibility() + }.goBack { + }.openAccessibilitySubMenu { Screengrab.screenshot("SettingsSubMenuAccessibilityRobot_settings-accessibility") - mDevice.pressBack() - - settingsLanguage() + }.goBack { + }.openLanguageSubMenu { Screengrab.screenshot("SettingsSubMenuAccessibilityRobot_settings-language") - mDevice.pressBack() - - settingDefaultBrowser() + }.goBack { + // From about here we need to scroll up to ensure all settings options are visible. + }.openSetDefaultBrowserSubMenu { Screengrab.screenshot("SettingsSubMenuDefaultBrowserRobot_settings-default-browser") - mDevice.pressBack() - - // Disabled for Pixel 2 - // settingsTP() - // Screengrab.screenshot("settings-enhanced-tp") - // mDevice.pressBack() - - loginsAndPassword() + }.goBack { + // Disabled for Pixel 2 + // }.openEnhancedTrackingProtectionSubMenu { + // Screengrab.screenshot("settings-enhanced-tp") + // }.goBack { + }.openLoginsAndPasswordSubMenu { Screengrab.screenshot("SettingsSubMenuLoginsAndPasswords-settings-logins-passwords") - mDevice.pressBack() - + }.goBack { swipeToBottom() Screengrab.screenshot("SettingsRobot_settings-scroll-to-bottom") - - settingsTelemetry() + }.openSettingsSubMenuDataCollection { Screengrab.screenshot("settings-telemetry") - mDevice.pressBack() - - addOns() + }.goBack { + }.openAddonsManagerMenu { Screengrab.screenshot("settings-addons") } } diff --git a/app/src/androidTest/java/org/mozilla/fenix/ui/BookmarksTest.kt b/app/src/androidTest/java/org/mozilla/fenix/ui/BookmarksTest.kt index d09de56b3..747aed42d 100644 --- a/app/src/androidTest/java/org/mozilla/fenix/ui/BookmarksTest.kt +++ b/app/src/androidTest/java/org/mozilla/fenix/ui/BookmarksTest.kt @@ -223,8 +223,7 @@ class BookmarksTest { IdlingRegistry.getInstance().register(bookmarksListIdlingResource!!) }.openThreeDotMenu(defaultWebPage.url) { }.clickOpenInNewTab { - verifyUrl(defaultWebPage.url.toString()) - }.openTabDrawer { + verifyTabTrayIsOpened() verifyNormalModeSelected() } } @@ -242,8 +241,7 @@ class BookmarksTest { IdlingRegistry.getInstance().register(bookmarksListIdlingResource!!) }.openThreeDotMenu(defaultWebPage.url) { }.clickOpenInPrivateTab { - verifyUrl(defaultWebPage.url.toString()) - }.openTabDrawer { + verifyTabTrayIsOpened() verifyPrivateModeSelected() } } diff --git a/app/src/androidTest/java/org/mozilla/fenix/ui/DeepLinkTest.kt b/app/src/androidTest/java/org/mozilla/fenix/ui/DeepLinkTest.kt index 7bca26ebe..ff9159210 100644 --- a/app/src/androidTest/java/org/mozilla/fenix/ui/DeepLinkTest.kt +++ b/app/src/androidTest/java/org/mozilla/fenix/ui/DeepLinkTest.kt @@ -108,7 +108,6 @@ class DeepLinkTest { fun openSettingsLogins() { robot.openSettingsLogins { verifyDefaultView() - verifyDefaultValueSyncLogins() verifyDefaultValueAutofillLogins() } } diff --git a/app/src/androidTest/java/org/mozilla/fenix/ui/HistoryTest.kt b/app/src/androidTest/java/org/mozilla/fenix/ui/HistoryTest.kt index 8267e85be..6dcdc9e4c 100644 --- a/app/src/androidTest/java/org/mozilla/fenix/ui/HistoryTest.kt +++ b/app/src/androidTest/java/org/mozilla/fenix/ui/HistoryTest.kt @@ -149,8 +149,7 @@ class HistoryTest { IdlingRegistry.getInstance().register(historyListIdlingResource!!) }.openThreeDotMenu { }.clickOpenInNormalTab { - verifyUrl(firstWebPage.url.toString()) - }.openTabDrawer { + verifyTabTrayIsOpened() verifyNormalModeSelected() } } @@ -170,8 +169,7 @@ class HistoryTest { IdlingRegistry.getInstance().register(historyListIdlingResource!!) }.openThreeDotMenu { }.clickOpenInPrivateTab { - verifyUrl(firstWebPage.url.toString()) - }.openTabDrawer { + verifyTabTrayIsOpened() verifyPrivateModeSelected() } } diff --git a/app/src/androidTest/java/org/mozilla/fenix/ui/MediaNotificationTest.kt b/app/src/androidTest/java/org/mozilla/fenix/ui/MediaNotificationTest.kt index 02ce669f2..ac17093b2 100644 --- a/app/src/androidTest/java/org/mozilla/fenix/ui/MediaNotificationTest.kt +++ b/app/src/androidTest/java/org/mozilla/fenix/ui/MediaNotificationTest.kt @@ -4,13 +4,15 @@ package org.mozilla.fenix.ui -import androidx.test.uiautomator.UiSelector +import mozilla.components.browser.state.store.BrowserStore +import mozilla.components.concept.engine.mediasession.MediaSession import okhttp3.mockwebserver.MockWebServer import org.junit.After import org.junit.Before import org.junit.Ignore import org.junit.Rule import org.junit.Test +import org.mozilla.fenix.ext.components import org.mozilla.fenix.helpers.AndroidAssetDispatcher import org.mozilla.fenix.helpers.HomeActivityTestRule import org.mozilla.fenix.helpers.TestAssetHelper @@ -33,9 +35,14 @@ class MediaNotificationTest { @get:Rule val activityTestRule = HomeActivityTestRule() + private lateinit var browserStore: BrowserStore @Before fun setUp() { + // Initializing this as part of class construction, below the rule would throw a NPE + // So we are initializing this here instead of in all tests. + browserStore = activityTestRule.activity.components.core.store + mockWebServer = MockWebServer().apply { dispatcher = AndroidAssetDispatcher() start() @@ -45,16 +52,10 @@ class MediaNotificationTest { @After fun tearDown() { mockWebServer.shutdown() - // verify if the notification tray is expanded and should be closed before the next test - val notificationShade = - mDevice.findObject(UiSelector().resourceId("com.android.systemui:id/notification_stack_scroller")) - - if (notificationShade.exists()) - mDevice.pressBack() } + @Ignore("Still failing, due to https://github.com/mozilla-mobile/android-components/issues/9748") @Test - @Ignore("https://github.com/mozilla-mobile/fenix/issues/15754") fun videoPlaybackSystemNotificationTest() { val videoTestPage = TestAssetHelper.getVideoPageAsset(mockWebServer) @@ -62,7 +63,7 @@ class MediaNotificationTest { }.enterURLAndEnterToBrowser(videoTestPage.url) { mDevice.waitForIdle() clickMediaPlayerPlayButton() - waitForPlaybackToStart() + assertPlaybackState(browserStore, MediaSession.PlaybackState.PLAYING) }.openNotificationShade { verifySystemNotificationExists(videoTestPage.title) clickMediaSystemNotificationControlButton("Pause") @@ -72,7 +73,7 @@ class MediaNotificationTest { mDevice.pressBack() browserScreen { - verifyMediaIsPaused() + assertPlaybackState(browserStore, MediaSession.PlaybackState.PAUSED) }.openTabDrawer { closeTab() } @@ -88,60 +89,6 @@ class MediaNotificationTest { } @Test - @Ignore("https://github.com/mozilla-mobile/fenix/issues/15754") - fun audioPlaybackSystemNotificationTest() { - val audioTestPage = TestAssetHelper.getAudioPageAsset(mockWebServer) - - navigationToolbar { - }.enterURLAndEnterToBrowser(audioTestPage.url) { - mDevice.waitForIdle() - clickMediaPlayerPlayButton() - waitForPlaybackToStart() - }.openNotificationShade { - verifySystemNotificationExists(audioTestPage.title) - clickMediaSystemNotificationControlButton("Pause") - verifyMediaSystemNotificationButtonState("Play") - } - - mDevice.pressBack() - - browserScreen { - verifyMediaIsPaused() - }.openTabDrawer { - closeTab() - } - - mDevice.openNotification() - - notificationShade { - verifySystemNotificationGone(audioTestPage.title) - } - - // close notification shade before the next test - mDevice.pressBack() - } - - @Test - @Ignore("https://github.com/mozilla-mobile/fenix/issues/15754") - fun tabMediaControlButtonTest() { - val audioTestPage = TestAssetHelper.getAudioPageAsset(mockWebServer) - - navigationToolbar { - }.enterURLAndEnterToBrowser(audioTestPage.url) { - mDevice.waitForIdle() - clickMediaPlayerPlayButton() - waitForPlaybackToStart() - }.openTabDrawer { - verifyTabMediaControlButtonState("Pause") - clickTabMediaControlButton() - verifyTabMediaControlButtonState("Play") - }.openTab(audioTestPage.title) { - verifyMediaIsPaused() - } - } - - @Test - @Ignore("https://github.com/mozilla-mobile/fenix/issues/15754") fun mediaSystemNotificationInPrivateModeTest() { val audioTestPage = TestAssetHelper.getAudioPageAsset(mockWebServer) @@ -151,7 +98,7 @@ class MediaNotificationTest { }.enterURLAndEnterToBrowser(audioTestPage.url) { mDevice.waitForIdle() clickMediaPlayerPlayButton() - waitForPlaybackToStart() + assertPlaybackState(browserStore, MediaSession.PlaybackState.PLAYING) }.openNotificationShade { verifySystemNotificationExists("A site is playing media") clickMediaSystemNotificationControlButton("Pause") @@ -161,7 +108,7 @@ class MediaNotificationTest { mDevice.pressBack() browserScreen { - verifyMediaIsPaused() + assertPlaybackState(browserStore, MediaSession.PlaybackState.PAUSED) }.openTabDrawer { closeTab() verifySnackBarText("Private tab closed") diff --git a/app/src/androidTest/java/org/mozilla/fenix/ui/SearchTest.kt b/app/src/androidTest/java/org/mozilla/fenix/ui/SearchTest.kt index 11454a188..06ac71c14 100644 --- a/app/src/androidTest/java/org/mozilla/fenix/ui/SearchTest.kt +++ b/app/src/androidTest/java/org/mozilla/fenix/ui/SearchTest.kt @@ -32,6 +32,7 @@ class SearchTest { verifySearchView() verifyBrowserToolbar() verifyScanButton() + verifySearchEngineButton() } } diff --git a/app/src/androidTest/java/org/mozilla/fenix/ui/SettingsPrivacyTest.kt b/app/src/androidTest/java/org/mozilla/fenix/ui/SettingsPrivacyTest.kt index 81a1a4459..1999e13d8 100644 --- a/app/src/androidTest/java/org/mozilla/fenix/ui/SettingsPrivacyTest.kt +++ b/app/src/androidTest/java/org/mozilla/fenix/ui/SettingsPrivacyTest.kt @@ -147,6 +147,12 @@ class SettingsPrivacyTest { verifyDeleteBrowsingDataOnQuitSubMenuItems() }.goBack { + // NOTIFICATIONS + verifyNotificationsButton() + }.openSettingsSubMenuNotifications { + verifySystemNotificationsView() + }.goBack { + // DATA COLLECTION verifyDataCollectionButton() }.openSettingsSubMenuDataCollection { @@ -170,7 +176,6 @@ class SettingsPrivacyTest { TestHelper.scrollToElementByText("Logins and passwords") }.openLoginsAndPasswordSubMenu { verifyDefaultView() - verifyDefaultValueSyncLogins() verifyDefaultValueAutofillLogins() verifyDefaultValueExceptions() }.openSavedLogins { @@ -203,7 +208,6 @@ class SettingsPrivacyTest { TestHelper.scrollToElementByText("Logins and passwords") }.openLoginsAndPasswordSubMenu { verifyDefaultView() - verifyDefaultValueSyncLogins() }.openSavedLogins { verifySecurityPromptForLogins() tapSetupLater() @@ -228,7 +232,6 @@ class SettingsPrivacyTest { }.openSettings { }.openLoginsAndPasswordSubMenu { verifyDefaultView() - verifyDefaultValueSyncLogins() }.openSavedLogins { verifySecurityPromptForLogins() tapSetupLater() diff --git a/app/src/androidTest/java/org/mozilla/fenix/ui/SmokeTest.kt b/app/src/androidTest/java/org/mozilla/fenix/ui/SmokeTest.kt index be94e034d..1e5d40593 100644 --- a/app/src/androidTest/java/org/mozilla/fenix/ui/SmokeTest.kt +++ b/app/src/androidTest/java/org/mozilla/fenix/ui/SmokeTest.kt @@ -9,8 +9,11 @@ import androidx.core.net.toUri import androidx.recyclerview.widget.RecyclerView import androidx.test.espresso.IdlingRegistry import androidx.test.platform.app.InstrumentationRegistry +import androidx.test.rule.ActivityTestRule import androidx.test.rule.GrantPermissionRule import androidx.test.uiautomator.UiDevice +import mozilla.components.browser.state.store.BrowserStore +import mozilla.components.concept.engine.mediasession.MediaSession import okhttp3.mockwebserver.MockWebServer import org.junit.After import org.junit.Before @@ -18,23 +21,29 @@ import org.junit.Ignore import org.junit.Rule import org.junit.Test import org.mozilla.fenix.FeatureFlags +import org.mozilla.fenix.IntentReceiverActivity import org.mozilla.fenix.R +import org.mozilla.fenix.ext.components import org.mozilla.fenix.ext.settings import org.mozilla.fenix.helpers.AndroidAssetDispatcher import org.mozilla.fenix.helpers.HomeActivityTestRule import org.mozilla.fenix.helpers.RecyclerViewIdlingResource import org.mozilla.fenix.helpers.TestAssetHelper import org.mozilla.fenix.helpers.TestHelper +import org.mozilla.fenix.helpers.TestHelper.createCustomTabIntent import org.mozilla.fenix.helpers.TestHelper.deleteDownloadFromStorage +import org.mozilla.fenix.helpers.TestHelper.scrollToElementByText import org.mozilla.fenix.helpers.ViewVisibilityIdlingResource import org.mozilla.fenix.ui.robots.browserScreen import org.mozilla.fenix.ui.robots.clickTabCrashedRestoreButton import org.mozilla.fenix.ui.robots.clickUrlbar +import org.mozilla.fenix.ui.robots.customTabScreen import org.mozilla.fenix.ui.robots.dismissTrackingOnboarding import org.mozilla.fenix.ui.robots.downloadRobot import org.mozilla.fenix.ui.robots.enhancedTrackingProtection import org.mozilla.fenix.ui.robots.homeScreen import org.mozilla.fenix.ui.robots.navigationToolbar +import org.mozilla.fenix.ui.robots.notificationShade import org.mozilla.fenix.ui.robots.tabDrawer import org.mozilla.fenix.ui.util.STRING_ONBOARDING_TRACKING_PROTECTION_HEADER @@ -52,8 +61,9 @@ class SmokeTest { private var recentlyClosedTabsListIdlingResource: RecyclerViewIdlingResource? = null private var readerViewNotification: ViewVisibilityIdlingResource? = null private val downloadFileName = "Globe.svg" - val collectionName = "First Collection" + private val collectionName = "First Collection" private var bookmarksListIdlingResource: RecyclerViewIdlingResource? = null + private val customMenuItem = "TestMenuItem" // This finds the dialog fragment child of the homeFragment, otherwise the awesomeBar would return null private fun getAwesomebarView(): View? { @@ -66,6 +76,12 @@ class SmokeTest { @get:Rule val activityTestRule = HomeActivityTestRule() + private lateinit var browserStore: BrowserStore + + @get: Rule + val intentReceiverActivityTestRule = ActivityTestRule( + IntentReceiverActivity::class.java, true, false + ) @get:Rule var mGrantPermissions = GrantPermissionRule.grant( @@ -75,6 +91,10 @@ class SmokeTest { @Before fun setUp() { + // Initializing this as part of class construction, below the rule would throw a NPE + // So we are initializing this here instead of in all related tests. + browserStore = activityTestRule.activity.components.core.store + mockWebServer = MockWebServer().apply { dispatcher = AndroidAssetDispatcher() start() @@ -112,7 +132,7 @@ class SmokeTest { } } - // copied over from HomeScreenTest + // Verifies the first run onboarding screen @Test fun firstRunScreenTest() { homeScreen { @@ -155,7 +175,6 @@ class SmokeTest { } @Test - @Ignore("https://github.com/mozilla-mobile/fenix/issues/18603") // Verifies the functionality of the onboarding Start Browsing button fun startBrowsingButtonTest() { homeScreen { @@ -525,7 +544,6 @@ class SmokeTest { } } - @Ignore("Failing, see: https://github.com/mozilla-mobile/fenix/issues/17847") @Test // Swipes the nav bar left/right to switch between tabs fun swipeToSwitchTabTest() { @@ -1062,34 +1080,6 @@ class SmokeTest { } } - @Ignore("Feature is temporarily removed; disabling test. See https://github.com/mozilla-mobile/fenix/issues/18656") - @Test - fun selectTabsButtonVisibilityTest() { - homeScreen { - }.dismissOnboarding() - - val firstWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 1) - val secondWebPage = TestAssetHelper.getGenericAsset(mockWebServer, 2) - - navigationToolbar { - }.enterURLAndEnterToBrowser(firstWebPage.url) { - mDevice.waitForIdle() - }.openTabDrawer { - }.openNewTab { - }.submitQuery(secondWebPage.url.toString()) { - mDevice.waitForIdle() - }.openTabDrawer { - }.toggleToPrivateTabs { - }.openNewTab { - }.dismissSearchBar { } - - homeScreen { - }.openTabDrawer { - }.toggleToNormalTabs { - verifySelectTabsButton() - } - } - @Test fun privateTabsTrayWithOpenedTabTest() { val website = TestAssetHelper.getGenericAsset(mockWebServer, 1) @@ -1230,4 +1220,104 @@ class SmokeTest { verifyPageContent(website.content) } } + + @Test + // Verifies the main menu of a custom tab with a custom menu item + fun customTabMenuItemsTest() { + val customTabPage = TestAssetHelper.getGenericAsset(mockWebServer, 1) + + intentReceiverActivityTestRule.launchActivity( + createCustomTabIntent( + customTabPage.url.toString(), + customMenuItem + ) + ) + + customTabScreen { + browserScreen { + verifyPageContent(customTabPage.content) + } + }.openMainMenu { + verifyPoweredByTextIsDisplayed() + verifyCustomMenuItem(customMenuItem) + verifyDesktopSiteButtonExists() + verifyFindInPageButtonExists() + verifyOpenInBrowserButtonExists() + verifyBackButtonExists() + verifyForwardButtonExists() + verifyRefreshButtonExists() + } + } + + @Test + // The test opens a link in a custom tab then sends it to the browser + fun openCustomTabInBrowserTest() { + val customTabPage = TestAssetHelper.getGenericAsset(mockWebServer, 1) + + intentReceiverActivityTestRule.launchActivity( + createCustomTabIntent( + customTabPage.url.toString() + ) + ) + + customTabScreen { + browserScreen { + verifyPageContent(customTabPage.content) + } + }.openMainMenu { + }.clickOpenInBrowserButton { + verifyTabCounter("1") + } + } + + @Test + fun audioPlaybackSystemNotificationTest() { + val audioTestPage = TestAssetHelper.getAudioPageAsset(mockWebServer) + + navigationToolbar { + }.enterURLAndEnterToBrowser(audioTestPage.url) { + mDevice.waitForIdle() + clickMediaPlayerPlayButton() + assertPlaybackState(browserStore, MediaSession.PlaybackState.PLAYING) + }.openNotificationShade { + verifySystemNotificationExists(audioTestPage.title) + clickMediaSystemNotificationControlButton("Pause") + verifyMediaSystemNotificationButtonState("Play") + } + + mDevice.pressBack() + + browserScreen { + assertPlaybackState(browserStore, MediaSession.PlaybackState.PAUSED) + }.openTabDrawer { + closeTab() + } + + mDevice.openNotification() + + notificationShade { + verifySystemNotificationGone(audioTestPage.title) + } + + // close notification shade before the next test + mDevice.pressBack() + } + + @Test + fun tabMediaControlButtonTest() { + val audioTestPage = TestAssetHelper.getAudioPageAsset(mockWebServer) + + navigationToolbar { + }.enterURLAndEnterToBrowser(audioTestPage.url) { + mDevice.waitForIdle() + clickMediaPlayerPlayButton() + assertPlaybackState(browserStore, MediaSession.PlaybackState.PLAYING) + }.openTabDrawer { + verifyTabMediaControlButtonState("Pause") + clickTabMediaControlButton() + verifyTabMediaControlButtonState("Play") + }.openTab(audioTestPage.title) { + assertPlaybackState(browserStore, MediaSession.PlaybackState.PAUSED) + } + } } diff --git a/app/src/androidTest/java/org/mozilla/fenix/ui/robots/BrowserRobot.kt b/app/src/androidTest/java/org/mozilla/fenix/ui/robots/BrowserRobot.kt index d10a7df65..30a1691bf 100644 --- a/app/src/androidTest/java/org/mozilla/fenix/ui/robots/BrowserRobot.kt +++ b/app/src/androidTest/java/org/mozilla/fenix/ui/robots/BrowserRobot.kt @@ -9,6 +9,7 @@ package org.mozilla.fenix.ui.robots import android.content.Context import android.content.Intent import android.net.Uri +import android.os.SystemClock import android.widget.EditText import androidx.test.espresso.Espresso.onView import androidx.test.espresso.Espresso.pressBack @@ -33,10 +34,13 @@ import androidx.test.uiautomator.UiDevice import androidx.test.uiautomator.UiSelector import androidx.test.uiautomator.Until import mozilla.components.browser.state.selector.selectedTab +import mozilla.components.browser.state.store.BrowserStore +import mozilla.components.concept.engine.mediasession.MediaSession import org.hamcrest.CoreMatchers.allOf import org.hamcrest.CoreMatchers.containsString import org.hamcrest.Matchers.not import org.junit.Assert.assertTrue +import org.junit.Assert.fail import org.mozilla.fenix.R import org.mozilla.fenix.ext.components import org.mozilla.fenix.helpers.Constants.LONG_CLICK_DURATION @@ -371,14 +375,33 @@ class BrowserRobot { mediaPlayerPlayButton().click() } - fun waitForPlaybackToStart() { - val playStateMessage = mDevice.findObject(UiSelector().text("Media file is playing")) - assertTrue(playStateMessage.waitForExists(waitingTime)) - } - - fun verifyMediaIsPaused() { - val pausedStateMessage = mDevice.findObject(UiSelector().text("Media file is paused")) - assertTrue(pausedStateMessage.waitForExists(waitingTime)) + /** + * Get the current playback state of the currently selected tab. + * The result may be null if there if the currently playing media tab cannot be found in [store] + * + * @param store [BrowserStore] from which to get data about the current tab's state. + * @return nullable [MediaSession.PlaybackState] indicating the media playback state for the current tab. + */ + private fun getCurrentPlaybackState(store: BrowserStore): MediaSession.PlaybackState? { + return store.state.selectedTab?.mediaSessionState?.playbackState + } + + /** + * Asserts that in [waitingTime] the playback state of the current tab will be [expectedState]. + * + * @param store [BrowserStore] from which to get data about the current tab's state. + * @param expectedState [MediaSession.PlaybackState] the playback state that will be asserted + * @param waitingTime maximum time the test will wait for the playback state to become [expectedState] + * before failing the assertion. + */ + fun assertPlaybackState(store: BrowserStore, expectedState: MediaSession.PlaybackState) { + val startMills = SystemClock.uptimeMillis() + var currentMills: Long = 0 + while (currentMills <= waitingTime) { + if (expectedState == getCurrentPlaybackState(store)) return + currentMills = SystemClock.uptimeMillis() - startMills + } + fail("Playback did not moved to state: $expectedState") } fun swipeNavBarRight(tabUrl: String) { diff --git a/app/src/androidTest/java/org/mozilla/fenix/ui/robots/CustomTabRobot.kt b/app/src/androidTest/java/org/mozilla/fenix/ui/robots/CustomTabRobot.kt new file mode 100644 index 000000000..90f05e96a --- /dev/null +++ b/app/src/androidTest/java/org/mozilla/fenix/ui/robots/CustomTabRobot.kt @@ -0,0 +1,84 @@ +/* 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 org.mozilla.fenix.ui.robots + +import androidx.test.espresso.Espresso.onView +import androidx.test.espresso.action.ViewActions.click +import androidx.test.espresso.assertion.ViewAssertions.matches +import androidx.test.espresso.matcher.ViewMatchers.isDisplayed +import androidx.test.espresso.matcher.ViewMatchers.withId +import androidx.test.espresso.matcher.ViewMatchers.withText +import androidx.test.uiautomator.UiSelector +import junit.framework.TestCase.assertTrue +import mozilla.components.support.ktx.android.content.appName +import org.mozilla.fenix.R +import org.mozilla.fenix.helpers.TestAssetHelper.waitingTime + +/** + * Implementation of the robot pattern for Custom tabs + */ +class CustomTabRobot { + + fun verifyDesktopSiteButtonExists() { + desktopSiteButton().check(matches(isDisplayed())) + } + + fun verifyFindInPageButtonExists() { + findInPageButton().check(matches(isDisplayed())) + } + + fun verifyPoweredByTextIsDisplayed() { + mDevice.findObject(UiSelector().textContains("POWERED BY ${appContext.appName}")) + } + + fun verifyOpenInBrowserButtonExists() { + openInBrowserButton().check(matches(isDisplayed())) + } + + fun verifyBackButtonExists() = assertTrue(backButton().waitForExists(waitingTime)) + + fun verifyForwardButtonExists() = assertTrue(forwardButton().waitForExists(waitingTime)) + + fun verifyRefreshButtonExists() = assertTrue(refreshButton().waitForExists(waitingTime)) + + fun verifyCustomMenuItem(label: String) { + assertTrue(mDevice.findObject(UiSelector().text(label)).exists()) + } + + class Transition { + fun openMainMenu(interact: CustomTabRobot.() -> Unit): Transition { + mainMenuButton().waitForExists(waitingTime) + mainMenuButton().click() + + CustomTabRobot().interact() + return Transition() + } + + fun clickOpenInBrowserButton(interact: BrowserRobot.() -> Unit): BrowserRobot.Transition { + openInBrowserButton().perform(click()) + + BrowserRobot().interact() + return BrowserRobot.Transition() + } + } +} + +fun customTabScreen(interact: CustomTabRobot.() -> Unit): CustomTabRobot.Transition { + CustomTabRobot().interact() + return CustomTabRobot.Transition() +} + +private fun mainMenuButton() = mDevice.findObject(UiSelector().description("Menu")) + +private fun desktopSiteButton() = onView(withId(R.id.switch_widget)) + +private fun findInPageButton() = onView(withText("Find in page")) + +private fun openInBrowserButton() = onView(withText("Open in ${appContext.appName}")) + +private fun refreshButton() = mDevice.findObject(UiSelector().description("Refresh")) + +private fun forwardButton() = mDevice.findObject(UiSelector().description("Forward")) + +private fun backButton() = mDevice.findObject(UiSelector().description("Back")) diff --git a/app/src/androidTest/java/org/mozilla/fenix/ui/robots/HomeScreenRobot.kt b/app/src/androidTest/java/org/mozilla/fenix/ui/robots/HomeScreenRobot.kt index 95825a1c5..2f62957d1 100644 --- a/app/src/androidTest/java/org/mozilla/fenix/ui/robots/HomeScreenRobot.kt +++ b/app/src/androidTest/java/org/mozilla/fenix/ui/robots/HomeScreenRobot.kt @@ -11,7 +11,6 @@ import android.widget.EditText import androidx.recyclerview.widget.RecyclerView import androidx.test.espresso.Espresso.onView import androidx.test.espresso.NoMatchingViewException -import androidx.test.espresso.ViewInteraction import androidx.test.espresso.action.ViewActions import androidx.test.espresso.action.ViewActions.click import androidx.test.espresso.action.ViewActions.swipeLeft @@ -24,7 +23,6 @@ import androidx.test.espresso.matcher.ViewMatchers.Visibility import androidx.test.espresso.matcher.ViewMatchers.hasDescendant import androidx.test.espresso.matcher.ViewMatchers.hasSibling import androidx.test.espresso.matcher.ViewMatchers.isDisplayed -import androidx.test.espresso.matcher.ViewMatchers.withContentDescription import androidx.test.espresso.matcher.ViewMatchers.withEffectiveVisibility import androidx.test.espresso.matcher.ViewMatchers.withHint import androidx.test.espresso.matcher.ViewMatchers.withId @@ -33,10 +31,12 @@ import androidx.test.platform.app.InstrumentationRegistry import androidx.test.uiautomator.By import androidx.test.uiautomator.By.text import androidx.test.uiautomator.UiDevice +import androidx.test.uiautomator.UiObject import androidx.test.uiautomator.UiScrollable import androidx.test.uiautomator.UiSelector import androidx.test.uiautomator.Until import androidx.test.uiautomator.Until.findObject +import junit.framework.TestCase.assertTrue import mozilla.components.browser.state.state.searchEngines import mozilla.components.support.ktx.android.content.appName import org.hamcrest.CoreMatchers.allOf @@ -240,12 +240,6 @@ class HomeScreenRobot { } } - fun scrollToElementByText(text: String): UiScrollable { - val appView = UiScrollable(UiSelector().scrollable(true)) - appView.scrollTextIntoView(text) - return appView - } - fun togglePrivateBrowsingModeOnOff() { onView(ViewMatchers.withResourceName("privateBrowsingButton")) .perform(click()) @@ -256,12 +250,6 @@ class HomeScreenRobot { fun swipeToTop() = onView(withId(R.id.sessionControlRecyclerView)).perform(ViewActions.swipeDown()) - fun swipeTabRight(title: String) = - tab(title).perform(ViewActions.swipeRight()) - - fun swipeTabLeft(title: String) = - tab(title).perform(ViewActions.swipeLeft()) - fun verifySnackBarText(expectedText: String) { val mDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation()) mDevice.waitNotNull(findObject(By.text(expectedText)), waitingTime) @@ -273,21 +261,6 @@ class HomeScreenRobot { ).perform(click()) } - fun verifyTabMediaControlButtonState(action: String) { - mDevice.waitNotNull( - findObject( - By - .res("org.mozilla.fenix.debug:id/play_pause_button") - .desc(action) - ), - waitingTime - ) - - tabMediaControlButton().check(matches(withContentDescription(action))) - } - - fun clickTabMediaControlButton() = tabMediaControlButton().click() - class Transition { val mDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation()) @@ -314,6 +287,8 @@ class HomeScreenRobot { } fun openSearch(interact: SearchRobot.() -> Unit): SearchRobot.Transition { + mDevice.findObject(UiSelector().resourceId("$packageName:id/toolbar")) + .waitForExists(waitingTime) navigationToolbar().perform(click()) SearchRobot().interact() @@ -325,7 +300,6 @@ class HomeScreenRobot { } fun clickStartBrowsingButton(interact: SearchRobot.() -> Unit): SearchRobot.Transition { - scrollToElementByText("Start browsing") startBrowsingButton().click() SearchRobot().interact() @@ -333,7 +307,11 @@ class HomeScreenRobot { } fun togglePrivateBrowsingMode() { - onView(ViewMatchers.withResourceName("privateBrowsingButton")) + mDevice.findObject(UiSelector().resourceId("$packageName:id/privateBrowsingButton")) + .waitForExists( + waitingTime + ) + privateBrowsingButton() .perform(click()) } @@ -342,10 +320,10 @@ class HomeScreenRobot { for (i in 1..5) { mDevice.findObject(UiSelector().resourceId("$packageName:id/privateBrowsingButton")) .waitForExists( - waitingTime + waitingTime ) - onView(ViewMatchers.withResourceName("privateBrowsingButton")) + privateBrowsingButton() .perform(click()) } @@ -357,25 +335,11 @@ class HomeScreenRobot { onView(ViewMatchers.isRoot()).perform(ViewActions.pressBack()) } - fun openTabsListThreeDotMenu(interact: ThreeDotMenuMainRobot.() -> Unit): ThreeDotMenuMainRobot.Transition { -// tabsListThreeDotButton().perform(click()) - - ThreeDotMenuMainRobot().interact() - return ThreeDotMenuMainRobot.Transition() - } - - fun closeAllPrivateTabs(interact: HomeScreenRobot.() -> Unit): Transition { - onView(withId(R.id.close_tabs_button)) - .check(matches(withEffectiveVisibility(Visibility.VISIBLE))) - .perform(click()) - - HomeScreenRobot().interact() - return Transition() - } - fun openNavigationToolbar(interact: NavigationToolbarRobot.() -> Unit): NavigationToolbarRobot.Transition { + mDevice.findObject(UiSelector().resourceId("$packageName:id/toolbar")) + .waitForExists(waitingTime) + navigationToolbar().perform(click()) - assertNavigationToolbar().perform(click()) NavigationToolbarRobot().interact() return NavigationToolbarRobot.Transition() } @@ -462,6 +426,13 @@ fun homeScreen(interact: HomeScreenRobot.() -> Unit): HomeScreenRobot.Transition val mDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation()) val appContext = InstrumentationRegistry.getInstrumentation().targetContext +private fun homeScreenList() = + UiScrollable( + UiSelector() + .resourceId("$packageName:id/sessionControlRecyclerView") + .scrollable(true) + ).setAsVerticalList() + private fun assertKeyboardVisibility(isExpectedToBeVisible: Boolean) = Assert.assertEquals( isExpectedToBeVisible, @@ -470,14 +441,10 @@ private fun assertKeyboardVisibility(isExpectedToBeVisible: Boolean) = .contains("mInputShown=true") ) -private fun navigationToolbar() = - onView(allOf(withText("Search or enter address"))) - -private fun closeTabButton() = onView(withId(R.id.close_tab_button)) +private fun navigationToolbar() = onView(withId(R.id.toolbar)) private fun assertNavigationToolbar() = - onView(allOf(withText("Search or enter address"))) - .check(matches(withEffectiveVisibility(Visibility.VISIBLE))) + navigationToolbar().check(matches(withEffectiveVisibility(Visibility.VISIBLE))) private fun assertFocusedNavigationToolbar() = onView(allOf(withHint("Search or enter address"))) @@ -493,8 +460,8 @@ private fun assertHomeMenu() = onView(ViewMatchers.withResourceName("menuButton" .check(matches(withEffectiveVisibility(Visibility.VISIBLE))) private fun assertHomePrivateBrowsingButton() = - onView(ViewMatchers.withResourceName("privateBrowsingButton")) - .check(matches(withEffectiveVisibility(Visibility.VISIBLE))) + privateBrowsingButton() + .check(matches(isDisplayed())) private fun assertHomeWordmark() = onView(ViewMatchers.withResourceName("wordmark")) .check(matches(withEffectiveVisibility(Visibility.VISIBLE))) @@ -644,9 +611,7 @@ private fun assertPrivacyNoticeButton() { } private fun assertStartBrowsingButton() { - scrollToElementByText("Start browsing") - onView(withId(R.id.finish_button)) - .check(matches(withEffectiveVisibility(Visibility.VISIBLE))) + assertTrue(startBrowsingButton().waitForExists(waitingTime)) } // Pick your toolbar placement @@ -711,7 +676,7 @@ private fun assertShareTabsOverlay() { onView(withId(R.id.share_tab_url)).check(matches(isDisplayed())) } -private fun tabMediaControlButton() = onView(withId(R.id.play_pause_button)) +private fun privateBrowsingButton() = onView(withId(R.id.privateBrowsingButton)) private fun collectionItem(title: String) = onView(allOf(withId(R.id.label), withText(title))) @@ -730,15 +695,11 @@ private fun removeTabFromCollectionButton(title: String) = private fun tabsCounter() = onView(withId(R.id.tab_button)) -private fun tab(title: String) = - onView( - allOf( - withId(R.id.tab_title), - withText(title) - ) - ) - -private fun startBrowsingButton(): ViewInteraction { - scrollToElementByText("Start browsing") - return onView(allOf(withText("Start browsing"))) +private fun startBrowsingButton(): UiObject { + val startBrowsingButton = mDevice.findObject(UiSelector().resourceId("$packageName:id/finish_button")) + homeScreenList() + .scrollIntoView(startBrowsingButton) + homeScreenList() + .ensureFullyVisible(startBrowsingButton) + return startBrowsingButton } diff --git a/app/src/androidTest/java/org/mozilla/fenix/ui/robots/SearchRobot.kt b/app/src/androidTest/java/org/mozilla/fenix/ui/robots/SearchRobot.kt index 6bf120a16..a9ccd138a 100644 --- a/app/src/androidTest/java/org/mozilla/fenix/ui/robots/SearchRobot.kt +++ b/app/src/androidTest/java/org/mozilla/fenix/ui/robots/SearchRobot.kt @@ -49,6 +49,7 @@ class SearchRobot { fun verifySearchView() = assertSearchView() fun verifyBrowserToolbar() = assertBrowserToolbarEditView() fun verifyScanButton() = assertScanButton() + fun verifySearchEngineButton() = assertSearchEngineButton() fun verifySearchWithText() = assertSearchWithText() fun verifySearchEngineResults(searchEngineName: String) = assertSearchEngineResults(searchEngineName) @@ -215,7 +216,7 @@ private fun assertSearchEngineResults(searchEngineName: String) { } private fun assertSearchView() { - onView(allOf(withId(R.id.search_layout))) + onView(withId(R.id.search_wrapper)).check(matches(withEffectiveVisibility(Visibility.VISIBLE))) } private fun assertBrowserToolbarEditView() = @@ -226,6 +227,10 @@ private fun assertScanButton() = onView(allOf(withText("Scan"))) .check(matches(ViewMatchers.withEffectiveVisibility(ViewMatchers.Visibility.VISIBLE))) +private fun assertSearchEngineButton() = + onView(withId(R.id.search_engines_shortcut_button)) + .check(matches(withEffectiveVisibility(Visibility.VISIBLE))) + private fun assertSearchWithText() = onView(allOf(withText("THIS TIME, SEARCH WITH:"))) .check(matches(ViewMatchers.withEffectiveVisibility(ViewMatchers.Visibility.VISIBLE))) diff --git a/app/src/androidTest/java/org/mozilla/fenix/ui/robots/SettingsRobot.kt b/app/src/androidTest/java/org/mozilla/fenix/ui/robots/SettingsRobot.kt index 61acebf2a..c0d8f33bf 100644 --- a/app/src/androidTest/java/org/mozilla/fenix/ui/robots/SettingsRobot.kt +++ b/app/src/androidTest/java/org/mozilla/fenix/ui/robots/SettingsRobot.kt @@ -9,10 +9,10 @@ package org.mozilla.fenix.ui.robots import android.content.pm.PackageManager import androidx.recyclerview.widget.RecyclerView import androidx.test.espresso.Espresso.onView -import androidx.test.espresso.action.ViewActions -import androidx.test.espresso.contrib.RecyclerViewActions import androidx.test.espresso.ViewInteraction +import androidx.test.espresso.action.ViewActions import androidx.test.espresso.assertion.ViewAssertions.matches +import androidx.test.espresso.contrib.RecyclerViewActions import androidx.test.espresso.intent.Intents.intended import androidx.test.espresso.intent.matcher.IntentMatchers import androidx.test.espresso.intent.matcher.IntentMatchers.toPackage @@ -70,6 +70,7 @@ class SettingsRobot { fun verifyDeleteBrowsingDataOnQuitButton() = assertDeleteBrowsingDataOnQuitButton() fun verifyDeleteBrowsingDataOnQuitValue(state: String) = assertDeleteBrowsingDataValue(state) + fun verifyNotificationsButton() = assertNotificationsButton() fun verifyDataCollectionButton() = assertDataCollectionButton() fun verifyOpenLinksInAppsButton() = assertOpenLinksInAppsButton() fun verifyOpenLinksInAppsSwitchDefault() = assertOpenLinksInAppsValue() @@ -154,6 +155,24 @@ class SettingsRobot { return SettingsSubMenuAccessibilityRobot.Transition() } + fun openLanguageSubMenu(interact: SettingsSubMenuLanguageRobot.() -> Unit): SettingsSubMenuLanguageRobot.Transition { + + fun languageButton() = onView(withText("Language")) + languageButton().click() + + SettingsSubMenuLanguageRobot().interact() + return SettingsSubMenuLanguageRobot.Transition() + } + + fun openSetDefaultBrowserSubMenu(interact: SettingsSubMenuSetDefaultBrowserRobot.() -> Unit): SettingsSubMenuSetDefaultBrowserRobot.Transition { + scrollToElementByText("Set as default browser") + fun setDefaultBrowserButton() = onView(withText("Set as default browser")) + setDefaultBrowserButton().click() + + SettingsSubMenuSetDefaultBrowserRobot().interact() + return SettingsSubMenuSetDefaultBrowserRobot.Transition() + } + fun openEnhancedTrackingProtectionSubMenu(interact: SettingsSubMenuEnhancedTrackingProtectionRobot.() -> Unit): SettingsSubMenuEnhancedTrackingProtectionRobot.Transition { scrollToElementByText("Enhanced Tracking Protection") fun enhancedTrackingProtectionButton() = @@ -217,6 +236,15 @@ class SettingsRobot { return SettingsSubMenuDeleteBrowsingDataOnQuitRobot.Transition() } + fun openSettingsSubMenuNotifications(interact: SystemSettingsRobot.() -> Unit): SystemSettingsRobot.Transition { + scrollToElementByText("Notifications") + fun notificationsButton() = mDevice.findObject(textContains("Notifications")) + notificationsButton().click() + + SystemSettingsRobot().interact() + return SystemSettingsRobot.Transition() + } + fun openSettingsSubMenuDataCollection(interact: SettingsSubMenuDataCollectionRobot.() -> Unit): SettingsSubMenuDataCollectionRobot.Transition { scrollToElementByText("Data collection") fun dataCollectionButton() = mDevice.findObject(textContains("Data collection")) @@ -365,8 +393,17 @@ private fun assertDeleteBrowsingDataValue(state: String) { onView(withText(state)).check(matches(withEffectiveVisibility(Visibility.VISIBLE))) } -private fun assertDataCollectionButton() = onView(withText("Data collection")) +private fun assertNotificationsButton() { + scrollToElementByText("Notifications") + onView(withText("Notifications")) + .check(matches(withEffectiveVisibility(Visibility.VISIBLE))) +} + +private fun assertDataCollectionButton() { + scrollToElementByText("Data collection") + onView(withText("Data collection")) .check(matches(withEffectiveVisibility(Visibility.VISIBLE))) +} private fun openLinksInAppsButton() = onView(withText("Open links in apps")) diff --git a/app/src/androidTest/java/org/mozilla/fenix/ui/robots/SettingsSubMenuLanguageRobot.kt b/app/src/androidTest/java/org/mozilla/fenix/ui/robots/SettingsSubMenuLanguageRobot.kt new file mode 100644 index 000000000..1dd28b2a7 --- /dev/null +++ b/app/src/androidTest/java/org/mozilla/fenix/ui/robots/SettingsSubMenuLanguageRobot.kt @@ -0,0 +1,29 @@ +/* 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 org.mozilla.fenix.ui.robots + +import androidx.test.espresso.Espresso.onView +import androidx.test.espresso.action.ViewActions +import androidx.test.espresso.matcher.ViewMatchers +import androidx.test.platform.app.InstrumentationRegistry +import androidx.test.uiautomator.UiDevice +import org.hamcrest.CoreMatchers + +class SettingsSubMenuLanguageRobot { + class Transition { + val mDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation()) + + fun goBack(interact: SettingsRobot.() -> Unit): SettingsRobot.Transition { + mDevice.waitForIdle() + goBackButton().perform(ViewActions.click()) + + SettingsRobot().interact() + return SettingsRobot.Transition() + } + } +} + +private fun goBackButton() = + onView(CoreMatchers.allOf(ViewMatchers.withContentDescription("Navigate up"))) diff --git a/app/src/androidTest/java/org/mozilla/fenix/ui/robots/SettingsSubMenuLoginsAndPasswordRobot.kt b/app/src/androidTest/java/org/mozilla/fenix/ui/robots/SettingsSubMenuLoginsAndPasswordRobot.kt index 46b8656ce..74a6805de 100644 --- a/app/src/androidTest/java/org/mozilla/fenix/ui/robots/SettingsSubMenuLoginsAndPasswordRobot.kt +++ b/app/src/androidTest/java/org/mozilla/fenix/ui/robots/SettingsSubMenuLoginsAndPasswordRobot.kt @@ -26,7 +26,7 @@ import org.mozilla.fenix.helpers.ext.waitNotNull class SettingsSubMenuLoginsAndPasswordRobot { fun verifyDefaultView() { - mDevice.waitNotNull(Until.findObjects(By.text("Sync logins")), TestAssetHelper.waitingTime) + mDevice.waitNotNull(Until.findObjects(By.text("Sync logins across devices")), TestAssetHelper.waitingTime) assertDefaultView() } @@ -42,8 +42,6 @@ class SettingsSubMenuLoginsAndPasswordRobot { fun verifyDefaultValueAutofillLogins() = assertDefaultValueAutofillLogins() - fun verifyDefaultValueSyncLogins() = assertDefaultValueSyncLogins() - class Transition { val mDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation()) @@ -71,7 +69,7 @@ class SettingsSubMenuLoginsAndPasswordRobot { } fun openSyncLogins(interact: SettingsTurnOnSyncRobot.() -> Unit): SettingsTurnOnSyncRobot.Transition { - fun syncLoginsButton() = onView(ViewMatchers.withText("Sync logins")) + fun syncLoginsButton() = onView(ViewMatchers.withText("Sync logins across devices")) syncLoginsButton().click() SettingsTurnOnSyncRobot().interact() @@ -96,7 +94,7 @@ fun settingsSubMenuLoginsAndPassword(interact: SettingsSubMenuLoginsAndPasswordR private fun goBackButton() = onView(CoreMatchers.allOf(ViewMatchers.withContentDescription("Navigate up"))) -private fun assertDefaultView() = onView(ViewMatchers.withText("Sync logins")) +private fun assertDefaultView() = onView(ViewMatchers.withText("Sync logins across devices")) .check(matches(withEffectiveVisibility(ViewMatchers.Visibility.VISIBLE))) private fun assertDefaultValueAutofillLogins() = onView(ViewMatchers.withText("Autofill")) diff --git a/app/src/androidTest/java/org/mozilla/fenix/ui/robots/SettingsSubMenuSetDefaultBrowserRobot.kt b/app/src/androidTest/java/org/mozilla/fenix/ui/robots/SettingsSubMenuSetDefaultBrowserRobot.kt new file mode 100644 index 000000000..7b7d3bd2c --- /dev/null +++ b/app/src/androidTest/java/org/mozilla/fenix/ui/robots/SettingsSubMenuSetDefaultBrowserRobot.kt @@ -0,0 +1,25 @@ +/* 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 org.mozilla.fenix.ui.robots + +import androidx.test.platform.app.InstrumentationRegistry +import androidx.test.uiautomator.UiDevice + +class SettingsSubMenuSetDefaultBrowserRobot { + class Transition { + val mDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation()) + + fun goBack(interact: SettingsRobot.() -> Unit): SettingsRobot.Transition { + mDevice.waitForIdle() + + // We are now in system settings / showing a default browser dialog. + // Really want to go back to the app. Not interested in up navigation like in other robots. + mDevice.pressBack() + + SettingsRobot().interact() + return SettingsRobot.Transition() + } + } +} diff --git a/app/src/androidTest/java/org/mozilla/fenix/ui/robots/SettingsTurnOnSyncRobot.kt b/app/src/androidTest/java/org/mozilla/fenix/ui/robots/SettingsTurnOnSyncRobot.kt index 156815761..5faa2840b 100644 --- a/app/src/androidTest/java/org/mozilla/fenix/ui/robots/SettingsTurnOnSyncRobot.kt +++ b/app/src/androidTest/java/org/mozilla/fenix/ui/robots/SettingsTurnOnSyncRobot.kt @@ -36,11 +36,11 @@ class SettingsTurnOnSyncRobot { class Transition { val mDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation()) - fun goBack(interact: SettingsSubMenuLoginsAndPasswordRobot.() -> Unit): SettingsSubMenuLoginsAndPasswordRobot.Transition { + fun goBack(interact: SettingsSubMenuLoginsAndPasswordRobot.() -> Unit): SettingsRobot.Transition { goBackButton().perform(ViewActions.click()) SettingsSubMenuLoginsAndPasswordRobot().interact() - return SettingsSubMenuLoginsAndPasswordRobot.Transition() + return SettingsRobot.Transition() } } } diff --git a/app/src/androidTest/java/org/mozilla/fenix/ui/robots/SystemSettingsRobot.kt b/app/src/androidTest/java/org/mozilla/fenix/ui/robots/SystemSettingsRobot.kt index bd3847a8a..daf9ae8c7 100644 --- a/app/src/androidTest/java/org/mozilla/fenix/ui/robots/SystemSettingsRobot.kt +++ b/app/src/androidTest/java/org/mozilla/fenix/ui/robots/SystemSettingsRobot.kt @@ -6,8 +6,12 @@ package org.mozilla.fenix.ui.robots import androidx.test.espresso.intent.Intents import androidx.test.espresso.intent.matcher.IntentMatchers.hasAction +import androidx.test.uiautomator.UiSelector +import org.junit.Assert.assertTrue +import org.mozilla.fenix.helpers.TestAssetHelper.waitingTime class SystemSettingsRobot { + fun verifySystemNotificationsView() = assertSystemNotificationsView() fun verifyNotifications() { Intents.intended(hasAction("android.settings.APP_NOTIFICATION_SETTINGS")) } @@ -18,6 +22,12 @@ class SystemSettingsRobot { class Transition { // Difficult to know where this will go + fun goBack(interact: SettingsRobot.() -> Unit): SettingsRobot.Transition { + mDevice.pressBack() + + SettingsRobot().interact() + return SettingsRobot.Transition() + } } } @@ -25,3 +35,11 @@ fun systemSettings(interact: SystemSettingsRobot.() -> Unit): SystemSettingsRobo SystemSettingsRobot().interact() return SystemSettingsRobot.Transition() } + +private fun assertSystemNotificationsView() { + mDevice.findObject(UiSelector().resourceId("com.android.settings:id/list")) + .waitForExists(waitingTime) + assertTrue(mDevice.findObject(UiSelector().textContains("Show notifications")) + .waitForExists(waitingTime) + ) +} diff --git a/app/src/androidTest/java/org/mozilla/fenix/ui/robots/TabDrawerRobot.kt b/app/src/androidTest/java/org/mozilla/fenix/ui/robots/TabDrawerRobot.kt index f0007760c..8a9256817 100644 --- a/app/src/androidTest/java/org/mozilla/fenix/ui/robots/TabDrawerRobot.kt +++ b/app/src/androidTest/java/org/mozilla/fenix/ui/robots/TabDrawerRobot.kt @@ -80,6 +80,7 @@ class TabDrawerRobot { fun verifySelectTabsButton() = assertSelectTabsButton() fun verifyTabTrayOverflowMenu(visibility: Boolean) = assertTabTrayOverflowButton(visibility) + fun verifyTabTrayIsOpened() = assertTabTrayDoesExist() fun verifyTabTrayIsClosed() = assertTabTrayDoesNotExist() fun verifyHalfExpandedRatio() = assertMinisculeHalfExpandedRatio() fun verifyBehaviorState(expectedState: Int) = assertBehaviorState(expectedState) @@ -421,6 +422,11 @@ private fun assertTabTrayOverflowButton(visible: Boolean) = onView(withId(R.id.tab_tray_overflow)) .check(matches(withEffectiveVisibility(visibleOrGone(visible)))) +private fun assertTabTrayDoesExist() { + onView(withId(R.id.tab_wrapper)) + .check(matches(withEffectiveVisibility(ViewMatchers.Visibility.VISIBLE))) +} + private fun assertTabTrayDoesNotExist() { onView(withId(R.id.tab_wrapper)) .check(doesNotExist()) diff --git a/app/src/androidTest/java/org/mozilla/fenix/ui/robots/ThreeDotMenuBookmarksRobot.kt b/app/src/androidTest/java/org/mozilla/fenix/ui/robots/ThreeDotMenuBookmarksRobot.kt index 1173b6bec..2c13ba626 100644 --- a/app/src/androidTest/java/org/mozilla/fenix/ui/robots/ThreeDotMenuBookmarksRobot.kt +++ b/app/src/androidTest/java/org/mozilla/fenix/ui/robots/ThreeDotMenuBookmarksRobot.kt @@ -38,18 +38,18 @@ class ThreeDotMenuBookmarksRobot { return BookmarksRobot.Transition() } - fun clickOpenInNewTab(interact: BrowserRobot.() -> Unit): BrowserRobot.Transition { + fun clickOpenInNewTab(interact: TabDrawerRobot.() -> Unit): TabDrawerRobot.Transition { openInNewTabButton().click() - BrowserRobot().interact() - return BrowserRobot.Transition() + TabDrawerRobot().interact() + return TabDrawerRobot.Transition() } - fun clickOpenInPrivateTab(interact: BrowserRobot.() -> Unit): BrowserRobot.Transition { + fun clickOpenInPrivateTab(interact: TabDrawerRobot.() -> Unit): TabDrawerRobot.Transition { openInPrivateTabButton().click() - BrowserRobot().interact() - return BrowserRobot.Transition() + TabDrawerRobot().interact() + return TabDrawerRobot.Transition() } fun clickDelete(interact: BookmarksRobot.() -> Unit): BookmarksRobot.Transition { diff --git a/app/src/androidTest/java/org/mozilla/fenix/ui/robots/ThreeDotMenuHistoryItemRobot.kt b/app/src/androidTest/java/org/mozilla/fenix/ui/robots/ThreeDotMenuHistoryItemRobot.kt index cc44a1621..850a9cec9 100644 --- a/app/src/androidTest/java/org/mozilla/fenix/ui/robots/ThreeDotMenuHistoryItemRobot.kt +++ b/app/src/androidTest/java/org/mozilla/fenix/ui/robots/ThreeDotMenuHistoryItemRobot.kt @@ -41,16 +41,16 @@ class ThreeDotMenuHistoryItemRobot { return LibrarySubMenusMultipleSelectionToolbarRobot.Transition() } - fun clickOpenInNormalTab(interact: BrowserRobot.() -> Unit): BrowserRobot.Transition { + fun clickOpenInNormalTab(interact: TabDrawerRobot.() -> Unit): TabDrawerRobot.Transition { openInNewNormalTabButton().click() - BrowserRobot().interact() - return BrowserRobot.Transition() + TabDrawerRobot().interact() + return TabDrawerRobot.Transition() } - fun clickOpenInPrivateTab(interact: BrowserRobot.() -> Unit): BrowserRobot.Transition { + fun clickOpenInPrivateTab(interact: TabDrawerRobot.() -> Unit): TabDrawerRobot.Transition { openInNewPrivateTabButton().click() - BrowserRobot().interact() - return BrowserRobot.Transition() + TabDrawerRobot().interact() + return TabDrawerRobot.Transition() } fun clickDelete(interact: HistoryRobot.() -> Unit): HistoryRobot.Transition { diff --git a/app/src/debug/res/raw/initial_experiments.json b/app/src/debug/res/raw/initial_experiments.json new file mode 100644 index 000000000..fdff36028 --- /dev/null +++ b/app/src/debug/res/raw/initial_experiments.json @@ -0,0 +1,236 @@ +{ + "data": [{ + "slug": "feature-text-variables-validation-android", + "appId": "org.mozilla.fenix", + "appName": "fenix", + "channel": "nightly", + "branches": [{ + "slug": "control", + "ratio": 100, + "feature": { + "value": {}, + "enabled": true, + "featureId": "nimbus-validation" + } + }, + { + "slug": "a1", + "ratio": 0, + "feature": { + "value": { + "settings-title": "settings_title", + "settings-title-punctuation": "…" + }, + "enabled": true, + "featureId": "nimbus-validation" + } + }, + { + "slug": "a2", + "ratio": 0, + "feature": { + "value": { + "settings-title": "preferences_category_general", + "settings-title-punctuation": "!" + }, + "enabled": true, + "featureId": "nimbus-validation" + } + } + ], + "outcomes": [], + "arguments": {}, + "probeSets": [], + "startDate": null, + "targeting": "true", + "featureIds": [ + "nimbus-validation" + ], + "application": "org.mozilla.firefox_beta", + "bucketConfig": { + "count": 0, + "start": 0, + "total": 10000, + "namespace": "nimbus-validation-2", + "randomizationUnit": "nimbus_id" + }, + "schemaVersion": "1.5.0", + "userFacingName": "Nimbus Text Variables Validation", + "referenceBranch": "control", + "proposedDuration": 14, + "isEnrollmentPaused": false, + "proposedEnrollment": 7, + "userFacingDescription": "Demonstration experiment to make trivial visible changes to text in Settings", + "last_modified": 1621443780172 + }, + { + "slug": "feature-icon-variables-validation-android", + "appId": "org.mozilla.fenix", + "appName": "fenix", + "channel": "nightly", + "branches": [{ + "slug": "control", + "ratio": 100, + "feature": { + "value": {}, + "enabled": true, + "featureId": "nimbus-validation" + } + }, + { + "slug": "treatment", + "ratio": 0, + "feature": { + "value": { + "settings-title": "Fancy Settings", + "settings-icon": "ic_edit" + }, + "enabled": true, + "featureId": "nimbus-validation" + } + } + ], + "outcomes": [], + "arguments": {}, + "probeSets": [], + "startDate": null, + "targeting": "true", + "featureIds": [ + "nimbus-validation" + ], + "application": "org.mozilla.firefox_beta", + "bucketConfig": { + "count": 0, + "start": 0, + "total": 10000, + "namespace": "nimbus-validation-2", + "randomizationUnit": "nimbus_id" + }, + "schemaVersion": "1.5.0", + "userFacingName": "Nimbus Icon Variables Validation", + "referenceBranch": "control", + "proposedDuration": 14, + "isEnrollmentPaused": false, + "proposedEnrollment": 7, + "userFacingDescription": "Demonstration experiment to make trivial visible changes to icons in Settings", + "last_modified": 1621443780172 + }, + + { + "slug": "feature-text-variables-validation-ios", + "appId": "org.mozilla.ios.Fennec", + "appName": "firefox_ios", + "channel": "nightly", + "branches": [{ + "slug": "control", + "ratio": 100, + "feature": { + "value": {}, + "enabled": true, + "featureId": "nimbus-validation" + } + }, + { + "slug": "a1", + "ratio": 0, + "feature": { + "value": { + "settings-title": "Menu/Menu.OpenSettingsAction.Title", + "settings-title-punctuation": "…" + }, + "enabled": true, + "featureId": "nimbus-validation" + } + }, + { + "slug": "a2", + "ratio": 0, + "feature": { + "value": { + "settings-title": "Settings.General.SectionName", + "settings-title-punctuation": "!" + }, + "enabled": true, + "featureId": "nimbus-validation" + } + } + ], + "outcomes": [], + "arguments": {}, + "probeSets": [], + "startDate": null, + "targeting": "true", + "featureIds": [ + "nimbus-validation" + ], + "application": "org.mozilla.ios.Fennec", + "bucketConfig": { + "count": 0, + "start": 0, + "total": 10000, + "namespace": "nimbus-validation-2", + "randomizationUnit": "nimbus_id" + }, + "schemaVersion": "1.5.0", + "userFacingName": "Nimbus Text Variables Validation", + "referenceBranch": "control", + "proposedDuration": 14, + "isEnrollmentPaused": false, + "proposedEnrollment": 7, + "userFacingDescription": "Demonstration experiment to make trivial visible changes to text in Settings", + "last_modified": 1621443780172 + }, + { + "slug": "feature-icon-variables-validation-ios", + "appId": "org.mozilla.ios.Fennec", + "appName": "firefox_ios", + "channel": "nightly", + "branches": [{ + "slug": "control", + "ratio": 100, + "feature": { + "value": {}, + "enabled": true, + "featureId": "nimbus-validation" + } + }, + { + "slug": "treatment", + "ratio": 0, + "feature": { + "value": { + "settings-title": "Fancy Settings", + "settings-icon": "menu-ViewMobile" + }, + "enabled": true, + "featureId": "nimbus-validation" + } + } + ], + "outcomes": [], + "arguments": {}, + "probeSets": [], + "startDate": null, + "targeting": "true", + "featureIds": [ + "nimbus-validation" + ], + "application": "org.mozilla.ios.Fennec", + "bucketConfig": { + "count": 0, + "start": 0, + "total": 10000, + "namespace": "nimbus-validation-2", + "randomizationUnit": "nimbus_id" + }, + "schemaVersion": "1.5.0", + "userFacingName": "Nimbus Icon Variables Validation", + "referenceBranch": "control", + "proposedDuration": 14, + "isEnrollmentPaused": false, + "proposedEnrollment": 7, + "userFacingDescription": "Demonstration experiment to make trivial visible changes to icons in Settings", + "last_modified": 1621443780172 + } + ] +} diff --git a/app/src/debug/res/xml/shortcuts.xml b/app/src/debug/res/xml/shortcuts.xml index 1873a5af4..43b3ff7bd 100644 --- a/app/src/debug/res/xml/shortcuts.xml +++ b/app/src/debug/res/xml/shortcuts.xml @@ -26,4 +26,4 @@ android:targetPackage="org.mozilla.fenix.debug" android:targetClass="org.mozilla.fenix.IntentReceiverActivity" /> - \ No newline at end of file + diff --git a/app/src/geckoNightly/java/org/mozilla/fenix/engine/GeckoProvider.kt b/app/src/geckoNightly/java/org/mozilla/fenix/engine/GeckoProvider.kt deleted file mode 100644 index 9a1d2f8b1..000000000 --- a/app/src/geckoNightly/java/org/mozilla/fenix/engine/GeckoProvider.kt +++ /dev/null @@ -1,91 +0,0 @@ -/* 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/. */ - -import android.content.Context -import mozilla.components.browser.engine.gecko.autofill.GeckoLoginDelegateWrapper -import mozilla.components.browser.engine.gecko.ext.toContentBlockingSetting -import mozilla.components.browser.engine.gecko.glean.GeckoAdapter -import mozilla.components.concept.engine.EngineSession.TrackingProtectionPolicy -import mozilla.components.concept.storage.LoginsStorage -import mozilla.components.lib.crash.handler.CrashHandlerService -import mozilla.components.service.sync.logins.GeckoLoginStorageDelegate -import org.mozilla.fenix.Config -import org.mozilla.fenix.ext.components -import org.mozilla.geckoview.GeckoRuntime -import org.mozilla.geckoview.GeckoRuntimeSettings -import org.mozilla.geckoview.ContentBlocking -import org.mozilla.geckoview.ContentBlocking.SafeBrowsingProvider - -object GeckoProvider { - private var runtime: GeckoRuntime? = null - const val CN_UPDATE_URL = - "https://sb.firefox.com.cn/downloads?client=SAFEBROWSING_ID&appver=%MAJOR_VERSION%&pver=2.2" - const val CN_GET_HASH_URL = - "https://sb.firefox.com.cn/gethash?client=SAFEBROWSING_ID&appver=%MAJOR_VERSION%&pver=2.2" - - @Synchronized - fun getOrCreateRuntime( - context: Context, - storage: Lazy, - trackingProtectionPolicy: TrackingProtectionPolicy - ): GeckoRuntime { - if (runtime == null) { - runtime = createRuntime(context, storage, trackingProtectionPolicy) - } - - return runtime!! - } - - private fun createRuntime( - context: Context, - storage: Lazy, - policy: TrackingProtectionPolicy - ): GeckoRuntime { - val builder = GeckoRuntimeSettings.Builder() - - val runtimeSettings = builder - .crashHandler(CrashHandlerService::class.java) - .telemetryDelegate(GeckoAdapter()) - .contentBlocking(policy.toContentBlockingSetting()) - .debugLogging(Config.channel.isDebug) - .aboutConfigEnabled(true) - .build() - - val settings = context.components.settings - if (!settings.shouldUseAutoSize) { - runtimeSettings.automaticFontSizeAdjustment = false - val fontSize = settings.fontSizeFactor - runtimeSettings.fontSizeFactor = fontSize - } - - // Add safebrowsing providers for China - if (Config.channel.isMozillaOnline) { - val mozcn = SafeBrowsingProvider - .withName("mozcn") - .version("2.2") - .lists("m6eb-phish-shavar", "m6ib-phish-shavar") - .updateUrl(CN_UPDATE_URL) - .getHashUrl(CN_GET_HASH_URL) - .build() - - runtimeSettings.contentBlocking.setSafeBrowsingProviders(mozcn, - // Keep the existing configuration - ContentBlocking.GOOGLE_SAFE_BROWSING_PROVIDER, - ContentBlocking.GOOGLE_LEGACY_SAFE_BROWSING_PROVIDER) - - runtimeSettings.contentBlocking.setSafeBrowsingPhishingTable( - "m6eb-phish-shavar", - "m6ib-phish-shavar", - // Existing configuration - "goog-phish-proto") - } - - val geckoRuntime = GeckoRuntime.create(context, runtimeSettings) - val loginStorageDelegate = GeckoLoginStorageDelegate(storage) - @Suppress("Deprecation") - geckoRuntime.loginStorageDelegate = GeckoLoginDelegateWrapper(loginStorageDelegate) - - return geckoRuntime - } -} diff --git a/app/src/main/java/org/mozilla/fenix/FenixApplication.kt b/app/src/main/java/org/mozilla/fenix/FenixApplication.kt index a14b00e73..f613fac45 100644 --- a/app/src/main/java/org/mozilla/fenix/FenixApplication.kt +++ b/app/src/main/java/org/mozilla/fenix/FenixApplication.kt @@ -63,6 +63,17 @@ import org.mozilla.fenix.session.VisibilityLifecycleCallback import org.mozilla.fenix.telemetry.TelemetryLifecycleObserver import org.mozilla.fenix.utils.BrowsersCache import java.util.concurrent.TimeUnit +import mozilla.components.browser.state.store.BrowserStore +import mozilla.components.feature.search.ext.buildSearchUrl +import mozilla.components.feature.search.ext.waitForSelectedOrDefaultSearchEngine +import mozilla.components.service.fxa.manager.SyncEnginesStorage +import org.mozilla.fenix.GleanMetrics.Addons +import org.mozilla.fenix.GleanMetrics.Preferences +import org.mozilla.fenix.GleanMetrics.SearchDefaultEngine +import org.mozilla.fenix.components.metrics.Event +import org.mozilla.fenix.components.metrics.MozillaProductDetector +import org.mozilla.fenix.components.toolbar.ToolbarPosition +import org.mozilla.fenix.utils.Settings /** *The main application class for Fenix. Records data to measure initialization performance. @@ -130,13 +141,11 @@ open class FenixApplication : LocaleAwareApplication(), Provider { buildInfo = GleanBuildInfo.buildInfo ) - // Set this early to guarantee it's in every ping from here on. - Metrics.distributionId.set( - when (Config.channel.isMozillaOnline) { - true -> "MozillaOnline" - false -> "Mozilla" - } - ) + // We avoid blocking the main thread on startup by setting startup metrics on the background thread. + val store = components.core.store + GlobalScope.launch(Dispatchers.IO) { + setStartupMetrics(store, settings()) + } } @CallSuper @@ -167,7 +176,6 @@ open class FenixApplication : LocaleAwareApplication(), Provider { initializeWebExtensionSupport() restoreBrowserState() restoreDownloads() - restoreLocale() // Just to make sure it is impossible for any application-services pieces // to invoke parts of itself that require complete megazord initialization @@ -220,10 +228,6 @@ open class FenixApplication : LocaleAwareApplication(), Provider { components.useCases.downloadUseCases.restoreDownloads() } - private fun restoreLocale() { - components.useCases.localeUseCases.restore() - } - private fun initVisualCompletenessQueueAndQueueTasks() { val queue = components.performance.visualCompletenessQueue.queue @@ -239,6 +243,7 @@ open class FenixApplication : LocaleAwareApplication(), Provider { components.core.historyStorage.warmUp() components.core.bookmarksStorage.warmUp() components.core.passwordsStorage.warmUp() + components.core.autofillStorage.warmUp() } SecurePrefsTelemetry(this@FenixApplication, components.analytics.experiments).startTests() @@ -269,6 +274,14 @@ open class FenixApplication : LocaleAwareApplication(), Provider { } } + fun queueRestoreLocale() { + components.performance.visualCompletenessQueue.queue.runIfReadyOrQueue { + GlobalScope.launch(Dispatchers.IO) { + components.useCases.localeUseCases.restore() + } + } + } + initQueue() // We init these items in the visual completeness queue to avoid them initing in the critical @@ -276,6 +289,7 @@ open class FenixApplication : LocaleAwareApplication(), Provider { queueInitStorageAndServices() queueMetrics() queueReviewPrompt() + queueRestoreLocale() } private fun startMetricsIfEnabled() { @@ -514,6 +528,181 @@ open class FenixApplication : LocaleAwareApplication(), Provider { } } + /** + * This function is called right after Glean is initialized. Part of this function depends on + * shared preferences to be updated so the correct value is sent with the metrics ping. + * + * The reason we're using shared preferences to track these values is due to the limitations of + * the current metrics ping design. The values set here will be sent in every metrics ping even + * if these values have not changed since the last startup. + */ + @Suppress("ComplexMethod", "LongMethod") + @VisibleForTesting + internal fun setStartupMetrics( + browserStore: BrowserStore, + settings: Settings, + browsersCache: BrowsersCache = BrowsersCache, + mozillaProductDetector: MozillaProductDetector = MozillaProductDetector + ) { + setPreferenceMetrics(settings) + with(Metrics) { + // Set this early to guarantee it's in every ping from here on. + distributionId.set( + when (Config.channel.isMozillaOnline) { + true -> "MozillaOnline" + false -> "Mozilla" + } + ) + + defaultBrowser.set(browsersCache.all(applicationContext).isDefaultBrowser) + mozillaProductDetector.getMozillaBrowserDefault(applicationContext)?.also { + defaultMozBrowser.set(it) + } + + mozillaProducts.set(mozillaProductDetector.getInstalledMozillaProducts(applicationContext)) + + adjustCampaign.set(settings.adjustCampaignId) + adjustAdGroup.set(settings.adjustAdGroup) + adjustCreative.set(settings.adjustCreative) + adjustNetwork.set(settings.adjustNetwork) + + searchWidgetInstalled.set(settings.searchWidgetInstalled) + + val openTabsCount = settings.openTabsCount + hasOpenTabs.set(openTabsCount > 0) + if (openTabsCount > 0) { + tabsOpenCount.add(openTabsCount) + } + + val topSitesSize = settings.topSitesSize + hasTopSites.set(topSitesSize > 0) + if (topSitesSize > 0) { + topSitesCount.add(topSitesSize) + } + + if (settings.creditCardsSavedCount > 0) { + creditCardsSavedCount.add(settings.creditCardsSavedCount) + } + + if (settings.creditCardsDeletedCount > 0) { + creditCardsDeletedCount.add(settings.creditCardsDeletedCount) + } + + if (settings.creditCardsAutofilledCount > 0) { + creditCardsAutofillCount.add(settings.creditCardsAutofilledCount) + } + + val installedAddonSize = settings.installedAddonsCount + Addons.hasInstalledAddons.set(installedAddonSize > 0) + if (installedAddonSize > 0) { + Addons.installedAddons.set(settings.installedAddonsList.split(',')) + } + + val enabledAddonSize = settings.enabledAddonsCount + Addons.hasEnabledAddons.set(enabledAddonSize > 0) + if (enabledAddonSize > 0) { + Addons.enabledAddons.set(settings.enabledAddonsList.split(',')) + } + + val desktopBookmarksSize = settings.desktopBookmarksSize + hasDesktopBookmarks.set(desktopBookmarksSize > 0) + if (desktopBookmarksSize > 0) { + desktopBookmarksCount.add(desktopBookmarksSize) + } + + val mobileBookmarksSize = settings.mobileBookmarksSize + hasMobileBookmarks.set(mobileBookmarksSize > 0) + if (mobileBookmarksSize > 0) { + mobileBookmarksCount.add(mobileBookmarksSize) + } + + toolbarPosition.set( + when (settings.toolbarPosition) { + ToolbarPosition.BOTTOM -> Event.ToolbarPositionChanged.Position.BOTTOM.name + ToolbarPosition.TOP -> Event.ToolbarPositionChanged.Position.TOP.name + } + ) + + tabViewSetting.set(settings.getTabViewPingString()) + closeTabSetting.set(settings.getTabTimeoutPingString()) + } + + browserStore.waitForSelectedOrDefaultSearchEngine { searchEngine -> + if (searchEngine != null) { + SearchDefaultEngine.apply { + code.set(searchEngine.id) + name.set(searchEngine.name) + submissionUrl.set(searchEngine.buildSearchUrl("")) + } + } + } + } + + @Suppress("ComplexMethod") + private fun setPreferenceMetrics( + settings: Settings + ) { + with(Preferences) { + searchSuggestionsEnabled.set(settings.shouldShowSearchSuggestions) + remoteDebuggingEnabled.set(settings.isRemoteDebuggingEnabled) + telemetryEnabled.set(settings.isTelemetryEnabled) + browsingHistorySuggestion.set(settings.shouldShowHistorySuggestions) + bookmarksSuggestion.set(settings.shouldShowBookmarkSuggestions) + clipboardSuggestionsEnabled.set(settings.shouldShowClipboardSuggestions) + searchShortcutsEnabled.set(settings.shouldShowSearchShortcuts) + openLinksInPrivate.set(settings.openLinksInAPrivateTab) + privateSearchSuggestions.set(settings.shouldShowSearchSuggestionsInPrivate) + voiceSearchEnabled.set(settings.shouldShowVoiceSearch) + openLinksInAppEnabled.set(settings.openLinksInExternalApp) + signedInSync.set(settings.signedInFxaAccount) + + val syncedItems = SyncEnginesStorage(applicationContext).getStatus().entries.filter { + it.value + }.map { it.key.nativeName } + syncItems.set(syncedItems) + + toolbarPositionSetting.set( + when { + settings.shouldUseFixedTopToolbar -> "fixed_top" + settings.shouldUseBottomToolbar -> "bottom" + else -> "top" + } + ) + + enhancedTrackingProtection.set( + when { + !settings.shouldUseTrackingProtection -> "" + settings.useStandardTrackingProtection -> "standard" + settings.useStrictTrackingProtection -> "strict" + settings.useCustomTrackingProtection -> "custom" + else -> "" + } + ) + + val accessibilitySelection = mutableListOf() + + if (settings.switchServiceIsEnabled) { + accessibilitySelection.add("switch") + } + + if (settings.touchExplorationIsEnabled) { + accessibilitySelection.add("touch exploration") + } + + accessibilityServices.set(accessibilitySelection.toList()) + + userTheme.set( + when { + settings.shouldUseLightTheme -> "light" + settings.shouldUseDarkTheme -> "dark" + settings.shouldFollowDeviceTheme -> "system" + settings.shouldUseAutoBatteryTheme -> "battery" + else -> "" + } + ) + } + } + protected fun recordOnInit() { // This gets called by more than one process. Ideally we'd only run this in the main process // but the code to check which process we're in crashes because the Context isn't valid yet. diff --git a/app/src/main/java/org/mozilla/fenix/HomeActivity.kt b/app/src/main/java/org/mozilla/fenix/HomeActivity.kt index 1da6a183f..5317b9c2d 100644 --- a/app/src/main/java/org/mozilla/fenix/HomeActivity.kt +++ b/app/src/main/java/org/mozilla/fenix/HomeActivity.kt @@ -52,7 +52,6 @@ import mozilla.components.concept.storage.BookmarkNodeType import mozilla.components.feature.contextmenu.DefaultSelectionActionDelegate import mozilla.components.feature.privatemode.notification.PrivateNotificationFeature import mozilla.components.feature.search.BrowserStoreSearchAdapter -import mozilla.components.feature.search.ext.legacy import mozilla.components.service.fxa.sync.SyncReason import mozilla.components.support.base.feature.ActivityResultHandler import mozilla.components.support.base.feature.UserInteractionHandler @@ -83,6 +82,7 @@ import org.mozilla.fenix.ext.navigateBlockingForAsyncNavGraph import org.mozilla.fenix.ext.measureNoInline import org.mozilla.fenix.ext.metrics import org.mozilla.fenix.ext.nav +import org.mozilla.fenix.ext.setNavigationIcon import org.mozilla.fenix.ext.settings import org.mozilla.fenix.home.HomeFragmentDirections import org.mozilla.fenix.home.intent.CrashReporterIntentProcessor @@ -303,9 +303,12 @@ open class HomeActivity : LocaleAwareAppCompatActivity(), NavHostActivity { super.onResume() // Even if screenshots are allowed, we hide private content in the recents screen in onPause - // so onResume we should go back to setting these flags with the user screenshot setting + // only when we are in private mode, so in onResume we should go back to setting these flags + // with the user screenshot setting only when we are in private mode. // See https://github.com/mozilla-mobile/fenix/issues/11153 - updateSecureWindowFlags(settings().lastKnownMode) + if (settings().lastKnownMode == BrowsingMode.Private) { + updateSecureWindowFlags(settings().lastKnownMode) + } // Diagnostic breadcrumb for "Display already aquired" crash: // https://github.com/mozilla-mobile/android-components/issues/7960 @@ -373,6 +376,7 @@ open class HomeActivity : LocaleAwareAppCompatActivity(), NavHostActivity { components.core.store.state.getNormalOrPrivateTabs(private = false).isNotEmpty() // Even if screenshots are allowed, we want to hide private content in the recents screen + // only when we are in private mode // See https://github.com/mozilla-mobile/fenix/issues/11153 if (settings().lastKnownMode.isPrivate) { window.addFlags(FLAG_SECURE) @@ -719,6 +723,7 @@ open class HomeActivity : LocaleAwareAppCompatActivity(), NavHostActivity { setSupportActionBar(navigationToolbar) // Add ids to this that we don't want to have a toolbar back button setupNavigationToolbar() + setNavigationIcon(R.drawable.ic_back_button) isToolbarInflated = true } @@ -856,10 +861,10 @@ open class HomeActivity : LocaleAwareAppCompatActivity(), NavHostActivity { SessionState.Source.USER_ENTERED, true, mode.isPrivate, - searchEngine = engine.legacy() + searchEngine = engine ) } else { - components.useCases.searchUseCases.defaultSearch.invoke(searchTermOrURL, engine.legacy()) + components.useCases.searchUseCases.defaultSearch.invoke(searchTermOrURL, engine) } } diff --git a/app/src/main/java/org/mozilla/fenix/SecureFragment.kt b/app/src/main/java/org/mozilla/fenix/SecureFragment.kt new file mode 100644 index 000000000..24d2edf3c --- /dev/null +++ b/app/src/main/java/org/mozilla/fenix/SecureFragment.kt @@ -0,0 +1,34 @@ +/* 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 org.mozilla.fenix + +import android.os.Bundle +import androidx.annotation.LayoutRes +import androidx.fragment.app.Fragment +import org.mozilla.fenix.ext.removeSecure +import org.mozilla.fenix.ext.secure + +/** + * A [Fragment] implementation that can be used to secure screens displaying sensitive information + * by not allowing taking screenshots of their content. + * + * Fragments displaying such screens should extend [SecureFragment] instead of [Fragment] class. + */ +open class SecureFragment(@LayoutRes contentLayoutId: Int) : Fragment(contentLayoutId) { + + constructor() : this(0) { + Fragment() + } + + override fun onCreate(savedInstanceState: Bundle?) { + this.secure() + super.onCreate(savedInstanceState) + } + + override fun onDestroy() { + this.removeSecure() + super.onDestroy() + } +} diff --git a/app/src/main/java/org/mozilla/fenix/browser/BaseBrowserFragment.kt b/app/src/main/java/org/mozilla/fenix/browser/BaseBrowserFragment.kt index 0307b146a..6d6d4b7b2 100644 --- a/app/src/main/java/org/mozilla/fenix/browser/BaseBrowserFragment.kt +++ b/app/src/main/java/org/mozilla/fenix/browser/BaseBrowserFragment.kt @@ -4,11 +4,14 @@ package org.mozilla.fenix.browser +import android.app.KeyguardManager import android.content.Context +import android.content.DialogInterface import android.content.Intent import android.content.res.Configuration import android.os.Build import android.os.Bundle +import android.provider.Settings import android.view.Gravity import android.view.LayoutInflater import android.view.View @@ -16,8 +19,9 @@ import android.view.ViewGroup import android.view.accessibility.AccessibilityManager import androidx.annotation.CallSuper import androidx.annotation.VisibleForTesting +import androidx.appcompat.app.AlertDialog import androidx.coordinatorlayout.widget.CoordinatorLayout -import androidx.core.net.toUri +import androidx.core.content.getSystemService import androidx.core.view.isVisible import androidx.fragment.app.Fragment import androidx.fragment.app.activityViewModels @@ -65,6 +69,7 @@ import mozilla.components.feature.intent.ext.EXTRA_SESSION_ID import mozilla.components.feature.media.fullscreen.MediaSessionFullscreenFeature import mozilla.components.feature.privatemode.feature.SecureWindowFeature import mozilla.components.feature.prompts.PromptFeature +import mozilla.components.feature.prompts.PromptFeature.Companion.PIN_REQUEST import mozilla.components.feature.prompts.share.ShareDelegate import mozilla.components.feature.readerview.ReaderViewFeature import mozilla.components.feature.search.SearchFeature @@ -130,8 +135,11 @@ import mozilla.components.feature.webauthn.WebAuthnFeature import mozilla.components.support.base.feature.ActivityResultHandler import org.mozilla.fenix.ext.navigateBlockingForAsyncNavGraph import mozilla.components.support.ktx.android.view.enterToImmersiveMode +import mozilla.components.support.ktx.kotlin.getOrigin import org.mozilla.fenix.GleanMetrics.PerfStartup import org.mozilla.fenix.ext.measureNoInline +import org.mozilla.fenix.ext.secure +import org.mozilla.fenix.settings.biometric.BiometricPromptFeature import mozilla.components.feature.session.behavior.ToolbarPosition as MozacToolbarPosition /** @@ -180,6 +188,7 @@ abstract class BaseBrowserFragment : Fragment(), UserInteractionHandler, Activit ViewBoundFeatureWrapper() private val searchFeature = ViewBoundFeatureWrapper() private val webAuthnFeature = ViewBoundFeatureWrapper() + private val biometricPromptFeature = ViewBoundFeatureWrapper() private var pipFeature: PictureInPictureFeature? = null var customTabSessionId: String? = null @@ -533,6 +542,21 @@ abstract class BaseBrowserFragment : Fragment(), UserInteractionHandler, Activit view = view ) + biometricPromptFeature.set( + feature = BiometricPromptFeature( + context = context, + fragment = this, + onAuthFailure = { + promptsFeature.get()?.onBiometricResult(isAuthenticated = false) + }, + onAuthSuccess = { + promptsFeature.get()?.onBiometricResult(isAuthenticated = true) + } + ), + owner = this, + view = view + ) + promptsFeature.set( feature = PromptFeature( activity = activity, @@ -545,6 +569,9 @@ abstract class BaseBrowserFragment : Fragment(), UserInteractionHandler, Activit isSaveLoginEnabled = { context.settings().shouldPromptToSaveLogins }, + isCreditCardAutofillEnabled = { + context.settings().shouldAutofillCreditCardDetails + }, loginExceptionStorage = context.components.core.loginExceptionStorage, shareDelegate = object : ShareDelegate { override fun showShareSheet( @@ -571,6 +598,15 @@ abstract class BaseBrowserFragment : Fragment(), UserInteractionHandler, Activit NavGraphDirections.actionGlobalSavedLoginsAuthFragment() findNavController().navigateBlockingForAsyncNavGraph(directions) } + }, + creditCardPickerView = creditCardSelectBar, + onManageCreditCards = { + val directions = + NavGraphDirections.actionGlobalCreditCardsSettingFragment() + findNavController().navigateBlockingForAsyncNavGraph(directions) + }, + onSelectCreditCard = { + showBiometricPrompt(context) } ), owner = this, @@ -722,6 +758,66 @@ abstract class BaseBrowserFragment : Fragment(), UserInteractionHandler, Activit initializeEngineView(toolbarHeight) } + /** + * Shows a biometric prompt and fallback to prompting for the password. + */ + private fun showBiometricPrompt(context: Context) { + if (BiometricPromptFeature.canUseFeature(context)) { + biometricPromptFeature.get() + ?.requestAuthentication(getString(R.string.credit_cards_biometric_prompt_unlock_message)) + return + } + + // Fallback to prompting for password with the KeyguardManager + val manager = context.getSystemService() + if (manager?.isKeyguardSecure == true) { + showPinVerification(manager) + } else { + // Warn that the device has not been secured + if (context.settings().shouldShowSecurityPinWarning) { + showPinDialogWarning(context) + } else { + promptsFeature.get()?.onBiometricResult(isAuthenticated = true) + } + } + } + + /** + * Shows a pin request prompt. This is only used when BiometricPrompt is unavailable. + */ + @Suppress("Deprecation") + private fun showPinVerification(manager: KeyguardManager) { + val intent = manager.createConfirmDeviceCredentialIntent( + getString(R.string.credit_cards_biometric_prompt_message_pin), + getString(R.string.credit_cards_biometric_prompt_unlock_message) + ) + requireActivity().startActivityForResult(intent, PIN_REQUEST) + } + + /** + * Shows a dialog warning about setting up a device lock PIN. + */ + private fun showPinDialogWarning(context: Context) { + AlertDialog.Builder(context).apply { + setTitle(getString(R.string.credit_cards_warning_dialog_title)) + setMessage(getString(R.string.credit_cards_warning_dialog_message)) + + setNegativeButton(getString(R.string.credit_cards_warning_dialog_later)) { _: DialogInterface, _ -> + promptsFeature.get()?.onBiometricResult(isAuthenticated = false) + } + + setPositiveButton(getString(R.string.credit_cards_warning_dialog_set_up_now)) { it: DialogInterface, _ -> + it.dismiss() + promptsFeature.get()?.onBiometricResult(isAuthenticated = false) + startActivity(Intent(Settings.ACTION_SECURITY_SETTINGS)) + } + + create() + }.show().secure(activity) + + context.settings().incrementSecureWarningCount() + } + @VisibleForTesting internal fun expandToolbarOnNavigation(store: BrowserStore) { consumeFlow(store) { flow -> @@ -1089,9 +1185,9 @@ abstract class BaseBrowserFragment : Fragment(), UserInteractionHandler, Activit private fun showQuickSettingsDialog() { val tab = getCurrentTab() ?: return viewLifecycleOwner.lifecycleScope.launch(Main) { - val sitePermissions: SitePermissions? = tab.content.url.toUri().host?.let { host -> - val storage = requireComponents.core.permissionStorage - storage.findSitePermissionsBy(host) + val sitePermissions: SitePermissions? = tab.content.url.getOrigin()?.let { origin -> + val storage = requireComponents.core.permissionStorage + storage.findSitePermissionsBy(origin) } view?.let { diff --git a/app/src/main/java/org/mozilla/fenix/components/AbstractBinding.kt b/app/src/main/java/org/mozilla/fenix/components/AbstractBinding.kt deleted file mode 100644 index cdc9fc755..000000000 --- a/app/src/main/java/org/mozilla/fenix/components/AbstractBinding.kt +++ /dev/null @@ -1,43 +0,0 @@ -/* 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 org.mozilla.fenix.components - -import androidx.annotation.CallSuper -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.ExperimentalCoroutinesApi -import kotlinx.coroutines.cancel -import kotlinx.coroutines.flow.Flow -import mozilla.components.lib.state.Action -import mozilla.components.lib.state.State -import mozilla.components.lib.state.Store -import mozilla.components.lib.state.ext.flowScoped -import mozilla.components.support.base.feature.LifecycleAwareFeature - -/** - * Helper class for creating small binding classes that are responsible for reacting to state - * changes. - * - * Taken with ♥️ from Focus. - */ -abstract class AbstractBinding( - private val store: Store -) : LifecycleAwareFeature { - private var scope: CoroutineScope? = null - - @OptIn(ExperimentalCoroutinesApi::class) - @CallSuper - override fun start() { - scope = store.flowScoped { flow -> - onState(flow) - } - } - - @CallSuper - override fun stop() { - scope?.cancel() - } - - abstract suspend fun onState(flow: Flow) -} diff --git a/app/src/main/java/org/mozilla/fenix/components/Analytics.kt b/app/src/main/java/org/mozilla/fenix/components/Analytics.kt index dddf03456..d875dd63d 100644 --- a/app/src/main/java/org/mozilla/fenix/components/Analytics.kt +++ b/app/src/main/java/org/mozilla/fenix/components/Analytics.kt @@ -17,12 +17,14 @@ import mozilla.components.service.nimbus.NimbusApi import mozilla.components.service.nimbus.NimbusDisabled import org.mozilla.fenix.BuildConfig import org.mozilla.fenix.Config +import org.mozilla.fenix.FeatureFlags import org.mozilla.fenix.HomeActivity import org.mozilla.fenix.R import org.mozilla.fenix.ReleaseChannel import org.mozilla.fenix.components.metrics.AdjustMetricsService import org.mozilla.fenix.components.metrics.GleanMetricsService import org.mozilla.fenix.components.metrics.MetricController +import org.mozilla.fenix.experiments.createNimbus import org.mozilla.fenix.ext.components import org.mozilla.fenix.ext.settings import org.mozilla.fenix.perf.lazyMonitored @@ -90,7 +92,7 @@ class Analytics( val metrics: MetricController by lazyMonitored { MetricController.create( listOf( - GleanMetricsService(context, lazy { context.components.core.store }), + GleanMetricsService(context), AdjustMetricsService(context as Application) ), isDataTelemetryEnabled = { context.settings().isTelemetryEnabled }, @@ -100,8 +102,11 @@ class Analytics( } val experiments: NimbusApi by lazyMonitored { - // No experiments for Iceraven - NimbusDisabled() + if (FeatureFlags.nimbusExperiments) { + createNimbus(context, BuildConfig.NIMBUS_ENDPOINT) + } else { + NimbusDisabled() + } } } diff --git a/app/src/main/java/org/mozilla/fenix/components/BackgroundServices.kt b/app/src/main/java/org/mozilla/fenix/components/BackgroundServices.kt index eaa06cedf..d9cc58bad 100644 --- a/app/src/main/java/org/mozilla/fenix/components/BackgroundServices.kt +++ b/app/src/main/java/org/mozilla/fenix/components/BackgroundServices.kt @@ -32,9 +32,11 @@ import mozilla.components.service.fxa.manager.SCOPE_SESSION import mozilla.components.service.fxa.manager.SCOPE_SYNC import mozilla.components.service.fxa.manager.SyncEnginesStorage import mozilla.components.service.fxa.sync.GlobalSyncableStoreProvider +import mozilla.components.service.sync.autofill.AutofillCreditCardsAddressesStorage import mozilla.components.service.sync.logins.SyncableLoginsStorage import mozilla.components.support.utils.RunWhenReadyQueue import org.mozilla.fenix.Config +import org.mozilla.fenix.FeatureFlags import org.mozilla.fenix.R import org.mozilla.fenix.perf.StrictModeManager import org.mozilla.fenix.components.metrics.Event @@ -60,6 +62,7 @@ class BackgroundServices( bookmarkStorage: Lazy, passwordsStorage: Lazy, remoteTabsStorage: Lazy, + creditCardsStorage: Lazy, strictMode: StrictModeManager ) { // Allows executing tasks which depend on the account manager, but do not need to eagerly initialize it. @@ -91,16 +94,33 @@ class BackgroundServices( @VisibleForTesting val supportedEngines = - setOf(SyncEngine.History, SyncEngine.Bookmarks, SyncEngine.Passwords, SyncEngine.Tabs) - private val syncConfig = SyncConfig(supportedEngines, PeriodicSyncConfig(periodMinutes = 240)) // four hours + setOfNotNull( + SyncEngine.History, + SyncEngine.Bookmarks, + SyncEngine.Passwords, + SyncEngine.Tabs, + SyncEngine.CreditCards, + if (FeatureFlags.addressesFeature) SyncEngine.Addresses else null + ) + private val syncConfig = + SyncConfig(supportedEngines, PeriodicSyncConfig(periodMinutes = 240)) // four hours + + private val creditCardKeyProvider by lazyMonitored { creditCardsStorage.value.crypto } init { - /* Make the "history", "bookmark", "passwords", and "tabs" stores accessible to workers - spawned by the sync manager. */ + // Make the "history", "bookmark", "passwords", "tabs", "credit cards" stores + // accessible to workers spawned by the sync manager. GlobalSyncableStoreProvider.configureStore(SyncEngine.History to historyStorage) GlobalSyncableStoreProvider.configureStore(SyncEngine.Bookmarks to bookmarkStorage) GlobalSyncableStoreProvider.configureStore(SyncEngine.Passwords to passwordsStorage) GlobalSyncableStoreProvider.configureStore(SyncEngine.Tabs to remoteTabsStorage) + GlobalSyncableStoreProvider.configureStore( + storePair = SyncEngine.CreditCards to creditCardsStorage, + keyProvider = lazy { creditCardKeyProvider } + ) + if (FeatureFlags.addressesFeature) { + GlobalSyncableStoreProvider.configureStore(SyncEngine.Addresses to creditCardsStorage) + } } private val telemetryAccountObserver = TelemetryAccountObserver( @@ -188,6 +208,7 @@ internal class TelemetryAccountObserver( private val metricController: MetricController ) : AccountObserver { override fun onAuthenticated(account: OAuthAccount, authType: AuthType) { + settings.signedInFxaAccount = true when (authType) { // User signed-in into an existing FxA account. AuthType.Signin -> Event.SyncAuthSignIn @@ -220,5 +241,6 @@ internal class TelemetryAccountObserver( override fun onLoggedOut() { metricController.track(Event.SyncAuthSignOut) + settings.signedInFxaAccount = false } } diff --git a/app/src/main/java/org/mozilla/fenix/components/Components.kt b/app/src/main/java/org/mozilla/fenix/components/Components.kt index a9e973a3c..c0073fff9 100644 --- a/app/src/main/java/org/mozilla/fenix/components/Components.kt +++ b/app/src/main/java/org/mozilla/fenix/components/Components.kt @@ -23,6 +23,7 @@ import org.mozilla.fenix.BuildConfig import org.mozilla.fenix.Config import org.mozilla.fenix.HomeActivity import org.mozilla.fenix.R +import org.mozilla.fenix.autofill.AutofillConfirmActivity import org.mozilla.fenix.autofill.AutofillUnlockActivity import org.mozilla.fenix.components.metrics.AppStartupTelemetry import org.mozilla.fenix.ext.components @@ -58,6 +59,7 @@ class Components(private val context: Context) { core.lazyBookmarksStorage, core.lazyPasswordsStorage, core.lazyRemoteTabsStorage, + core.lazyAutofillStorage, strictMode ) } @@ -172,7 +174,7 @@ class Components(private val context: Context) { storage = core.passwordsStorage, publicSuffixList = publicSuffixList, unlockActivity = AutofillUnlockActivity::class.java, - confirmActivity = AutofillConfiguration::class.java, + confirmActivity = AutofillConfirmActivity::class.java, applicationName = context.getString(R.string.app_name), httpClient = core.client ) diff --git a/app/src/main/java/org/mozilla/fenix/components/Core.kt b/app/src/main/java/org/mozilla/fenix/components/Core.kt index 837d00ee4..c18624e34 100644 --- a/app/src/main/java/org/mozilla/fenix/components/Core.kt +++ b/app/src/main/java/org/mozilla/fenix/components/Core.kt @@ -4,7 +4,7 @@ package org.mozilla.fenix.components -import GeckoProvider +import org.mozilla.fenix.gecko.GeckoProvider import android.content.Context import android.content.res.Configuration import android.os.Build @@ -108,6 +108,7 @@ class Core( suspendMediaWhenInactive = false, forceUserScalableContent = context.settings().forceEnableZoom, loginAutofillEnabled = context.settings().shouldAutofillLogins, + enterpriseRootsEnabled = context.settings().allowThirdPartyRootCerts, clearColor = ContextCompat.getColor( context, R.color.foundation_normal_theme @@ -119,6 +120,7 @@ class Core( defaultSettings, GeckoProvider.getOrCreateRuntime( context, + lazyAutofillStorage, lazyPasswordsStorage, trackingProtectionPolicyFactory.createTrackingProtectionPolicy() ) @@ -154,6 +156,7 @@ class Core( context, GeckoProvider.getOrCreateRuntime( context, + lazyAutofillStorage, lazyPasswordsStorage, trackingProtectionPolicyFactory.createTrackingProtectionPolicy() ) @@ -291,7 +294,7 @@ class Core( val lazyHistoryStorage = lazyMonitored { PlacesHistoryStorage(context, crashReporter) } val lazyBookmarksStorage = lazyMonitored { PlacesBookmarksStorage(context) } val lazyPasswordsStorage = lazyMonitored { SyncableLoginsStorage(context, passwordsEncryptionKey) } - val lazyAutofillStorage = lazyMonitored { AutofillCreditCardsAddressesStorage(context) } + val lazyAutofillStorage = lazyMonitored { AutofillCreditCardsAddressesStorage(context, lazySecurePrefs) } /** * The storage component to sync and persist tabs in a Firefox Sync account. @@ -390,6 +393,7 @@ class Core( * Shared Preferences that encrypt/decrypt using Android KeyStore and lib-dataprotect for 23+ * only on Nightly/Debug for now, otherwise simply stored. * See https://github.com/mozilla-mobile/fenix/issues/8324 + * Also, this needs revision. See https://github.com/mozilla-mobile/fenix/issues/19155 */ private fun getSecureAbove22Preferences() = SecureAbove22Preferences( @@ -398,6 +402,9 @@ class Core( forceInsecure = !Config.channel.isNightlyOrDebug ) + // Temporary. See https://github.com/mozilla-mobile/fenix/issues/19155 + private val lazySecurePrefs = lazyMonitored { getSecureAbove22Preferences() } + private val passwordsEncryptionKey by lazyMonitored { getSecureAbove22Preferences().getString(PASSWORDS_KEY) ?: generateEncryptionKey(KEY_STRENGTH).also { diff --git a/app/src/main/java/org/mozilla/fenix/components/UseCases.kt b/app/src/main/java/org/mozilla/fenix/components/UseCases.kt index bd9a4fb21..849a3a973 100644 --- a/app/src/main/java/org/mozilla/fenix/components/UseCases.kt +++ b/app/src/main/java/org/mozilla/fenix/components/UseCases.kt @@ -15,7 +15,6 @@ import mozilla.components.feature.downloads.DownloadsUseCases import mozilla.components.feature.pwa.WebAppShortcutManager import mozilla.components.feature.pwa.WebAppUseCases import mozilla.components.feature.search.SearchUseCases -import mozilla.components.feature.search.ext.toDefaultSearchEngineProvider import mozilla.components.feature.session.SessionUseCases import mozilla.components.feature.session.SettingsUseCases import mozilla.components.feature.session.TrackingProtectionUseCases @@ -66,7 +65,6 @@ class UseCases( val searchUseCases by lazyMonitored { SearchUseCases( store, - store.toDefaultSearchEngineProvider(), tabsUseCases ) } diff --git a/app/src/main/java/org/mozilla/fenix/components/metrics/GleanMetricsService.kt b/app/src/main/java/org/mozilla/fenix/components/metrics/GleanMetricsService.kt index 7eb8ee48b..74f49ccfa 100644 --- a/app/src/main/java/org/mozilla/fenix/components/metrics/GleanMetricsService.kt +++ b/app/src/main/java/org/mozilla/fenix/components/metrics/GleanMetricsService.kt @@ -5,10 +5,6 @@ package org.mozilla.fenix.components.metrics import android.content.Context -import mozilla.components.browser.state.store.BrowserStore -import mozilla.components.feature.search.ext.legacy -import mozilla.components.feature.search.ext.waitForSelectedOrDefaultSearchEngine -import mozilla.components.service.fxa.manager.SyncEnginesStorage import mozilla.components.service.glean.Glean import mozilla.components.service.glean.private.NoExtraKeys import mozilla.components.support.base.log.logger.Logger @@ -46,12 +42,10 @@ import org.mozilla.fenix.GleanMetrics.Metrics import org.mozilla.fenix.GleanMetrics.Onboarding import org.mozilla.fenix.GleanMetrics.Pings import org.mozilla.fenix.GleanMetrics.Pocket -import org.mozilla.fenix.GleanMetrics.Preferences import org.mozilla.fenix.GleanMetrics.PrivateBrowsingMode import org.mozilla.fenix.GleanMetrics.PrivateBrowsingShortcut import org.mozilla.fenix.GleanMetrics.ProgressiveWebApp import org.mozilla.fenix.GleanMetrics.ReaderMode -import org.mozilla.fenix.GleanMetrics.SearchDefaultEngine import org.mozilla.fenix.GleanMetrics.SearchShortcuts import org.mozilla.fenix.GleanMetrics.SearchSuggestions import org.mozilla.fenix.GleanMetrics.SearchWidget @@ -70,11 +64,7 @@ import org.mozilla.fenix.GleanMetrics.TopSites import org.mozilla.fenix.GleanMetrics.TrackingProtection import org.mozilla.fenix.GleanMetrics.UserSpecifiedSearchEngines import org.mozilla.fenix.GleanMetrics.VoiceSearch -import org.mozilla.fenix.components.toolbar.ToolbarPosition import org.mozilla.fenix.ext.components -import org.mozilla.fenix.ext.settings -import org.mozilla.fenix.utils.BrowsersCache -import org.mozilla.fenix.utils.Settings private class EventWrapper>( private val recorder: ((Map?) -> Unit), @@ -855,11 +845,11 @@ private val Event.wrapper: EventWrapper<*>? is Event.SyncAuthFromSharedReuse, Event.SyncAuthFromSharedCopy -> null } +/** + * Service responsible for sending the activation and installation pings. + */ class GleanMetricsService( - private val context: Context, - private val store: Lazy, - private val browsersCache: BrowsersCache = BrowsersCache, - private val mozillaProductDetector: MozillaProductDetector = MozillaProductDetector + private val context: Context ) : MetricsService { override val type = MetricServiceType.Data @@ -887,181 +877,11 @@ class GleanMetricsService( // can handle events being recorded before it's initialized. Glean.registerPings(Pings) - // setStartupMetrics is not a fast function. It does not need to be done before we can consider - // ourselves initialized. So, let's do it, well, later. - setStartupMetrics(context.settings()) - } - } - - /** - * This function is called before the metrics ping is sent. Part of this function depends on - * shared preferences to be updated so the correct value is sent with the metrics ping. - * - * The reason we're using shared preferences to track some of these values is due to the - * limitations of the metrics ping. Events are only sent in a metrics ping if the user have made - * changes between each ping. However, in some cases we want current values to be sent even if - * the user have not changed anything between pings. - */ - internal fun setStartupMetrics(settings: Settings) { - setPreferenceMetrics() - with(Metrics) { - defaultBrowser.set(browsersCache.all(context).isDefaultBrowser) - mozillaProductDetector.getMozillaBrowserDefault(context)?.also { - defaultMozBrowser.set(it) - } - - mozillaProducts.set(mozillaProductDetector.getInstalledMozillaProducts(context)) - - adjustCampaign.set(settings.adjustCampaignId) - adjustAdGroup.set(settings.adjustAdGroup) - adjustCreative.set(settings.adjustCreative) - adjustNetwork.set(settings.adjustNetwork) - - searchWidgetInstalled.set(settings.searchWidgetInstalled) - - val openTabsCount = settings.openTabsCount - hasOpenTabs.set(openTabsCount > 0) - if (openTabsCount > 0) { - tabsOpenCount.add(openTabsCount) - } - - val topSitesSize = settings.topSitesSize - hasTopSites.set(topSitesSize > 0) - if (topSitesSize > 0) { - topSitesCount.add(topSitesSize) - } - - val installedAddonSize = settings.installedAddonsCount - Addons.hasInstalledAddons.set(installedAddonSize > 0) - if (installedAddonSize > 0) { - Addons.installedAddons.set(settings.installedAddonsList.split(',')) - } - - val enabledAddonSize = settings.enabledAddonsCount - Addons.hasEnabledAddons.set(enabledAddonSize > 0) - if (enabledAddonSize > 0) { - Addons.enabledAddons.set(settings.enabledAddonsList.split(',')) - } - - val desktopBookmarksSize = settings.desktopBookmarksSize - hasDesktopBookmarks.set(desktopBookmarksSize > 0) - if (desktopBookmarksSize > 0) { - desktopBookmarksCount.add(desktopBookmarksSize) - } - - val mobileBookmarksSize = settings.mobileBookmarksSize - hasMobileBookmarks.set(mobileBookmarksSize > 0) - if (mobileBookmarksSize > 0) { - mobileBookmarksCount.add(mobileBookmarksSize) - } - - toolbarPosition.set( - when (settings.toolbarPosition) { - ToolbarPosition.BOTTOM -> Event.ToolbarPositionChanged.Position.BOTTOM.name - ToolbarPosition.TOP -> Event.ToolbarPositionChanged.Position.TOP.name - } - ) - - tabViewSetting.set(settings.getTabViewPingString()) - closeTabSetting.set(settings.getTabTimeoutPingString()) - } - - store.value.waitForSelectedOrDefaultSearchEngine { searchEngine -> - if (searchEngine != null) { - SearchDefaultEngine.apply { - code.set(searchEngine.id) - name.set(searchEngine.name) - submissionUrl.set(searchEngine.legacy().buildSearchUrl("")) - } - } - activationPing.checkAndSend() installationPing.checkAndSend() } } - private fun setPreferenceMetrics() { - // We purposefully make all of our preferences the string_list format to make data analysis - // simpler. While it makes things like booleans a bit more complicated, it means all our - // preferences can be analyzed with the same dashboard and compared. - with(Preferences) { - showSearchSuggestions.set(context.settings().shouldShowSearchSuggestions.toStringList()) - remoteDebugging.set(context.settings().isRemoteDebuggingEnabled.toStringList()) - telemetry.set(context.settings().isTelemetryEnabled.toStringList()) - searchBrowsingHistory.set(context.settings().shouldShowHistorySuggestions.toStringList()) - searchBookmarks.set(context.settings().shouldShowBookmarkSuggestions.toStringList()) - showClipboardSuggestions.set(context.settings().shouldShowClipboardSuggestions.toStringList()) - showSearchShortcuts.set(context.settings().shouldShowSearchShortcuts.toStringList()) - openLinksInAPrivateTab.set(context.settings().openLinksInAPrivateTab.toStringList()) - searchSuggestionsPrivate.set(context.settings().shouldShowSearchSuggestionsInPrivate.toStringList()) - showVoiceSearch.set(context.settings().shouldShowVoiceSearch.toStringList()) - openLinksInApp.set(context.settings().openLinksInExternalApp.toStringList()) - - val isLoggedIn = - context.components.backgroundServices.accountManager.accountProfile() != null - sync.set(isLoggedIn.toStringList()) - - val syncedItems = SyncEnginesStorage(context).getStatus().entries.filter { - it.value - }.map { it.key.nativeName } - - syncItems.set(syncedItems) - - val toolbarPositionSelection = - if (context.settings().shouldUseFixedTopToolbar) { - "fixed_top" - } else if (context.settings().shouldUseBottomToolbar) { - "bottom" - } else { - "top" - } - - toolbarPosition.set(listOf(toolbarPositionSelection)) - - val etpSelection = - if (!context.settings().shouldUseTrackingProtection) { - "" - } else if (context.settings().useStandardTrackingProtection) { - "standard" - } else if (context.settings().useStrictTrackingProtection) { - "strict" - } else if (context.settings().useCustomTrackingProtection) { - "custom" - } else { - "" - } - - trackingProtection.set(listOf(etpSelection)) - - val accessibilitySelection = mutableListOf() - - if (context.settings().switchServiceIsEnabled) { - accessibilitySelection.add("switch") - } - - if (context.settings().touchExplorationIsEnabled) { - accessibilitySelection.add("touch exploration") - } - - accessibilityServices.set(accessibilitySelection.toList()) - - val themeSelection = - if (context.settings().shouldUseLightTheme) { - "light" - } else if (context.settings().shouldUseDarkTheme) { - "dark" - } else if (context.settings().shouldFollowDeviceTheme) { - "system" - } else if (context.settings().shouldUseAutoBatteryTheme) { - "battery" - } else { - "" - } - - theme.set(listOf(themeSelection)) - } - } - override fun stop() { Glean.setUploadEnabled(false) } diff --git a/app/src/main/java/org/mozilla/fenix/components/metrics/MetricController.kt b/app/src/main/java/org/mozilla/fenix/components/metrics/MetricController.kt index f10182b46..c38ebb62d 100644 --- a/app/src/main/java/org/mozilla/fenix/components/metrics/MetricController.kt +++ b/app/src/main/java/org/mozilla/fenix/components/metrics/MetricController.kt @@ -20,7 +20,8 @@ import mozilla.components.feature.customtabs.CustomTabsFacts import mozilla.components.feature.downloads.facts.DownloadsFacts import mozilla.components.feature.findinpage.facts.FindInPageFacts import mozilla.components.feature.media.facts.MediaFacts -import mozilla.components.feature.prompts.dialog.LoginDialogFacts +import mozilla.components.feature.prompts.facts.LoginDialogFacts +import mozilla.components.feature.prompts.facts.CreditCardAutofillDialogFacts import mozilla.components.feature.pwa.ProgressiveWebAppFacts import mozilla.components.feature.syncedtabs.facts.SyncedTabsFacts import mozilla.components.feature.top.sites.facts.TopSitesFacts @@ -161,6 +162,10 @@ internal class ReleaseMetricController( Component.FEATURE_PROMPTS to LoginDialogFacts.Items.CANCEL -> Event.LoginDialogPromptCancelled Component.FEATURE_PROMPTS to LoginDialogFacts.Items.NEVER_SAVE -> Event.LoginDialogPromptNeverSave Component.FEATURE_PROMPTS to LoginDialogFacts.Items.SAVE -> Event.LoginDialogPromptSave + Component.FEATURE_PROMPTS to CreditCardAutofillDialogFacts.Items.AUTOFILL_CREDIT_CARD_SUCCESS -> { + settings.creditCardsAutofilledCount += 1 + null + } Component.FEATURE_FINDINPAGE to FindInPageFacts.Items.CLOSE -> Event.FindInPageClosed Component.FEATURE_FINDINPAGE to FindInPageFacts.Items.INPUT -> Event.FindInPageSearchCommitted @@ -223,7 +228,7 @@ internal class ReleaseMetricController( metadata?.get("enabled")?.let { enabledAddons -> if (enabledAddons is List<*>) { settings.enabledAddonsCount = enabledAddons.size - settings.enabledAddonsList = enabledAddons.joinToString() + settings.enabledAddonsList = enabledAddons.joinToString(",") } } diff --git a/app/src/main/java/org/mozilla/fenix/components/metrics/SecurePrefsTelemetry.kt b/app/src/main/java/org/mozilla/fenix/components/metrics/SecurePrefsTelemetry.kt index 47a34497a..c88841f16 100644 --- a/app/src/main/java/org/mozilla/fenix/components/metrics/SecurePrefsTelemetry.kt +++ b/app/src/main/java/org/mozilla/fenix/components/metrics/SecurePrefsTelemetry.kt @@ -9,7 +9,7 @@ import android.os.Build import mozilla.components.lib.dataprotect.SecurePrefsReliabilityExperiment import mozilla.components.service.nimbus.NimbusApi import org.mozilla.fenix.experiments.ExperimentBranch -import org.mozilla.fenix.experiments.Experiments +import org.mozilla.fenix.experiments.FeatureId import org.mozilla.fenix.ext.withExperiment /** @@ -24,7 +24,7 @@ class SecurePrefsTelemetry( // The Android Keystore is used to secure the shared prefs only on API 23+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { // These tests should run only if the experiment is live - experiments.withExperiment(Experiments.ANDROID_KEYSTORE) { experimentBranch -> + experiments.withExperiment(FeatureId.ANDROID_KEYSTORE) { experimentBranch -> // .. and this device is not in the control group. if (experimentBranch == ExperimentBranch.TREATMENT) { SecurePrefsReliabilityExperiment(appContext)() diff --git a/app/src/main/java/org/mozilla/fenix/components/search/SearchMigration.kt b/app/src/main/java/org/mozilla/fenix/components/search/SearchMigration.kt index 9d421a82d..acd789d53 100644 --- a/app/src/main/java/org/mozilla/fenix/components/search/SearchMigration.kt +++ b/app/src/main/java/org/mozilla/fenix/components/search/SearchMigration.kt @@ -6,9 +6,8 @@ package org.mozilla.fenix.components.search import android.content.Context import android.content.SharedPreferences -import mozilla.components.browser.search.SearchEngineParser import mozilla.components.browser.state.search.SearchEngine -import mozilla.components.feature.search.ext.migrate +import mozilla.components.feature.search.ext.parseLegacySearchEngine import mozilla.components.feature.search.middleware.SearchMiddleware import org.mozilla.fenix.ext.components import org.xmlpull.v1.XmlPullParserException @@ -50,18 +49,17 @@ internal class SearchMigration( ): List { val ids = preferences.getStringSet(PREF_KEY_CUSTOM_SEARCH_ENGINES, emptySet()) ?: emptySet() - val parser = SearchEngineParser() - return ids.mapNotNull { id -> val xml = preferences.getString(id, null) - parser.loadSafely(id, xml?.byteInputStream()?.buffered()) + loadSafely(id, xml?.byteInputStream()?.buffered()) } } } -private fun SearchEngineParser.loadSafely(id: String, stream: BufferedInputStream?): SearchEngine? { +@Suppress("DEPRECATION") +private fun loadSafely(id: String, stream: BufferedInputStream?): SearchEngine? { return try { - stream?.let { load(id, it).migrate() } + stream?.let { parseLegacySearchEngine(id, it) } } catch (e: IOException) { null } catch (e: XmlPullParserException) { diff --git a/app/src/main/java/org/mozilla/fenix/components/toolbar/DefaultToolbarMenu.kt b/app/src/main/java/org/mozilla/fenix/components/toolbar/DefaultToolbarMenu.kt index a4b4737b8..0cf53913a 100644 --- a/app/src/main/java/org/mozilla/fenix/components/toolbar/DefaultToolbarMenu.kt +++ b/app/src/main/java/org/mozilla/fenix/components/toolbar/DefaultToolbarMenu.kt @@ -41,7 +41,7 @@ import org.mozilla.fenix.R import org.mozilla.fenix.browser.browsingmode.BrowsingMode import org.mozilla.fenix.components.accounts.FenixAccountManager import org.mozilla.fenix.experiments.ExperimentBranch -import org.mozilla.fenix.experiments.Experiments +import org.mozilla.fenix.experiments.FeatureId import org.mozilla.fenix.ext.asActivity import org.mozilla.fenix.ext.components import org.mozilla.fenix.ext.settings @@ -632,7 +632,7 @@ open class DefaultToolbarMenu( val experiments = context.components.analytics.experiments val browsers = BrowsersCache.all(context) - return experiments.withExperiment(Experiments.DEFAULT_BROWSER) { experimentBranch -> + return experiments.withExperiment(FeatureId.DEFAULT_BROWSER) { experimentBranch -> if (experimentBranch == ExperimentBranch.DEFAULT_BROWSER_TOOLBAR_MENU && !browsers.isFirefoxDefaultBrowser ) { diff --git a/app/src/main/java/org/mozilla/fenix/downloads/DynamicDownloadDialog.kt b/app/src/main/java/org/mozilla/fenix/downloads/DynamicDownloadDialog.kt index 8f2b4fa39..df3fd5513 100644 --- a/app/src/main/java/org/mozilla/fenix/downloads/DynamicDownloadDialog.kt +++ b/app/src/main/java/org/mozilla/fenix/downloads/DynamicDownloadDialog.kt @@ -106,9 +106,8 @@ class DynamicDownloadDialog( metrics.track(Event.DownloadsItemOpened) val fileWasOpened = AbstractFetchDownloadService.openFile( - context = context, - contentType = downloadState.contentType, - filePath = downloadState.filePath + applicationContext = context.applicationContext, + download = downloadState ) if (!fileWasOpened) { diff --git a/app/src/main/java/org/mozilla/fenix/experiments/Experiments.kt b/app/src/main/java/org/mozilla/fenix/experiments/Experiments.kt index 92808c5ff..6f83567f3 100644 --- a/app/src/main/java/org/mozilla/fenix/experiments/Experiments.kt +++ b/app/src/main/java/org/mozilla/fenix/experiments/Experiments.kt @@ -4,14 +4,23 @@ package org.mozilla.fenix.experiments -class Experiments { - companion object { - const val A_A_NIMBUS_VALIDATION = "fenix-nimbus-validation-v3" - const val ANDROID_KEYSTORE = "fenix-android-keystore" - const val DEFAULT_BROWSER = "fenix-default-browser" - } +/** + * Enums to identify features in the app. These will likely grow and shrink depending + * on the experiments we want to perform. + * + * @property jsonName the kebab-case version of the feature id as represented in the Nimbus + * experiment JSON. + */ +enum class FeatureId(val jsonName: String) { + NIMBUS_VALIDATION("nimbus-validation"), + ANDROID_KEYSTORE("fenix-android-keystore"), + DEFAULT_BROWSER("fenix-default-browser") } +/** + * Experiment branches are becoming less interesting, though we collect some well + * defined ones here. + */ class ExperimentBranch { companion object { const val TREATMENT = "treatment" diff --git a/app/src/main/java/org/mozilla/fenix/experiments/NimbusSetup.kt b/app/src/main/java/org/mozilla/fenix/experiments/NimbusSetup.kt index 4362056cc..9933439e7 100644 --- a/app/src/main/java/org/mozilla/fenix/experiments/NimbusSetup.kt +++ b/app/src/main/java/org/mozilla/fenix/experiments/NimbusSetup.kt @@ -15,6 +15,7 @@ import mozilla.components.service.nimbus.NimbusDisabled import mozilla.components.service.nimbus.NimbusServerSettings import mozilla.components.support.base.log.logger.Logger import org.mozilla.fenix.BuildConfig +import org.mozilla.fenix.R import org.mozilla.fenix.components.isSentryEnabled import org.mozilla.fenix.ext.components import org.mozilla.fenix.ext.settings @@ -66,6 +67,10 @@ fun createNimbus(context: Context, url: String?): NimbusApi = globalUserParticipation = enabled } + if (url.isNullOrBlank()) { + setExperimentsLocally(R.raw.initial_experiments) + } + // We may have downloaded experiments on a previous run, so let's start using them // now. We didn't do this earlier, so as to make getExperimentBranch and friends returns // the same thing throughout the session. This call does its work on the db thread. diff --git a/app/src/main/java/org/mozilla/fenix/ext/Activity.kt b/app/src/main/java/org/mozilla/fenix/ext/Activity.kt index 6469a4c88..f38afd406 100644 --- a/app/src/main/java/org/mozilla/fenix/ext/Activity.kt +++ b/app/src/main/java/org/mozilla/fenix/ext/Activity.kt @@ -12,9 +12,12 @@ import android.app.role.RoleManager import android.content.Intent import android.os.Build import android.provider.Settings +import androidx.annotation.DrawableRes +import androidx.appcompat.app.AppCompatActivity import androidx.core.os.bundleOf import org.mozilla.fenix.BrowserDirection import org.mozilla.fenix.HomeActivity +import org.mozilla.fenix.R import org.mozilla.fenix.settings.SupportUtils /** @@ -108,6 +111,20 @@ private fun Activity.navigateToDefaultBrowserAppsSettings() { } } +/** + * Sets the icon for the back (up) navigation button. + * @param icon The resource id of the icon. + */ +fun Activity.setNavigationIcon( + @DrawableRes icon: Int +) { + (this as? AppCompatActivity)?.supportActionBar?.let { + it.setDisplayHomeAsUpEnabled(true) + it.setHomeAsUpIndicator(icon) + it.setHomeActionContentDescription(R.string.action_bar_up_description) + } +} + const val REQUEST_CODE_BROWSER_ROLE = 1 const val SETTINGS_SELECT_OPTION_KEY = ":settings:fragment_args_key" const val SETTINGS_SHOW_FRAGMENT_ARGS = ":settings:show_fragment_args" diff --git a/app/src/main/java/org/mozilla/fenix/ext/Fragment.kt b/app/src/main/java/org/mozilla/fenix/ext/Fragment.kt index 1eb2cb27b..2d08a0bd8 100644 --- a/app/src/main/java/org/mozilla/fenix/ext/Fragment.kt +++ b/app/src/main/java/org/mozilla/fenix/ext/Fragment.kt @@ -4,6 +4,7 @@ package org.mozilla.fenix.ext +import android.view.WindowManager import androidx.annotation.IdRes import androidx.annotation.StringRes import androidx.appcompat.app.AppCompatActivity @@ -35,6 +36,7 @@ fun Fragment.getPreferenceKey(@StringRes resourceId: Int): String = getString(re */ fun Fragment.showToolbar(title: String) { (requireActivity() as AppCompatActivity).title = title + activity?.setNavigationIcon(R.drawable.ic_back_button) (activity as NavHostActivity).getSupportActionBarAndInflateIfNecessary().show() } @@ -58,15 +60,29 @@ fun Fragment.hideToolbar() { } /** - * Pops the backstack to force users to re-auth if they put the app in the background and return to it - * while being inside the saved logins flow - * - * Does nothing if the user is currently navigating to any of the [destinations] given as a parameter + * Pops the backstack to force users to re-auth if they put the app in the background and return to + * it while being inside a secured flow (e.g. logins or credit cards). * + * Does nothing if the user is currently navigating to any of the [destinations] given as a + * parameter. */ -fun Fragment.redirectToReAuth(destinations: List, currentDestination: Int?) { +fun Fragment.redirectToReAuth( + destinations: List, + currentDestination: Int?, + currentLocation: Int +) { if (currentDestination !in destinations) { - findNavController().popBackStack(R.id.savedLoginsAuthFragment, false) + when (currentLocation) { + R.id.loginDetailFragment, + R.id.editLoginFragment, + R.id.savedLoginsFragment -> { + findNavController().popBackStack(R.id.savedLoginsAuthFragment, false) + } + R.id.creditCardEditorFragment, + R.id.creditCardsManagementFragment -> { + findNavController().popBackStack(R.id.creditCardsSettingFragment, false) + } + } } } @@ -89,3 +105,21 @@ fun Fragment.breadcrumb( ) ) } + +/** + * Sets the [WindowManager.LayoutParams.FLAG_SECURE] flag for the current activity window. + */ +fun Fragment.secure() { + this.activity?.window?.addFlags( + WindowManager.LayoutParams.FLAG_SECURE + ) +} + +/** + * Clears the [WindowManager.LayoutParams.FLAG_SECURE] flag for the current activity window. + */ +fun Fragment.removeSecure() { + this.activity?.window?.clearFlags( + WindowManager.LayoutParams.FLAG_SECURE + ) +} diff --git a/app/src/main/java/org/mozilla/fenix/ext/Nimbus.kt b/app/src/main/java/org/mozilla/fenix/ext/Nimbus.kt index e1ab7fa39..a218be948 100644 --- a/app/src/main/java/org/mozilla/fenix/ext/Nimbus.kt +++ b/app/src/main/java/org/mozilla/fenix/ext/Nimbus.kt @@ -6,37 +6,105 @@ package org.mozilla.fenix.ext import mozilla.components.service.nimbus.NimbusApi import mozilla.components.support.base.log.logger.Logger -import org.mozilla.fenix.FeatureFlags +import org.mozilla.experiments.nimbus.Variables +import org.mozilla.fenix.experiments.FeatureId /** - * Gets the branch of the given `experimentId` and transforms it with given closure. + * Gets the branch name of an experiment acting on the feature given `featureId`, and transforms it + * with given closure. * - * If we're enrolled in the experiment, the transform is passed the branch id/slug as a `String`. + * You are probably looking for `withVariables`. + * + * If we're enrolled in an experiment, the transform is passed the branch id/slug as a `String`. * * If we're not enrolled in the experiment, or the experiment is not valid then the transform * is passed a `null`. */ +fun NimbusApi.withExperiment(featureId: FeatureId, transform: (String?) -> T): T { + return transform(withExperiment(featureId)) +} + +/** + * The synonym for [getExperimentBranch] to complement [withExperiment(String, (String?) -> T))]. + * + * Short-hand for ` org.mozilla.experiments.nimbus.NimbusApi.getExperimentBranch`. + */ @Suppress("TooGenericExceptionCaught") -fun NimbusApi.withExperiment(experimentId: String, transform: (String?) -> T): T { - val branch = if (FeatureFlags.nimbusExperiments) { - try { - getExperimentBranch(experimentId) - } catch (e: Throwable) { - Logger.error("Failed to getExperimentBranch($experimentId)", e) - null - } - } else { +fun NimbusApi.withExperiment(featureId: FeatureId) = + try { + getExperimentBranch(featureId.jsonName) + } catch (e: Throwable) { + Logger.error("Failed to getExperimentBranch(${featureId.jsonName})", e) null } - return transform(branch) -} /** - * The degenerate case of `withExperiment(String, (String?) -> T))`, with an identity transform. + * Get the variables needed to configure the feature given by `featureId`. + * + * @param featureId The feature id that identifies the feature under experiment. + * + * @param sendExposureEvent Passing `true` to this parameter will record the exposure event + * automatically if the client is enrolled in an experiment for the given [featureId]. + * Passing `false` here indicates that the application will manually record the exposure + * event by calling the `sendExposureEvent` function at the time of the exposure to the + * feature. + * + * See [sendExposureEvent] for more information on manually recording the event. + * + * @return a [Variables] object used to configure the feature. + */ +fun NimbusApi.getVariables(featureId: FeatureId, sendExposureEvent: Boolean = true) = + getVariables(featureId.jsonName, sendExposureEvent) + +/** + * A synonym for `getVariables(featureId, sendExposureEvent)`. + * + * This exists as a complement to the `withVariable(featureId, sendExposureEvent, transform)` method. * - * Short-hand for `mozilla.components.service.nimbus.NimbusApi.getExperimentBranch`. + * @param featureId the id of the feature as it appears in `Experimenter` + * @param sendExposureEvent by default `true`. This logs an event that the user was exposed to an experiment + * involving this feature. + * @return a `Variables` object providing typed accessors to a remotely configured JSON object. */ -fun NimbusApi.withExperiment(experimentId: String) = - this.withExperiment(experimentId, ::identity) +fun NimbusApi.withVariables(featureId: FeatureId, sendExposureEvent: Boolean = true) = + getVariables(featureId, sendExposureEvent) -private fun identity(value: T) = value +/** + * Get a `Variables` object for this feature and use that to configure the feature itself or a + * more type safe configuration object. + * + * @param featureId the id of the feature as it appears in `Experimenter` + * @param sendExposureEvent by default `true`. This logs an event that the user was exposed to an experiment + * involving this feature. + */ +fun NimbusApi.withVariables(featureId: FeatureId, sendExposureEvent: Boolean = true, transform: (Variables) -> T) = + transform(getVariables(featureId, sendExposureEvent)) + +/** + * Records the `exposure` event in telemetry. + * + * This is a manual function to accomplish the same purpose as passing `true` as the + * `sendExposureEvent` property of the `getVariables` function. It is intended to be used + * when requesting feature variables must occur at a different time than the actual user's + * exposure to the feature within the app. + * + * - Examples: + * - If the `Variables` are needed at a different time than when the exposure to the feature + * actually happens, such as constructing a menu happening at a different time than the + * user seeing the menu. + * - If `getVariables` is required to be called multiple times for the same feature and it is + * desired to only record the exposure once, such as if `getVariables` were called + * with every keystroke. + * + * In the case where the use of this function is required, then the `getVariables` function + * should be called with `false` so that the exposure event is not recorded when the variables + * are fetched. + * + * This function is safe to call even when there is no active experiment for the feature. The SDK + * will ensure that an event is only recorded for active experiments. + * + * @param featureId string representing the id of the feature for which to record the exposure + * event. + */ +fun NimbusApi.recordExposureEvent(featureId: FeatureId) = + recordExposureEvent(featureId.jsonName) diff --git a/app/src/geckoBeta/java/org/mozilla/fenix/engine/GeckoProvider.kt b/app/src/main/java/org/mozilla/fenix/gecko/GeckoProvider.kt similarity index 77% rename from app/src/geckoBeta/java/org/mozilla/fenix/engine/GeckoProvider.kt rename to app/src/main/java/org/mozilla/fenix/gecko/GeckoProvider.kt index 4fbd61291..efec1dc26 100644 --- a/app/src/geckoBeta/java/org/mozilla/fenix/engine/GeckoProvider.kt +++ b/app/src/main/java/org/mozilla/fenix/gecko/GeckoProvider.kt @@ -2,20 +2,25 @@ * 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 org.mozilla.fenix.gecko + import android.content.Context -import mozilla.components.browser.engine.gecko.autofill.GeckoLoginDelegateWrapper +import mozilla.components.browser.engine.gecko.autofill.GeckoAutocompleteStorageDelegate import mozilla.components.browser.engine.gecko.ext.toContentBlockingSetting import mozilla.components.browser.engine.gecko.glean.GeckoAdapter import mozilla.components.concept.engine.EngineSession.TrackingProtectionPolicy +import mozilla.components.concept.storage.CreditCardsAddressesStorage import mozilla.components.concept.storage.LoginsStorage import mozilla.components.lib.crash.handler.CrashHandlerService +import mozilla.components.service.sync.autofill.GeckoCreditCardsAddressesStorageDelegate import mozilla.components.service.sync.logins.GeckoLoginStorageDelegate import org.mozilla.fenix.Config import org.mozilla.fenix.ext.components +import org.mozilla.fenix.ext.settings import org.mozilla.geckoview.ContentBlocking +import org.mozilla.geckoview.ContentBlocking.SafeBrowsingProvider import org.mozilla.geckoview.GeckoRuntime import org.mozilla.geckoview.GeckoRuntimeSettings -import org.mozilla.geckoview.ContentBlocking.SafeBrowsingProvider object GeckoProvider { private var runtime: GeckoRuntime? = null @@ -27,11 +32,13 @@ object GeckoProvider { @Synchronized fun getOrCreateRuntime( context: Context, - storage: Lazy, + autofillStorage: Lazy, + loginStorage: Lazy, trackingProtectionPolicy: TrackingProtectionPolicy ): GeckoRuntime { if (runtime == null) { - runtime = createRuntime(context, storage, trackingProtectionPolicy) + runtime = + createRuntime(context, autofillStorage, loginStorage, trackingProtectionPolicy) } return runtime!! @@ -39,7 +46,8 @@ object GeckoProvider { private fun createRuntime( context: Context, - storage: Lazy, + autofillStorage: Lazy, + loginStorage: Lazy, policy: TrackingProtectionPolicy ): GeckoRuntime { val builder = GeckoRuntimeSettings.Builder() @@ -48,8 +56,8 @@ object GeckoProvider { .crashHandler(CrashHandlerService::class.java) .telemetryDelegate(GeckoAdapter()) .contentBlocking(policy.toContentBlockingSetting()) - .aboutConfigEnabled(true) .debugLogging(Config.channel.isDebug) + .aboutConfigEnabled(true) .build() val settings = context.components.settings @@ -82,9 +90,13 @@ object GeckoProvider { } val geckoRuntime = GeckoRuntime.create(context, runtimeSettings) - val loginStorageDelegate = GeckoLoginStorageDelegate(storage) - @Suppress("Deprecation") - geckoRuntime.loginStorageDelegate = GeckoLoginDelegateWrapper(loginStorageDelegate) + + geckoRuntime.autocompleteStorageDelegate = GeckoAutocompleteStorageDelegate( + GeckoCreditCardsAddressesStorageDelegate(autofillStorage) { + context.settings().shouldAutofillCreditCardDetails + }, + GeckoLoginStorageDelegate(loginStorage) + ) return geckoRuntime } diff --git a/app/src/main/java/org/mozilla/fenix/home/HomeMenu.kt b/app/src/main/java/org/mozilla/fenix/home/HomeMenu.kt index cf89bd2bb..4184f59db 100644 --- a/app/src/main/java/org/mozilla/fenix/home/HomeMenu.kt +++ b/app/src/main/java/org/mozilla/fenix/home/HomeMenu.kt @@ -27,11 +27,10 @@ import org.mozilla.fenix.FeatureFlags import org.mozilla.fenix.FeatureFlags.tabsTrayRewrite import org.mozilla.fenix.R import org.mozilla.fenix.components.accounts.FenixAccountManager -import org.mozilla.fenix.experiments.ExperimentBranch -import org.mozilla.fenix.experiments.Experiments +import org.mozilla.fenix.experiments.FeatureId import org.mozilla.fenix.ext.components +import org.mozilla.fenix.ext.getVariables import org.mozilla.fenix.ext.settings -import org.mozilla.fenix.ext.withExperiment import org.mozilla.fenix.theme.ThemeManager import org.mozilla.fenix.whatsnew.WhatsNew @@ -142,23 +141,9 @@ class HomeMenu( onItemTapped.invoke(Item.Bookmarks) } - // We want to validate that the Nimbus experiments library is working, from the android UI - // all the way back to the data science backend. We're not testing the user's preference - // or response, we're end-to-end testing the experiments platform. - // So here, we're running multiple identical branches with the same treatment, and if the - // user isn't targeted, then we get still get the same treatment. - // The `let` block is degenerate here, but left here so as to document the form of how experiments - // are implemented here. - val historyIcon = experiments.withExperiment(Experiments.A_A_NIMBUS_VALIDATION) { - when (it) { - ExperimentBranch.A1 -> R.drawable.ic_history - ExperimentBranch.A2 -> R.drawable.ic_history - else -> R.drawable.ic_history - } - } val historyItem = BrowserMenuImageText( context.getString(R.string.library_history), - historyIcon, + R.drawable.ic_history, primaryTextColor ) { onItemTapped.invoke(Item.History) @@ -172,9 +157,11 @@ class HomeMenu( onItemTapped.invoke(Item.Extensions) } + // Use nimbus to set the icon and title. + val variables = experiments.getVariables(FeatureId.NIMBUS_VALIDATION) val settingsItem = BrowserMenuImageText( - context.getString(R.string.browser_menu_settings), - R.drawable.ic_settings, + variables.getText("settings-title") ?: context.getString(R.string.browser_menu_settings), + variables.getDrawableResource("settings-icon") ?: R.drawable.ic_settings, primaryTextColor ) { onItemTapped.invoke(Item.Settings) @@ -252,23 +239,9 @@ class HomeMenu( onItemTapped.invoke(Item.Bookmarks) } - // We want to validate that the Nimbus experiments library is working, from the android UI - // all the way back to the data science backend. We're not testing the user's preference - // or response, we're end-to-end testing the experiments platform. - // So here, we're running multiple identical branches with the same treatment, and if the - // user isn't targeted, then we get still get the same treatment. - // The `let` block is degenerate here, but left here so as to document the form of how experiments - // are implemented here. - val historyIcon = experiments.withExperiment(Experiments.A_A_NIMBUS_VALIDATION) { - when (it) { - ExperimentBranch.A1 -> R.drawable.ic_history - ExperimentBranch.A2 -> R.drawable.ic_history - else -> R.drawable.ic_history - } - } val historyItem = BrowserMenuImageText( context.getString(R.string.library_history), - historyIcon, + R.drawable.ic_history, primaryTextColor ) { onItemTapped.invoke(Item.History) @@ -310,9 +283,11 @@ class HomeMenu( onItemTapped.invoke(Item.Help) } + // Use nimbus to set the icon and title. + val variables = experiments.getVariables(FeatureId.NIMBUS_VALIDATION) val settingsItem = BrowserMenuImageText( - context.getString(R.string.browser_menu_settings), - R.drawable.ic_settings, + variables.getText("settings-title") ?: context.getString(R.string.browser_menu_settings), + variables.getDrawableResource("settings-icon") ?: R.drawable.ic_settings, primaryTextColor ) { onItemTapped.invoke(Item.Settings) diff --git a/app/src/main/java/org/mozilla/fenix/home/sessioncontrol/viewholders/TopSitePagerViewHolder.kt b/app/src/main/java/org/mozilla/fenix/home/sessioncontrol/viewholders/TopSitePagerViewHolder.kt index 36ed91467..b77b4e232 100644 --- a/app/src/main/java/org/mozilla/fenix/home/sessioncontrol/viewholders/TopSitePagerViewHolder.kt +++ b/app/src/main/java/org/mozilla/fenix/home/sessioncontrol/viewholders/TopSitePagerViewHolder.kt @@ -45,6 +45,10 @@ class TopSitePagerViewHolder( view.top_sites_pager.apply { adapter = topSitesPagerAdapter registerOnPageChangeCallback(topSitesPageChangeCallback) + // Retain one more TopSites pages to ensure a new layout request will measure the first page also. + // Otherwise the second page with 3 TopSites will have the entire ViewPager only show + // the first row of TopSites, hiding half of those shown on the first page. + offscreenPageLimit = 1 } } diff --git a/app/src/main/java/org/mozilla/fenix/home/sessioncontrol/viewholders/topsites/TopSiteItemViewHolder.kt b/app/src/main/java/org/mozilla/fenix/home/sessioncontrol/viewholders/topsites/TopSiteItemViewHolder.kt index 5ee55eb98..7ca0da2ca 100644 --- a/app/src/main/java/org/mozilla/fenix/home/sessioncontrol/viewholders/topsites/TopSiteItemViewHolder.kt +++ b/app/src/main/java/org/mozilla/fenix/home/sessioncontrol/viewholders/topsites/TopSiteItemViewHolder.kt @@ -11,6 +11,7 @@ import android.view.View import android.widget.PopupWindow import androidx.appcompat.content.res.AppCompatResources.getDrawable import kotlinx.android.synthetic.main.top_site_item.* +import kotlinx.android.synthetic.main.top_site_item.view.* import mozilla.components.browser.menu.BrowserMenuBuilder import mozilla.components.browser.menu.item.SimpleBrowserMenuItem import mozilla.components.feature.top.sites.TopSite @@ -64,10 +65,11 @@ class TopSiteItemViewHolder( fun bind(topSite: TopSite) { top_site_title.text = topSite.title - pin_indicator.visibility = if (topSite.type == PINNED || topSite.type == DEFAULT) { - View.VISIBLE + if (topSite.type == PINNED || topSite.type == DEFAULT) { + val pinIndicator = getDrawable(itemView.context, R.drawable.ic_new_pin) + top_site_title.setCompoundDrawablesWithIntrinsicBounds(pinIndicator, null, null, null) } else { - View.GONE + top_site_title.setCompoundDrawablesWithIntrinsicBounds(null, null, null, null) } when (topSite.url) { @@ -91,6 +93,11 @@ class TopSiteItemViewHolder( this.topSite = topSite } + fun bind(topSitePayload: TopSitesAdapter.TopSitePayload) { + itemView.top_site_title.text = topSitePayload.newTitle + topSite = topSite.copy(title = topSitePayload.newTitle) + } + private fun onTouchEvent( v: View, event: MotionEvent, diff --git a/app/src/main/java/org/mozilla/fenix/home/sessioncontrol/viewholders/topsites/TopSitesAdapter.kt b/app/src/main/java/org/mozilla/fenix/home/sessioncontrol/viewholders/topsites/TopSitesAdapter.kt index 78bf438d0..551908699 100644 --- a/app/src/main/java/org/mozilla/fenix/home/sessioncontrol/viewholders/topsites/TopSitesAdapter.kt +++ b/app/src/main/java/org/mozilla/fenix/home/sessioncontrol/viewholders/topsites/TopSitesAdapter.kt @@ -40,7 +40,7 @@ class TopSitesAdapter( holder.bind((payloads[0] as TopSite)) } is TopSitePayload -> { - holder.itemView.top_site_title.text = (payloads[0] as TopSitePayload).newTitle + holder.bind(payloads[0] as TopSitePayload) } } } diff --git a/app/src/main/java/org/mozilla/fenix/home/sessioncontrol/viewholders/topsites/TopSitesPagerAdapter.kt b/app/src/main/java/org/mozilla/fenix/home/sessioncontrol/viewholders/topsites/TopSitesPagerAdapter.kt index c960dc69f..e60cc4cd6 100644 --- a/app/src/main/java/org/mozilla/fenix/home/sessioncontrol/viewholders/topsites/TopSitesPagerAdapter.kt +++ b/app/src/main/java/org/mozilla/fenix/home/sessioncontrol/viewholders/topsites/TopSitesPagerAdapter.kt @@ -12,6 +12,7 @@ import kotlinx.android.synthetic.main.component_top_sites.view.* import mozilla.components.feature.top.sites.TopSite import org.mozilla.fenix.home.sessioncontrol.AdapterItem import org.mozilla.fenix.home.sessioncontrol.TopSiteInteractor +import org.mozilla.fenix.home.sessioncontrol.viewholders.TopSitePagerViewHolder.Companion.TOP_SITES_PER_PAGE import org.mozilla.fenix.home.sessioncontrol.viewholders.TopSiteViewHolder class TopSitesPagerAdapter( @@ -36,7 +37,10 @@ class TopSitesPagerAdapter( val adapter = holder.itemView.top_sites_list.adapter as TopSitesAdapter val payload = payloads[0] as AdapterItem.TopSitePagerPayload for (item in payload.changed) { - adapter.notifyItemChanged(item.first, item.second) + adapter.notifyItemChanged( + item.first % TOP_SITES_PER_PAGE, + TopSitesAdapter.TopSitePayload(item.second.title) + ) } } } diff --git a/app/src/main/java/org/mozilla/fenix/library/LibraryPageView.kt b/app/src/main/java/org/mozilla/fenix/library/LibraryPageView.kt index 4d4adf6e3..183f62abf 100644 --- a/app/src/main/java/org/mozilla/fenix/library/LibraryPageView.kt +++ b/app/src/main/java/org/mozilla/fenix/library/LibraryPageView.kt @@ -44,5 +44,7 @@ open class LibraryPageView( activity?.title = title val toolbar = activity?.findViewById(R.id.navigationToolbar) toolbar?.setToolbarColors(foregroundColor, backgroundColor) + toolbar?.setNavigationIcon(R.drawable.ic_back_button) + toolbar?.navigationIcon?.setTint(foregroundColor) } } diff --git a/app/src/main/java/org/mozilla/fenix/library/bookmarks/BookmarkController.kt b/app/src/main/java/org/mozilla/fenix/library/bookmarks/BookmarkController.kt index 3dc18e26d..2f6950e22 100644 --- a/app/src/main/java/org/mozilla/fenix/library/bookmarks/BookmarkController.kt +++ b/app/src/main/java/org/mozilla/fenix/library/bookmarks/BookmarkController.kt @@ -14,6 +14,7 @@ import kotlinx.coroutines.launch import mozilla.appservices.places.BookmarkRoot import mozilla.components.concept.engine.prompt.ShareData import mozilla.components.concept.storage.BookmarkNode +import mozilla.components.feature.tabs.TabsUseCases import mozilla.components.service.fxa.sync.SyncReason import org.mozilla.fenix.BrowserDirection import org.mozilla.fenix.HomeActivity @@ -55,11 +56,13 @@ class DefaultBookmarkController( private val scope: CoroutineScope, private val store: BookmarkFragmentStore, private val sharedViewModel: BookmarksSharedViewModel, + private val tabsUseCases: TabsUseCases?, private val loadBookmarkNode: suspend (String) -> BookmarkNode?, private val showSnackbar: (String) -> Unit, private val deleteBookmarkNodes: (Set, Event) -> Unit, private val deleteBookmarkFolder: (Set) -> Unit, - private val invokePendingDeletion: () -> Unit + private val invokePendingDeletion: () -> Unit, + private val showTabTray: () -> Unit ) : BookmarkController { private val resources: Resources = activity.resources @@ -70,7 +73,7 @@ class DefaultBookmarkController( } override fun handleBookmarkTapped(item: BookmarkNode) { - openInNewTab(item.url!!, true, BrowserDirection.FromBookmarks, activity.browsingModeManager.mode) + openInNewTabAndShow(item.url!!, true, BrowserDirection.FromBookmarks, activity.browsingModeManager.mode) } override fun handleBookmarkExpand(folder: BookmarkNode) { @@ -126,7 +129,8 @@ class DefaultBookmarkController( } override fun handleOpeningBookmark(item: BookmarkNode, mode: BrowsingMode) { - openInNewTab(item.url!!, true, BrowserDirection.FromBookmarks, mode) + openInNewTab(item.url!!, mode) + showTabTray() } override fun handleBookmarkDeletion(nodes: Set, eventType: Event) { @@ -169,7 +173,7 @@ class DefaultBookmarkController( } } - private fun openInNewTab( + private fun openInNewTabAndShow( searchTermOrURL: String, newTab: Boolean, from: BrowserDirection, @@ -182,6 +186,18 @@ class DefaultBookmarkController( } } + private fun openInNewTab( + url: String, + mode: BrowsingMode + ) { + invokePendingDeletion.invoke() + activity.browsingModeManager.mode = BrowsingMode.fromBoolean(mode == BrowsingMode.Private) + tabsUseCases?.let { tabsUseCases -> + val addTab = if (mode == BrowsingMode.Private) tabsUseCases.addPrivateTab else tabsUseCases.addTab + addTab.invoke(url) + } + } + private fun navigateToGivenDirection(directions: NavDirections) { invokePendingDeletion.invoke() navController.nav(R.id.bookmarkFragment, directions) diff --git a/app/src/main/java/org/mozilla/fenix/library/bookmarks/BookmarkFragment.kt b/app/src/main/java/org/mozilla/fenix/library/bookmarks/BookmarkFragment.kt index 4b93a4f31..e7a1a8475 100644 --- a/app/src/main/java/org/mozilla/fenix/library/bookmarks/BookmarkFragment.kt +++ b/app/src/main/java/org/mozilla/fenix/library/bookmarks/BookmarkFragment.kt @@ -92,11 +92,13 @@ class BookmarkFragment : LibraryPageFragment(), UserInteractionHan scope = viewLifecycleOwner.lifecycleScope, store = bookmarkStore, sharedViewModel = sharedViewModel, + tabsUseCases = activity?.components?.useCases?.tabsUseCases, loadBookmarkNode = ::loadBookmarkNode, showSnackbar = ::showSnackBarWithText, deleteBookmarkNodes = ::deleteMulti, deleteBookmarkFolder = ::showRemoveFolderDialog, - invokePendingDeletion = ::invokePendingDeletion + invokePendingDeletion = ::invokePendingDeletion, + showTabTray = ::showTabTray ), metrics = metrics!! ) @@ -243,7 +245,7 @@ class BookmarkFragment : LibraryPageFragment(), UserInteractionHan private fun showTabTray() { invokePendingDeletion() - navigateToBookmarkFragment(BookmarkFragmentDirections.actionGlobalTabTrayDialogFragment()) + navigateToBookmarkFragment(BookmarkFragmentDirections.actionGlobalTabsTrayFragment()) } private fun navigateToBookmarkFragment(directions: NavDirections) { diff --git a/app/src/main/java/org/mozilla/fenix/library/downloads/DownloadFragment.kt b/app/src/main/java/org/mozilla/fenix/library/downloads/DownloadFragment.kt index f9687e8ad..2ce209b92 100644 --- a/app/src/main/java/org/mozilla/fenix/library/downloads/DownloadFragment.kt +++ b/app/src/main/java/org/mozilla/fenix/library/downloads/DownloadFragment.kt @@ -98,12 +98,13 @@ class DownloadFragment : LibraryPageFragment(), UserInteractionHan .sortedByDescending { it.createdTime } // sort from newest to oldest .map { DownloadItem( - it.id, - it.fileName, - it.filePath, - it.contentLength?.toString() ?: "0", - it.contentType, - it.status + id = it.id, + url = it.url, + fileName = it.fileName, + filePath = it.filePath, + size = it.contentLength?.toString() ?: "0", + contentType = it.contentType, + status = it.status ) }.filter { it.status == DownloadState.Status.COMPLETED @@ -249,10 +250,21 @@ class DownloadFragment : LibraryPageFragment(), UserInteractionHan mode?.let { (activity as HomeActivity).browsingModeManager.mode = it } context?.let { + val contentLength = if (item.size.isNotEmpty()) { + item.size.toLong() + } else { + 0L + } AbstractFetchDownloadService.openFile( - context = it, - contentType = item.contentType, - filePath = item.filePath + applicationContext = it.applicationContext, + download = DownloadState( + id = item.id, + url = item.url, + fileName = item.fileName, + contentType = item.contentType, + status = item.status, + contentLength = contentLength + ) ) } diff --git a/app/src/main/java/org/mozilla/fenix/library/downloads/DownloadFragmentStore.kt b/app/src/main/java/org/mozilla/fenix/library/downloads/DownloadFragmentStore.kt index a122262de..106009ec6 100644 --- a/app/src/main/java/org/mozilla/fenix/library/downloads/DownloadFragmentStore.kt +++ b/app/src/main/java/org/mozilla/fenix/library/downloads/DownloadFragmentStore.kt @@ -12,13 +12,16 @@ import mozilla.components.lib.state.Store /** * Class representing a downloads entry * @property id Unique id of the download item + * @property url The full url to the content that should be downloaded * @property fileName File name of the download item * @property filePath Full path of the download item * @property size The size in bytes of the download item * @property contentType The type of file the download is + * @property status The status that represents every state that a download can be in */ data class DownloadItem( val id: String, + val url: String, val fileName: String?, val filePath: String, val size: String, diff --git a/app/src/main/java/org/mozilla/fenix/library/history/HistoryController.kt b/app/src/main/java/org/mozilla/fenix/library/history/HistoryController.kt index 8d9114a43..41d734c8e 100644 --- a/app/src/main/java/org/mozilla/fenix/library/history/HistoryController.kt +++ b/app/src/main/java/org/mozilla/fenix/library/history/HistoryController.kt @@ -21,7 +21,8 @@ import org.mozilla.fenix.ext.navigateBlockingForAsyncNavGraph @Suppress("TooManyFunctions") interface HistoryController { - fun handleOpen(item: HistoryItem, mode: BrowsingMode? = null) + fun handleOpen(item: HistoryItem) + fun handleOpenInNewTab(item: HistoryItem, mode: BrowsingMode) fun handleSelect(item: HistoryItem) fun handleDeselect(item: HistoryItem) fun handleBackPressed(): Boolean @@ -42,15 +43,20 @@ class DefaultHistoryController( private val snackbar: FenixSnackbar, private val clipboardManager: ClipboardManager, private val scope: CoroutineScope, - private val openToBrowser: (item: HistoryItem, mode: BrowsingMode?) -> Unit, + private val openToBrowser: (item: HistoryItem) -> Unit, + private val openInNewTab: (item: HistoryItem, mode: BrowsingMode) -> Unit, private val displayDeleteAll: () -> Unit, private val invalidateOptionsMenu: () -> Unit, private val deleteHistoryItems: (Set) -> Unit, private val syncHistory: suspend () -> Unit, private val metrics: MetricController ) : HistoryController { - override fun handleOpen(item: HistoryItem, mode: BrowsingMode?) { - openToBrowser(item, mode) + override fun handleOpen(item: HistoryItem) { + openToBrowser(item) + } + + override fun handleOpenInNewTab(item: HistoryItem, mode: BrowsingMode) { + openInNewTab(item, mode) } override fun handleSelect(item: HistoryItem) { diff --git a/app/src/main/java/org/mozilla/fenix/library/history/HistoryFragment.kt b/app/src/main/java/org/mozilla/fenix/library/history/HistoryFragment.kt index 7d96b91b7..8eac22ccd 100644 --- a/app/src/main/java/org/mozilla/fenix/library/history/HistoryFragment.kt +++ b/app/src/main/java/org/mozilla/fenix/library/history/HistoryFragment.kt @@ -80,22 +80,23 @@ class HistoryFragment : LibraryPageFragment(), UserInteractionHandl ) } val historyController: HistoryController = DefaultHistoryController( - historyStore, - findNavController(), - resources, - FenixSnackbar.make( + store = historyStore, + navController = findNavController(), + resources = resources, + snackbar = FenixSnackbar.make( view = view, duration = FenixSnackbar.LENGTH_LONG, isDisplayedWithBrowserToolbar = false ), - activity?.getSystemService(CLIPBOARD_SERVICE) as ClipboardManager, - lifecycleScope, - ::openItem, - ::displayDeleteAllDialog, - ::invalidateOptionsMenu, - ::deleteHistoryItems, - ::syncHistory, - requireComponents.analytics.metrics + clipboardManager = activity?.getSystemService(CLIPBOARD_SERVICE) as ClipboardManager, + scope = lifecycleScope, + openToBrowser = ::openItem, + openInNewTab = ::openItemAndShowTray, + displayDeleteAll = ::displayDeleteAllDialog, + invalidateOptionsMenu = ::invalidateOptionsMenu, + deleteHistoryItems = ::deleteHistoryItems, + syncHistory = ::syncHistory, + metrics = requireComponents.analytics.metrics ) historyInteractor = HistoryInteractor( historyController @@ -104,6 +105,7 @@ class HistoryFragment : LibraryPageFragment(), UserInteractionHandl view.historyLayout, historyInteractor ) + showToolbar(getString(R.string.library_history)) return view } @@ -160,7 +162,6 @@ class HistoryFragment : LibraryPageFragment(), UserInteractionHandl override fun onResume() { super.onResume() - showToolbar(getString(R.string.library_history)) } override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) { @@ -216,7 +217,7 @@ class HistoryFragment : LibraryPageFragment(), UserInteractionHandl invokePendingDeletion() findNavController().nav( R.id.historyFragment, - HistoryFragmentDirections.actionGlobalTabTrayDialogFragment() + HistoryFragmentDirections.actionGlobalTabsTrayFragment() ) } @@ -247,14 +248,8 @@ class HistoryFragment : LibraryPageFragment(), UserInteractionHandl _historyView = null } - private fun openItem(item: HistoryItem, mode: BrowsingMode? = null) { - when (mode?.isPrivate) { - true -> requireComponents.analytics.metrics.track(Event.HistoryOpenedInPrivateTab) - false -> requireComponents.analytics.metrics.track(Event.HistoryOpenedInNewTab) - null -> requireComponents.analytics.metrics.track(Event.HistoryItemOpened) - } - - mode?.let { (activity as HomeActivity).browsingModeManager.mode = it } + private fun openItem(item: HistoryItem) { + requireComponents.analytics.metrics.track(Event.HistoryItemOpened) (activity as HomeActivity).openToBrowserAndLoad( searchTermOrURL = item.url, @@ -263,6 +258,22 @@ class HistoryFragment : LibraryPageFragment(), UserInteractionHandl ) } + private fun openItemAndShowTray(item: HistoryItem, mode: BrowsingMode) { + when (mode.isPrivate) { + true -> requireComponents.analytics.metrics.track(Event.HistoryOpenedInPrivateTab) + false -> requireComponents.analytics.metrics.track(Event.HistoryOpenedInNewTab) + } + + val homeActivity = activity as HomeActivity + homeActivity.browsingModeManager.mode = mode + homeActivity.components.useCases.tabsUseCases.let { tabsUseCases -> + val addTab = if (mode == BrowsingMode.Private) tabsUseCases.addPrivateTab else tabsUseCases.addTab + addTab.invoke(item.url) + } + + showTabTray() + } + private fun displayDeleteAllDialog() { activity?.let { activity -> AlertDialog.Builder(activity).apply { diff --git a/app/src/main/java/org/mozilla/fenix/library/history/HistoryInteractor.kt b/app/src/main/java/org/mozilla/fenix/library/history/HistoryInteractor.kt index 2c8b9056e..e7792e827 100644 --- a/app/src/main/java/org/mozilla/fenix/library/history/HistoryInteractor.kt +++ b/app/src/main/java/org/mozilla/fenix/library/history/HistoryInteractor.kt @@ -43,11 +43,11 @@ class HistoryInteractor( } override fun onOpenInNormalTab(item: HistoryItem) { - historyController.handleOpen(item, BrowsingMode.Normal) + historyController.handleOpenInNewTab(item, BrowsingMode.Normal) } override fun onOpenInPrivateTab(item: HistoryItem) { - historyController.handleOpen(item, BrowsingMode.Private) + historyController.handleOpenInNewTab(item, BrowsingMode.Private) } override fun onDeleteAll() { diff --git a/app/src/main/java/org/mozilla/fenix/nimbus/NimbusBranchesFragment.kt b/app/src/main/java/org/mozilla/fenix/nimbus/NimbusBranchesFragment.kt new file mode 100644 index 000000000..235b3f27b --- /dev/null +++ b/app/src/main/java/org/mozilla/fenix/nimbus/NimbusBranchesFragment.kt @@ -0,0 +1,94 @@ +/* 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 org.mozilla.fenix.nimbus + +import android.os.Bundle +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import androidx.fragment.app.Fragment +import androidx.lifecycle.lifecycleScope +import androidx.navigation.fragment.navArgs +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.launch +import mozilla.components.lib.state.ext.consumeFrom +import mozilla.components.support.base.log.logger.Logger +import org.mozilla.fenix.R +import org.mozilla.fenix.components.StoreProvider +import org.mozilla.fenix.ext.components +import org.mozilla.fenix.ext.showToolbar +import org.mozilla.fenix.nimbus.controller.NimbusBranchesController +import org.mozilla.fenix.nimbus.view.NimbusBranchesView + +/** + * A fragment to show the branches of a Nimbus experiment. + */ +@Suppress("TooGenericExceptionCaught") +class NimbusBranchesFragment : Fragment() { + + private lateinit var nimbusBranchesStore: NimbusBranchesStore + private lateinit var nimbusBranchesView: NimbusBranchesView + private lateinit var controller: NimbusBranchesController + + private val args by navArgs() + + override fun onCreateView( + inflater: LayoutInflater, + container: ViewGroup?, + savedInstanceState: Bundle? + ): View? { + val view = + inflater.inflate(R.layout.mozac_service_nimbus_experiment_details, container, false) + + nimbusBranchesStore = StoreProvider.get(this) { + NimbusBranchesStore(NimbusBranchesState(branches = emptyList())) + } + + controller = NimbusBranchesController( + nimbusBranchesStore = nimbusBranchesStore, + experiments = requireContext().components.analytics.experiments, + experimentId = args.experimentId + ) + + nimbusBranchesView = + NimbusBranchesView(view.findViewById(R.id.nimbus_experiment_branches_list), controller) + + loadExperimentBranches() + + return view + } + + @ExperimentalCoroutinesApi + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + consumeFrom(nimbusBranchesStore) { state -> + nimbusBranchesView.update(state) + } + } + + override fun onResume() { + super.onResume() + showToolbar(args.experimentName) + } + + private fun loadExperimentBranches() { + lifecycleScope.launch(Dispatchers.IO) { + try { + val experiments = requireContext().components.analytics.experiments + val branches = experiments.getExperimentBranches(args.experimentId) ?: emptyList() + val selectedBranch = experiments.getExperimentBranch(args.experimentId) ?: "" + + nimbusBranchesStore.dispatch( + NimbusBranchesAction.UpdateBranches( + branches, + selectedBranch + ) + ) + } catch (e: Throwable) { + Logger.error("Failed to getActiveExperiments()", e) + } + } + } +} diff --git a/app/src/main/java/org/mozilla/fenix/nimbus/NimbusBranchesStore.kt b/app/src/main/java/org/mozilla/fenix/nimbus/NimbusBranchesStore.kt new file mode 100644 index 000000000..c378686ff --- /dev/null +++ b/app/src/main/java/org/mozilla/fenix/nimbus/NimbusBranchesStore.kt @@ -0,0 +1,79 @@ +/* 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 org.mozilla.fenix.nimbus + +import mozilla.components.lib.state.Action +import mozilla.components.lib.state.State +import mozilla.components.lib.state.Store +import org.mozilla.experiments.nimbus.Branch + +/** + * The [Store] for holding the [NimbusBranchesState] and applying [NimbusBranchesAction]s. + */ +class NimbusBranchesStore(initialState: NimbusBranchesState) : + Store( + initialState, ::nimbusBranchesFragmentStateReducer + ) + +/** + * The state for [NimbusBranchesFragment]. + * + * @property branches The list of [Branch]s to display in the branches list. + * @property selectedBranch The selected [Branch] slug for a Nimbus experiment. + * @property isLoading True if the branches are still being loaded from storage, otherwise false. + */ +data class NimbusBranchesState( + val branches: List, + val selectedBranch: String = "", + val isLoading: Boolean = true +) : State + +/** + * Actions to dispatch through the [NimbusBranchesStore] to modify the [NimbusBranchesState] + * through the [nimbusBranchesFragmentStateReducer]. + */ +sealed class NimbusBranchesAction : Action { + /** + * Updates the list of Nimbus branches and selected branch. + * + * @param branches The list of [Branch]s to display in the branches list. + * @param selectedBranch The selected [Branch] slug for a Nimbus experiment. + */ + data class UpdateBranches(val branches: List, val selectedBranch: String) : + NimbusBranchesAction() + + /** + * Updates the selected branch. + * + * @param selectedBranch The selected [Branch] slug for a Nimbus experiment. + */ + data class UpdateSelectedBranch(val selectedBranch: String) : NimbusBranchesAction() +} + +/** + * Reduces the Nimbus branches state from the current state with the provided [action] to + * be performed. + * + * @param state The current Nimbus branches state. + * @param action The action to be performed on the state. + * @return the new [NimbusBranchesState] with the [action] executed. + */ +private fun nimbusBranchesFragmentStateReducer( + state: NimbusBranchesState, + action: NimbusBranchesAction +): NimbusBranchesState { + return when (action) { + is NimbusBranchesAction.UpdateBranches -> { + state.copy( + branches = action.branches, + selectedBranch = action.selectedBranch, + isLoading = false + ) + } + is NimbusBranchesAction.UpdateSelectedBranch -> { + state.copy(selectedBranch = action.selectedBranch) + } + } +} diff --git a/app/src/main/java/org/mozilla/fenix/nimbus/NimbusDetailsFragment.kt b/app/src/main/java/org/mozilla/fenix/nimbus/NimbusDetailsFragment.kt deleted file mode 100644 index 7caf576bd..000000000 --- a/app/src/main/java/org/mozilla/fenix/nimbus/NimbusDetailsFragment.kt +++ /dev/null @@ -1,59 +0,0 @@ -/* 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 org.mozilla.fenix.nimbus - -import android.os.Bundle -import android.view.View -import androidx.fragment.app.Fragment -import androidx.navigation.fragment.navArgs -import androidx.recyclerview.widget.LinearLayoutManager -import androidx.recyclerview.widget.RecyclerView -import mozilla.components.service.nimbus.ui.NimbusDetailAdapter -import org.mozilla.fenix.R -import org.mozilla.fenix.ext.showToolbar - -/** - * A fragment to show the details of a Nimbus experiment. - */ -class NimbusDetailsFragment : Fragment(R.layout.mozac_service_nimbus_experiment_details) { - - private val args by navArgs() - private var adapter: NimbusDetailAdapter? = null - - override fun onViewCreated(view: View, savedInstanceState: Bundle?) { - super.onViewCreated(view, savedInstanceState) - bindRecyclerView(view) - } - - override fun onResume() { - super.onResume() - showToolbar(args.experiment) - } - - override fun onDestroyView() { - super.onDestroyView() - // Letting go of the resources to avoid memory leak. - adapter = null - } - - private fun bindRecyclerView(view: View) { - val recyclerView = view.findViewById(R.id.nimbus_experiment_branches_list) - recyclerView.layoutManager = LinearLayoutManager(requireContext()) - - val shouldRefresh = adapter != null - - // Dummy data until we have the appropriate Nimbus API. - val branches = listOf( - "Control", - "Treatment" - ) - - if (!shouldRefresh) { - adapter = NimbusDetailAdapter(branches) - } - - recyclerView.adapter = adapter - } -} diff --git a/app/src/main/java/org/mozilla/fenix/nimbus/NimbusExperimentsFragment.kt b/app/src/main/java/org/mozilla/fenix/nimbus/NimbusExperimentsFragment.kt index 4a8ec904f..30820dac2 100644 --- a/app/src/main/java/org/mozilla/fenix/nimbus/NimbusExperimentsFragment.kt +++ b/app/src/main/java/org/mozilla/fenix/nimbus/NimbusExperimentsFragment.kt @@ -22,6 +22,7 @@ import org.mozilla.fenix.R import org.mozilla.fenix.ext.components import org.mozilla.fenix.ext.runIfFragmentIsAttached import org.mozilla.fenix.ext.showToolbar +import org.mozilla.fenix.nimbus.view.NimbusExperimentsView /** * Fragment use for managing Nimbus experiments. @@ -60,7 +61,7 @@ class NimbusExperimentsFragment : Fragment(R.layout.mozac_service_nimbus_experim lifecycleScope.launch(IO) { try { val experiments = - requireContext().components.analytics.experiments.getActiveExperiments() + requireContext().components.analytics.experiments.getAvailableExperiments() lifecycleScope.launch(Main) { runIfFragmentIsAttached { @@ -72,7 +73,7 @@ class NimbusExperimentsFragment : Fragment(R.layout.mozac_service_nimbus_experim } view.findViewById(R.id.nimbus_experiments_empty_message).isVisible = - false + experiments.isEmpty() recyclerView.adapter = adapter } } diff --git a/app/src/main/java/org/mozilla/fenix/nimbus/controller/NimbusBranchesController.kt b/app/src/main/java/org/mozilla/fenix/nimbus/controller/NimbusBranchesController.kt new file mode 100644 index 000000000..0916e26df --- /dev/null +++ b/app/src/main/java/org/mozilla/fenix/nimbus/controller/NimbusBranchesController.kt @@ -0,0 +1,32 @@ +/* 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 org.mozilla.fenix.nimbus.controller + +import mozilla.components.service.nimbus.NimbusApi +import mozilla.components.service.nimbus.ui.NimbusBranchesAdapterDelegate +import org.mozilla.experiments.nimbus.Branch +import org.mozilla.fenix.nimbus.NimbusBranchesAction +import org.mozilla.fenix.nimbus.NimbusBranchesStore + +/** + * [NimbusBranchesFragment] controller. This implements [NimbusBranchesAdapterDelegate] to handle + * interactions with a Nimbus branch item. + * + * @param nimbusBranchesStore An instance of [NimbusBranchesStore] for dispatching + * [NimbusBranchesAction]s. + * @param experiments An instance of [NimbusApi] for interacting with the Nimbus experiments. + * @param experimentId The string experiment-id or "slug" for a Nimbus experiment. + */ +class NimbusBranchesController( + private val nimbusBranchesStore: NimbusBranchesStore, + private val experiments: NimbusApi, + private val experimentId: String +) : NimbusBranchesAdapterDelegate { + + override fun onBranchItemClicked(branch: Branch) { + experiments.optInWithBranch(experimentId, branch.slug) + nimbusBranchesStore.dispatch(NimbusBranchesAction.UpdateSelectedBranch(branch.slug)) + } +} diff --git a/app/src/main/java/org/mozilla/fenix/nimbus/view/NimbusBranchesView.kt b/app/src/main/java/org/mozilla/fenix/nimbus/view/NimbusBranchesView.kt new file mode 100644 index 000000000..5fdb59137 --- /dev/null +++ b/app/src/main/java/org/mozilla/fenix/nimbus/view/NimbusBranchesView.kt @@ -0,0 +1,36 @@ +/* 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 org.mozilla.fenix.nimbus.view + +import android.view.ViewGroup +import androidx.recyclerview.widget.LinearLayoutManager +import androidx.recyclerview.widget.RecyclerView +import kotlinx.android.extensions.LayoutContainer +import mozilla.components.service.nimbus.ui.NimbusBranchAdapter +import org.mozilla.fenix.nimbus.NimbusBranchesState +import org.mozilla.fenix.nimbus.controller.NimbusBranchesController + +/** + * View used for managing a Nimbus experiment's branches. + */ +class NimbusBranchesView( + override val containerView: ViewGroup, + val controller: NimbusBranchesController +) : LayoutContainer { + + private val nimbusAdapter = NimbusBranchAdapter(controller) + + init { + val recyclerView: RecyclerView = containerView as RecyclerView + recyclerView.apply { + adapter = nimbusAdapter + layoutManager = LinearLayoutManager(containerView.context) + } + } + + fun update(state: NimbusBranchesState) { + nimbusAdapter.updateData(state.branches, state.selectedBranch) + } +} diff --git a/app/src/main/java/org/mozilla/fenix/nimbus/NimbusExperimentsView.kt b/app/src/main/java/org/mozilla/fenix/nimbus/view/NimbusExperimentsView.kt similarity index 65% rename from app/src/main/java/org/mozilla/fenix/nimbus/NimbusExperimentsView.kt rename to app/src/main/java/org/mozilla/fenix/nimbus/view/NimbusExperimentsView.kt index 1bc6e030f..643a0b3a8 100644 --- a/app/src/main/java/org/mozilla/fenix/nimbus/NimbusExperimentsView.kt +++ b/app/src/main/java/org/mozilla/fenix/nimbus/view/NimbusExperimentsView.kt @@ -2,12 +2,13 @@ * 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 org.mozilla.fenix.nimbus +package org.mozilla.fenix.nimbus.view import androidx.navigation.NavController import mozilla.components.service.nimbus.ui.NimbusExperimentsAdapterDelegate -import org.mozilla.experiments.nimbus.EnrolledExperiment +import org.mozilla.experiments.nimbus.AvailableExperiment import org.mozilla.fenix.ext.navigateBlockingForAsyncNavGraph +import org.mozilla.fenix.nimbus.NimbusExperimentsFragmentDirections /** * View used for managing Nimbus experiments. @@ -16,10 +17,11 @@ class NimbusExperimentsView( private val navController: NavController ) : NimbusExperimentsAdapterDelegate { - override fun onExperimentItemClicked(experiment: EnrolledExperiment) { + override fun onExperimentItemClicked(experiment: AvailableExperiment) { val directions = - NimbusExperimentsFragmentDirections.actionNimbusExperimentsFragmentToNimbusDetailsFragment( - experiment.userFacingName + NimbusExperimentsFragmentDirections.actionNimbusExperimentsFragmentToNimbusBranchesFragment( + experimentId = experiment.slug, + experimentName = experiment.userFacingName ) navController.navigateBlockingForAsyncNavGraph(directions) diff --git a/app/src/main/java/org/mozilla/fenix/perf/StartupTimelineStateMachine.kt b/app/src/main/java/org/mozilla/fenix/perf/StartupTimelineStateMachine.kt index 806b42768..85236cde2 100644 --- a/app/src/main/java/org/mozilla/fenix/perf/StartupTimelineStateMachine.kt +++ b/app/src/main/java/org/mozilla/fenix/perf/StartupTimelineStateMachine.kt @@ -25,8 +25,6 @@ object StartupTimelineStateMachine { * The states the application passes through during startup. We define these states to help us * better understand Android startup. Note that these states are not 100% correlated to the * cold/warm/hot states Google Play Vitals uses. - * - * TODO: link to extensive documentation on cold/warm/hot states when completed. */ sealed class StartupState { /** The state when the application is starting up but is not in memory. */ diff --git a/app/src/main/java/org/mozilla/fenix/search/SearchDialogFragment.kt b/app/src/main/java/org/mozilla/fenix/search/SearchDialogFragment.kt index 2f1296adf..99912d989 100644 --- a/app/src/main/java/org/mozilla/fenix/search/SearchDialogFragment.kt +++ b/app/src/main/java/org/mozilla/fenix/search/SearchDialogFragment.kt @@ -554,7 +554,7 @@ class SearchDialogFragment : AppCompatDialogFragment(), UserInteractionHandler { private fun updateClipboardSuggestion(searchState: SearchFragmentState, clipboardUrl: String?) { val shouldShowView = searchState.showClipboardSuggestions && searchState.query.isEmpty() && - !clipboardUrl.isNullOrEmpty() + !clipboardUrl.isNullOrEmpty() && !searchState.showSearchShortcuts fill_link_from_clipboard.isVisible = shouldShowView fill_link_divider.isVisible = shouldShowView diff --git a/app/src/main/java/org/mozilla/fenix/search/awesomebar/AwesomeBarView.kt b/app/src/main/java/org/mozilla/fenix/search/awesomebar/AwesomeBarView.kt index dee2033e5..0f0a0b5d6 100644 --- a/app/src/main/java/org/mozilla/fenix/search/awesomebar/AwesomeBarView.kt +++ b/app/src/main/java/org/mozilla/fenix/search/awesomebar/AwesomeBarView.kt @@ -9,7 +9,6 @@ import androidx.core.graphics.BlendModeColorFilterCompat.createBlendModeColorFil import androidx.core.graphics.BlendModeCompat.SRC_IN import androidx.core.graphics.drawable.toBitmap import mozilla.components.browser.awesomebar.BrowserAwesomeBar -import mozilla.components.browser.search.DefaultSearchEngineProvider import mozilla.components.browser.state.search.SearchEngine import mozilla.components.browser.state.state.searchEngines import mozilla.components.concept.awesomebar.AwesomeBar @@ -21,8 +20,6 @@ import mozilla.components.feature.awesomebar.provider.SearchEngineSuggestionProv import mozilla.components.feature.awesomebar.provider.SearchSuggestionProvider import mozilla.components.feature.awesomebar.provider.SessionSuggestionProvider import mozilla.components.feature.search.SearchUseCases -import mozilla.components.feature.search.ext.legacy -import mozilla.components.feature.search.ext.toDefaultSearchEngineProvider import mozilla.components.feature.session.SessionUseCases import mozilla.components.feature.syncedtabs.DeviceIndicators import mozilla.components.feature.syncedtabs.SyncedTabsStorageSuggestionProvider @@ -34,7 +31,6 @@ import org.mozilla.fenix.browser.browsingmode.BrowsingMode import org.mozilla.fenix.ext.components import org.mozilla.fenix.search.SearchEngineSource import org.mozilla.fenix.search.SearchFragmentState -import mozilla.components.browser.search.SearchEngine as LegacySearchEngine /** * View that contains and configures the BrowserAwesomeBar @@ -70,7 +66,7 @@ class AwesomeBarView( private val searchUseCase = object : SearchUseCases.SearchUseCase { override fun invoke( searchTerms: String, - searchEngine: mozilla.components.browser.search.SearchEngine?, + searchEngine: SearchEngine?, parentSessionId: String? ) { interactor.onSearchTermsTapped(searchTerms) @@ -80,7 +76,7 @@ class AwesomeBarView( private val shortcutSearchUseCase = object : SearchUseCases.SearchUseCase { override fun invoke( searchTerms: String, - searchEngine: mozilla.components.browser.search.SearchEngine?, + searchEngine: SearchEngine?, parentSessionId: String? ) { interactor.onSearchTermsTapped(searchTerms) @@ -151,7 +147,7 @@ class AwesomeBarView( defaultSearchSuggestionProvider = SearchSuggestionProvider( context = activity, - defaultSearchEngineProvider = components.core.store.toDefaultSearchEngineProvider(), + store = components.core.store, searchUseCase = searchUseCase, fetchClient = components.core.client, mode = SearchSuggestionProvider.Mode.MULTIPLE_SUGGESTIONS, @@ -168,7 +164,7 @@ class AwesomeBarView( defaultSearchActionProvider = SearchActionProvider( - defaultSearchEngineProvider = components.core.store.toDefaultSearchEngineProvider(), + store = components.core.store, searchUseCase = searchUseCase, icon = searchBitmap, showDescription = false @@ -330,17 +326,13 @@ class AwesomeBarView( listOf( SearchActionProvider( - defaultSearchEngineProvider = object : DefaultSearchEngineProvider { - override fun getDefaultSearchEngine(): LegacySearchEngine? = - engine.legacy() - override suspend fun retrieveDefaultSearchEngine(): LegacySearchEngine? = - engine.legacy() - }, + searchEngine = engine, + store = components.core.store, searchUseCase = shortcutSearchUseCase, icon = searchBitmap ), SearchSuggestionProvider( - engine.legacy(), + engine, shortcutSearchUseCase, components.core.client, limit = 3, diff --git a/app/src/main/java/org/mozilla/fenix/settings/SecretSettingsFragment.kt b/app/src/main/java/org/mozilla/fenix/settings/SecretSettingsFragment.kt index 4b965904b..f15dd9d45 100644 --- a/app/src/main/java/org/mozilla/fenix/settings/SecretSettingsFragment.kt +++ b/app/src/main/java/org/mozilla/fenix/settings/SecretSettingsFragment.kt @@ -5,10 +5,12 @@ package org.mozilla.fenix.settings import android.os.Bundle +import androidx.preference.Preference import androidx.preference.PreferenceFragmentCompat import androidx.preference.SwitchPreference import org.mozilla.fenix.FeatureFlags import org.mozilla.fenix.R +import org.mozilla.fenix.ext.components import org.mozilla.fenix.ext.settings import org.mozilla.fenix.ext.showToolbar @@ -28,16 +30,22 @@ class SecretSettingsFragment : PreferenceFragmentCompat() { onPreferenceChangeListener = SharedPreferenceUpdater() } - requirePreference(R.string.pref_key_show_credit_cards_feature).apply { - isVisible = FeatureFlags.creditCardsFeature - isChecked = context.settings().creditCardsFeature - onPreferenceChangeListener = SharedPreferenceUpdater() - } - requirePreference(R.string.pref_key_new_tabs_tray).apply { isVisible = FeatureFlags.tabsTrayRewrite isChecked = context.settings().tabsTrayRewrite onPreferenceChangeListener = SharedPreferenceUpdater() } + + requirePreference(R.string.pref_key_allow_third_party_root_certs).apply { + isVisible = true + isChecked = context.settings().allowThirdPartyRootCerts + onPreferenceChangeListener = object : SharedPreferenceUpdater() { + override fun onPreferenceChange(preference: Preference, newValue: Any?): Boolean { + context.components.core.engine.settings.enterpriseRootsEnabled = + newValue as Boolean + return super.onPreferenceChange(preference, newValue) + } + } + } } } diff --git a/app/src/main/java/org/mozilla/fenix/settings/SettingsFragment.kt b/app/src/main/java/org/mozilla/fenix/settings/SettingsFragment.kt index 518bc3f4f..af76d9945 100644 --- a/app/src/main/java/org/mozilla/fenix/settings/SettingsFragment.kt +++ b/app/src/main/java/org/mozilla/fenix/settings/SettingsFragment.kt @@ -37,11 +37,12 @@ import mozilla.components.concept.sync.Profile import mozilla.components.support.ktx.android.view.showKeyboard import org.mozilla.fenix.BrowserDirection import org.mozilla.fenix.Config +import org.mozilla.fenix.FeatureFlags import org.mozilla.fenix.HomeActivity import org.mozilla.fenix.R import org.mozilla.fenix.components.metrics.Event import org.mozilla.fenix.experiments.ExperimentBranch -import org.mozilla.fenix.experiments.Experiments +import org.mozilla.fenix.experiments.FeatureId import org.mozilla.fenix.ext.application import org.mozilla.fenix.ext.components import org.mozilla.fenix.ext.getPreferenceKey @@ -51,6 +52,7 @@ import org.mozilla.fenix.ext.navigateToNotificationsSettings import org.mozilla.fenix.ext.requireComponents import org.mozilla.fenix.ext.settings import org.mozilla.fenix.ext.REQUEST_CODE_BROWSER_ROLE +import org.mozilla.fenix.ext.getVariables import org.mozilla.fenix.ext.openSetDefaultBrowserOption import org.mozilla.fenix.ext.showToolbar import org.mozilla.fenix.ext.withExperiment @@ -160,7 +162,13 @@ class SettingsFragment : PreferenceFragmentCompat() { override fun onResume() { super.onResume() - showToolbar(getString(R.string.settings_title)) + // Use nimbus to set the title, and a trivial addition + val experiments = requireContext().components.analytics.experiments + val variables = experiments.getVariables(FeatureId.NIMBUS_VALIDATION) + val title = variables.getText("settings-title") ?: getString(R.string.settings_title) + val suffix = variables.getString("settings-title-punctuation") ?: "" + + showToolbar("$title$suffix") // Account UI state is updated as part of `onCreate`. To not do it twice in a row, we only // update it here if we're not going through the `onCreate->onStart->onResume` lifecycle chain. @@ -439,7 +447,7 @@ class SettingsFragment : PreferenceFragmentCompat() { with(requireContext().settings()) { findPreference( getPreferenceKey(R.string.pref_key_credit_cards) - )?.isVisible = creditCardsFeature + )?.isVisible = FeatureFlags.creditCardsFeature findPreference( getPreferenceKey(R.string.pref_key_nimbus_experiments) )?.isVisible = showSecretDebugMenuThisSession @@ -588,7 +596,7 @@ class SettingsFragment : PreferenceFragmentCompat() { private fun isDefaultBrowserExperimentBranch(): Boolean { val experiments = context?.components?.analytics?.experiments - return experiments?.withExperiment(Experiments.DEFAULT_BROWSER) { experimentBranch -> + return experiments?.withExperiment(FeatureId.DEFAULT_BROWSER) { experimentBranch -> (experimentBranch == ExperimentBranch.DEFAULT_BROWSER_SETTINGS_MENU) } == true } diff --git a/app/src/main/java/org/mozilla/fenix/settings/SyncPreference.kt b/app/src/main/java/org/mozilla/fenix/settings/SyncPreference.kt new file mode 100644 index 000000000..411936074 --- /dev/null +++ b/app/src/main/java/org/mozilla/fenix/settings/SyncPreference.kt @@ -0,0 +1,50 @@ +/* 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 org.mozilla.fenix.settings + +import android.content.Context +import android.util.AttributeSet +import android.view.View +import androidx.appcompat.widget.SwitchCompat +import androidx.preference.PreferenceViewHolder +import androidx.preference.SwitchPreferenceCompat +import org.mozilla.fenix.R + +/** + * Variation of [SwitchPreferenceCompat] that uses a custom widgetLayoutResource in order to implement + * visibility changes to it. + * */ +class SyncPreference @JvmOverloads constructor( + context: Context, + attrs: AttributeSet? = null +) : SwitchPreferenceCompat(context, attrs) { + + private var switchView: SwitchCompat? = null + + /** + * Whether or not switch's toggle widget is visible. + * */ + var isSwitchWidgetVisible: Boolean = false + + init { + widgetLayoutResource = R.layout.preference_sync + } + + /** + * Updates the switch state. + * */ + internal fun setSwitchCheckedState(isChecked: Boolean) { + switchView?.isChecked = isChecked + } + + override fun onBindViewHolder(holder: PreferenceViewHolder) { + super.onBindViewHolder(holder) + + switchView = holder.findViewById(R.id.switch_widget) as SwitchCompat? + + switchView?.isChecked = isChecked + switchView?.visibility = if (isSwitchWidgetVisible) View.VISIBLE else View.INVISIBLE + } +} diff --git a/app/src/main/java/org/mozilla/fenix/settings/SyncPreferenceView.kt b/app/src/main/java/org/mozilla/fenix/settings/SyncPreferenceView.kt index 578d1eea3..e117a1a11 100644 --- a/app/src/main/java/org/mozilla/fenix/settings/SyncPreferenceView.kt +++ b/app/src/main/java/org/mozilla/fenix/settings/SyncPreferenceView.kt @@ -5,7 +5,6 @@ package org.mozilla.fenix.settings import androidx.lifecycle.LifecycleOwner -import androidx.preference.Preference import kotlinx.coroutines.MainScope import kotlinx.coroutines.launch import mozilla.components.concept.sync.AccountObserver @@ -14,33 +13,33 @@ import mozilla.components.concept.sync.OAuthAccount import mozilla.components.service.fxa.SyncEngine import mozilla.components.service.fxa.manager.FxaAccountManager import mozilla.components.service.fxa.manager.SyncEnginesStorage -import org.mozilla.fenix.R /** * A view to help manage the sync preference in the "Logins and passwords" and "Credit cards" * settings. The provided [syncPreference] is used to navigate to the different fragments - * that manages the sync account authentication. A summary status will be also added + * that manages the sync account authentication. A toggle will be also added * depending on the sync account status. * - * @param syncPreference The sync [Preference] to update and handle navigation. + * @param syncPreference The sync [SyncPreference] to update and handle navigation. * @param lifecycleOwner View lifecycle owner used to determine when to cancel UI jobs. * @param accountManager An instance of [FxaAccountManager]. * @param syncEngine The sync engine that will be used for the sync status lookup. + * @param loggedOffTitle Text label for the setting when user is not logged in. + * @param loggedInTitle Text label for the setting when user is logged in. * @param onSignInToSyncClicked A callback executed when the [syncPreference] is clicked with a * preference status of "Sign in to Sync". - * @param onSyncStatusClicked A callback executed when the [syncPreference] is clicked with a - * preference status of "On" or "Off". * @param onReconnectClicked A callback executed when the [syncPreference] is clicked with a * preference status of "Reconnect". */ @Suppress("LongParameterList") class SyncPreferenceView( - private val syncPreference: Preference, + private val syncPreference: SyncPreference, lifecycleOwner: LifecycleOwner, accountManager: FxaAccountManager, private val syncEngine: SyncEngine, + private val loggedOffTitle: String, + private val loggedInTitle: String, private val onSignInToSyncClicked: () -> Unit = {}, - private val onSyncStatusClicked: () -> Unit = {}, private val onReconnectClicked: () -> Unit = {} ) { @@ -70,49 +69,54 @@ class SyncPreferenceView( } /** - * Shows the current status of the sync preference ("On"/"Off") for the logged in user. + * Shows a switch toggle for the sync preference when the user is logged in. */ private fun updateSyncPreferenceStatus() { syncPreference.apply { + isSwitchWidgetVisible = true + val syncEnginesStatus = SyncEnginesStorage(context).getStatus() - val loginsSyncStatus = syncEnginesStatus.getOrElse(syncEngine) { false } + val syncStatus = syncEnginesStatus.getOrElse(syncEngine) { false } - summary = context.getString( - if (loginsSyncStatus) R.string.preferences_passwords_sync_logins_on - else R.string.preferences_passwords_sync_logins_off - ) + title = loggedInTitle + isChecked = syncStatus - setOnPreferenceClickListener { - onSyncStatusClicked() + setOnPreferenceChangeListener { _, newValue -> + SyncEnginesStorage(context).setStatus(syncEngine, newValue as Boolean) + setSwitchCheckedState(newValue) true } } } /** - * Display that the user can "Sign in to Sync" when the user is logged off. + * Display that the user can sync across devices when the user is logged off. */ private fun updateSyncPreferenceNeedsLogin() { syncPreference.apply { - summary = context.getString(R.string.preferences_passwords_sync_logins_sign_in) + isSwitchWidgetVisible = false + + title = loggedOffTitle - setOnPreferenceClickListener { + setOnPreferenceChangeListener { _, _ -> onSignInToSyncClicked() - true + false } } } /** - * Displays that the user needs to "Reconnect" to fix their account problems with sync. + * Displays the logged off title to prompt the user to to re-authenticate their sync account. */ private fun updateSyncPreferenceNeedsReauth() { syncPreference.apply { - summary = context.getString(R.string.preferences_passwords_sync_logins_reconnect) + isSwitchWidgetVisible = false - setOnPreferenceClickListener { + title = loggedOffTitle + + setOnPreferenceChangeListener { _, _ -> onReconnectClicked() - true + false } } } diff --git a/app/src/main/java/org/mozilla/fenix/settings/about/AboutFragment.kt b/app/src/main/java/org/mozilla/fenix/settings/about/AboutFragment.kt index ba1d7a886..beb70564e 100644 --- a/app/src/main/java/org/mozilla/fenix/settings/about/AboutFragment.kt +++ b/app/src/main/java/org/mozilla/fenix/settings/about/AboutFragment.kt @@ -25,6 +25,7 @@ import org.mozilla.fenix.crashes.CrashListActivity import org.mozilla.fenix.ext.navigateBlockingForAsyncNavGraph import org.mozilla.fenix.ext.requireComponents import org.mozilla.fenix.ext.settings +import org.mozilla.fenix.ext.showToolbar import org.mozilla.fenix.settings.SupportUtils import org.mozilla.fenix.settings.about.AboutItemType.LICENSING_INFO import org.mozilla.fenix.settings.about.AboutItemType.PRIVACY_NOTICE @@ -53,7 +54,7 @@ class AboutFragment : Fragment(), AboutPageListener { appName = getString(R.string.app_name) headerAppName = if (Config.channel.isRelease) getString(R.string.daylight_app_name) else appName - activity?.title = getString(R.string.preferences_about, appName) + showToolbar(getString(R.string.preferences_about, appName)) return rootView } diff --git a/app/src/main/java/org/mozilla/fenix/settings/account/AccountSettingsFragment.kt b/app/src/main/java/org/mozilla/fenix/settings/account/AccountSettingsFragment.kt index 655d76e65..6c36b9ff8 100644 --- a/app/src/main/java/org/mozilla/fenix/settings/account/AccountSettingsFragment.kt +++ b/app/src/main/java/org/mozilla/fenix/settings/account/AccountSettingsFragment.kt @@ -35,6 +35,7 @@ import mozilla.components.service.fxa.sync.SyncReason import mozilla.components.service.fxa.sync.SyncStatusObserver import mozilla.components.service.fxa.sync.getLastSynced import mozilla.components.support.ktx.android.content.getColorFromAttr +import org.mozilla.fenix.FeatureFlags import org.mozilla.fenix.R import org.mozilla.fenix.components.FenixSnackbar import org.mozilla.fenix.components.StoreProvider @@ -164,44 +165,40 @@ class AccountSettingsFragment : PreferenceFragmentCompat() { updateSyncEngineStates() setDisabledWhileSyncing(accountManager.isSyncActive()) - fun updateSyncEngineState(context: Context, engine: SyncEngine, newState: Boolean) { - SyncEnginesStorage(context).setStatus(engine, newState) - viewLifecycleOwner.lifecycleScope.launch { - context.components.backgroundServices.accountManager.syncNow(SyncReason.EngineChange) - } - } - fun SyncEngine.prefId(): Int = when (this) { SyncEngine.History -> R.string.pref_key_sync_history SyncEngine.Bookmarks -> R.string.pref_key_sync_bookmarks SyncEngine.Passwords -> R.string.pref_key_sync_logins SyncEngine.Tabs -> R.string.pref_key_sync_tabs + SyncEngine.CreditCards -> R.string.pref_key_sync_credit_cards + SyncEngine.Addresses -> R.string.pref_key_sync_address else -> throw IllegalStateException("Accessing internal sync engines") } - listOf(SyncEngine.History, SyncEngine.Bookmarks, SyncEngine.Tabs).forEach { + listOf( + SyncEngine.History, + SyncEngine.Bookmarks, + SyncEngine.Tabs, + SyncEngine.Addresses + ).forEach { requirePreference(it.prefId()).apply { setOnPreferenceChangeListener { _, newValue -> - updateSyncEngineState(context, it, newValue as Boolean) + updateSyncEngineState(it, newValue as Boolean) true } } } - // 'Passwords' listener is special, since we also display a pin protection warning. - requirePreference(SyncEngine.Passwords.prefId()).apply { - setOnPreferenceChangeListener { _, newValue -> - val manager = - activity?.getSystemService(Context.KEYGUARD_SERVICE) as KeyguardManager - if (manager.isKeyguardSecure || - newValue == false || - !context.settings().shouldShowSecurityPinWarningSync - ) { - updateSyncEngineState(context, SyncEngine.Passwords, newValue as Boolean) - } else { - showPinDialogWarning(newValue as Boolean) + // 'Passwords' and 'Credit card' listeners are special, since we also display a pin protection warning. + listOf( + SyncEngine.Passwords, + SyncEngine.CreditCards + ).forEach { + requirePreference(it.prefId()).apply { + setOnPreferenceChangeListener { _, newValue -> + updateSyncEngineStateWithPinWarning(it, newValue as Boolean) + true } - true } } @@ -218,7 +215,57 @@ class AccountSettingsFragment : PreferenceFragmentCompat() { ) } - private fun showPinDialogWarning(newValue: Boolean) { + /** + * Prompts the user if they do not have a password/pin set up to secure their device, and + * updates the state of the sync engine with the new checkbox value. + * + * Currently used for logins and credit cards. + * + * @param syncEngine the sync engine whose preference has changed. + * @param newValue the value denoting whether or not to sync the specified preference. + */ + private fun updateSyncEngineStateWithPinWarning( + syncEngine: SyncEngine, + newValue: Boolean + ) { + val manager = activity?.getSystemService(Context.KEYGUARD_SERVICE) as KeyguardManager + + if (manager.isKeyguardSecure || + !newValue || + !requireContext().settings().shouldShowSecurityPinWarningSync + ) { + updateSyncEngineState(syncEngine, newValue) + } else { + showPinDialogWarning(syncEngine, newValue) + } + } + + /** + * Updates the sync engine status with the new state of the preference and triggers a sync + * event. + * + * @param engine the sync engine whose preference has changed. + * @param newValue the new value of the sync preference, where true indicates sync for that + * preference and false indicates not synced. + */ + private fun updateSyncEngineState(engine: SyncEngine, newValue: Boolean) { + SyncEnginesStorage(requireContext()).setStatus(engine, newValue) + viewLifecycleOwner.lifecycleScope.launch { + requireContext().components.backgroundServices.accountManager.syncNow(SyncReason.EngineChange) + } + } + + /** + * Creates and shows a warning dialog that prompts the user to create a pin/password to + * secure their device when none is detected. The user has the option to continue with + * updating their sync preferences (updates the [SyncEngine] state) or navigating to + * device security settings to create a pin/password. + * + * @param syncEngine the sync engine whose preference has changed. + * @param newValue the new value of the sync preference, where true indicates sync for that + * preference and false indicates not synced. + */ + private fun showPinDialogWarning(syncEngine: SyncEngine, newValue: Boolean) { context?.let { AlertDialog.Builder(it).apply { setTitle(getString(R.string.logins_warning_dialog_title)) @@ -227,11 +274,7 @@ class AccountSettingsFragment : PreferenceFragmentCompat() { ) setNegativeButton(getString(R.string.logins_warning_dialog_later)) { _: DialogInterface, _ -> - SyncEnginesStorage(context).setStatus(SyncEngine.Passwords, newValue) - // Use fragment's lifecycle; the view may be gone by the time dialog is interacted with. - lifecycleScope.launch { - context.components.backgroundServices.accountManager.syncNow(SyncReason.EngineChange) - } + updateSyncEngineState(syncEngine, newValue) } setPositiveButton(getString(R.string.logins_warning_dialog_set_up_now)) { it: DialogInterface, _ -> @@ -247,12 +290,20 @@ class AccountSettingsFragment : PreferenceFragmentCompat() { } } + /** + * Updates the status of all [SyncEngine] states. + */ private fun updateSyncEngineStates() { val syncEnginesStatus = SyncEnginesStorage(requireContext()).getStatus() requirePreference(R.string.pref_key_sync_bookmarks).apply { isEnabled = syncEnginesStatus.containsKey(SyncEngine.Bookmarks) isChecked = syncEnginesStatus.getOrElse(SyncEngine.Bookmarks) { true } } + requirePreference(R.string.pref_key_sync_credit_cards).apply { + isVisible = FeatureFlags.creditCardsFeature + isEnabled = syncEnginesStatus.containsKey(SyncEngine.CreditCards) + isChecked = syncEnginesStatus.getOrElse(SyncEngine.CreditCards) { true } + } requirePreference(R.string.pref_key_sync_history).apply { isEnabled = syncEnginesStatus.containsKey(SyncEngine.History) isChecked = syncEnginesStatus.getOrElse(SyncEngine.History) { true } @@ -265,8 +316,17 @@ class AccountSettingsFragment : PreferenceFragmentCompat() { isEnabled = syncEnginesStatus.containsKey(SyncEngine.Tabs) isChecked = syncEnginesStatus.getOrElse(SyncEngine.Tabs) { true } } + requirePreference(R.string.pref_key_sync_address).apply { + isVisible = FeatureFlags.addressesFeature + isEnabled = syncEnginesStatus.containsKey(SyncEngine.Addresses) + isChecked = syncEnginesStatus.getOrElse(SyncEngine.Addresses) { true } + } } + /** + * Manual sync triggered by the user. This also checks account authentication and refreshes the + * device list. + */ private fun syncNow() { viewLifecycleOwner.lifecycleScope.launch { requireComponents.analytics.metrics.track(Event.SyncAccountSyncNow) @@ -281,8 +341,13 @@ class AccountSettingsFragment : PreferenceFragmentCompat() { } } - private fun syncDeviceName(newValue: String): Boolean { - if (newValue.trim().isEmpty()) { + /** + * Takes a non-empty value and sets the device name. May fail due to authentication. + * + * @param newDeviceName the new name of the device. Cannot be an empty string. + */ + private fun syncDeviceName(newDeviceName: String): Boolean { + if (newDeviceName.trim().isEmpty()) { return false } // This may fail, and we'll have a disparity in the UI until `updateDeviceName` is called. @@ -290,7 +355,7 @@ class AccountSettingsFragment : PreferenceFragmentCompat() { context?.let { accountManager.authenticatedAccount() ?.deviceConstellation() - ?.setDeviceName(newValue, it) + ?.setDeviceName(newDeviceName, it) } } return true @@ -409,6 +474,5 @@ class AccountSettingsFragment : PreferenceFragmentCompat() { companion object { private const val DEVICE_NAME_MAX_LENGTH = 128 - private const val DEVICE_NAME_EDIT_TEXT_MIN_HEIGHT_DP = 48 } } diff --git a/app/src/main/java/org/mozilla/fenix/settings/advanced/LocaleViewHolders.kt b/app/src/main/java/org/mozilla/fenix/settings/advanced/LocaleViewHolders.kt index 3163e9fe3..35cc659bf 100644 --- a/app/src/main/java/org/mozilla/fenix/settings/advanced/LocaleViewHolders.kt +++ b/app/src/main/java/org/mozilla/fenix/settings/advanced/LocaleViewHolders.kt @@ -77,7 +77,7 @@ class LocaleViewHolder( "ca" to "Català", "cak" to "Kaqchikel", "ceb" to "Cebuano", - "co" to "Corsu, ", + "co" to "Corsu", "cs" to "čeština", "cy" to "Cymraeg", "da" to "dansk", @@ -99,7 +99,7 @@ class LocaleViewHolder( "gn" to "Avañe'ẽ", "gu-IN" to "ગુજરાતી", "he" to "עברית", - "hi-IN" to "हिन्दी ", + "hi-IN" to "हिन्दी", "hil" to "Ilonggo", "hr" to "hrvatski jezik", "hsb" to "Hornjoserbsce", @@ -216,7 +216,7 @@ class LocaleViewHolder( "it" to "Italian", "ja" to "Japanese", "ka" to "Georgian", - "kab" to "Kabyle ", + "kab" to "Kabyle", "kk" to "Kazakh", "kmr" to "Kurmanji Kurdish", "kn" to "Kannada", @@ -230,7 +230,7 @@ class LocaleViewHolder( "ms" to "Malay", "my" to "Burmese", "nb-NO" to "Norwegian Bokmål", - "ne-NP" to "Nepali ", + "ne-NP" to "Nepali", "nl" to "Dutch, Flemish", "nn-NO" to "Norwegian Nynorsk", "nv" to "Navajo, Navaho", diff --git a/app/src/main/java/org/mozilla/fenix/settings/biometric/BiometricPromptPreferenceFragment.kt b/app/src/main/java/org/mozilla/fenix/settings/biometric/BiometricPromptPreferenceFragment.kt new file mode 100644 index 000000000..7470d50e2 --- /dev/null +++ b/app/src/main/java/org/mozilla/fenix/settings/biometric/BiometricPromptPreferenceFragment.kt @@ -0,0 +1,120 @@ +/* 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 org.mozilla.fenix.settings.biometric + +import android.app.Activity.RESULT_OK +import android.app.KeyguardManager +import android.content.Context +import android.content.Intent +import android.view.View +import androidx.core.content.getSystemService +import androidx.preference.Preference +import androidx.preference.PreferenceFragmentCompat +import mozilla.components.support.base.feature.ViewBoundFeatureWrapper +import org.mozilla.fenix.ext.settings +import org.mozilla.fenix.settings.requirePreference + +/** + * Helper for creating and implementing the [BiometricPromptFeature]. Currently used + * for logins and credit cards. + */ +abstract class BiometricPromptPreferenceFragment : PreferenceFragmentCompat() { + + private val biometricPromptFeature = ViewBoundFeatureWrapper() + + /** + * Gets the string to be used for [BiometricPromptFeature.requestAuthentication] prompting to + * unlock the device. + */ + abstract fun unlockMessage(): String + + /** + * Navigate when authentication is successful. + */ + abstract fun navigateOnSuccess() + + /** + * Shows a dialog warning to set up a pin/password when the device is not secured. This is + * only used when BiometricPrompt is unavailable on the device. + */ + abstract fun showPinDialogWarning(context: Context) + + /** + * Toggle preferences to enable or disable navigation during authentication flows. + * + * @param prefList a list of [Preference]s to toggle. + * @param enabled whether or not the preferences should be enabled. + */ + fun togglePrefsEnabled(prefList: List, enabled: Boolean) { + for (preference in prefList) { + requirePreference(preference).isEnabled = enabled + } + } + + /** + * Creates a prompt to verify the device's pin/password and start activity based on the result. + * This is only used when BiometricPrompt is unavailable on the device. + */ + @Suppress("Deprecation") + abstract fun showPinVerification(manager: KeyguardManager) + + /** + * Sets the biometric prompt feature. + * + * @param view the view that the prompt will be associate with. + * @param prefList a list of [Preference]s to toggle. + */ + fun setBiometricPrompt(view: View, prefList: List) { + biometricPromptFeature.set( + feature = BiometricPromptFeature( + context = requireContext(), + fragment = this, + onAuthFailure = { + togglePrefsEnabled(prefList, true) + }, + onAuthSuccess = ::navigateOnSuccess + ), + owner = this, + view = view + ) + } + + /** + * Use [BiometricPromptFeature] or [KeyguardManager] to confirm device security. + * + * @param prefList a list of [Preference]s to disable while authentication is happening. + */ + fun verifyCredentialsOrShowSetupWarning(context: Context, prefList: List) { + // Use the BiometricPrompt if available + if (BiometricPromptFeature.canUseFeature(context)) { + togglePrefsEnabled(prefList, false) + biometricPromptFeature.get()?.requestAuthentication(unlockMessage()) + return + } + + // Fallback to prompting for password with the KeyguardManager + val manager = context.getSystemService() + if (manager?.isKeyguardSecure == true) { + showPinVerification(manager) + } else { + // Warn that the device has not been secured + if (context.settings().shouldShowSecurityPinWarning) { + showPinDialogWarning(context) + } else { + navigateOnSuccess() + } + } + } + + override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { + if (requestCode == PIN_REQUEST && resultCode == RESULT_OK) { + navigateOnSuccess() + } + } + + companion object { + const val PIN_REQUEST = 303 + } +} diff --git a/app/src/main/java/org/mozilla/fenix/settings/creditcards/CreditCardEditorFragment.kt b/app/src/main/java/org/mozilla/fenix/settings/creditcards/CreditCardEditorFragment.kt index 91b9ac8ce..c47f874a2 100644 --- a/app/src/main/java/org/mozilla/fenix/settings/creditcards/CreditCardEditorFragment.kt +++ b/app/src/main/java/org/mozilla/fenix/settings/creditcards/CreditCardEditorFragment.kt @@ -9,15 +9,14 @@ import android.view.Menu import android.view.MenuInflater import android.view.MenuItem import android.view.View -import androidx.fragment.app.Fragment import androidx.lifecycle.lifecycleScope import androidx.navigation.fragment.findNavController import androidx.navigation.fragment.navArgs -import kotlinx.android.synthetic.main.fragment_credit_card_editor.* -import mozilla.components.concept.storage.UpdatableCreditCardFields -import mozilla.components.support.ktx.android.view.hideKeyboard import org.mozilla.fenix.R +import org.mozilla.fenix.SecureFragment import org.mozilla.fenix.ext.components +import org.mozilla.fenix.ext.redirectToReAuth +import org.mozilla.fenix.ext.settings import org.mozilla.fenix.ext.showToolbar import org.mozilla.fenix.settings.creditcards.controller.DefaultCreditCardEditorController import org.mozilla.fenix.settings.creditcards.interactor.CreditCardEditorInteractor @@ -27,7 +26,11 @@ import org.mozilla.fenix.settings.creditcards.view.CreditCardEditorView /** * Display a credit card editor for adding and editing a credit card. */ -class CreditCardEditorFragment : Fragment(R.layout.fragment_credit_card_editor) { +class CreditCardEditorFragment : SecureFragment(R.layout.fragment_credit_card_editor) { + + private lateinit var creditCardEditorState: CreditCardEditorState + private lateinit var creditCardEditorView: CreditCardEditorView + private lateinit var menu: Menu private val args by navArgs() @@ -50,48 +53,53 @@ class CreditCardEditorFragment : Fragment(R.layout.fragment_credit_card_editor) showToolbar(getString(R.string.credit_cards_edit_card)) } + val storage = requireContext().components.core.autofillStorage interactor = DefaultCreditCardEditorInteractor( controller = DefaultCreditCardEditorController( - storage = requireContext().components.core.autofillStorage, + storage = storage, lifecycleScope = lifecycleScope, - navController = findNavController() + navController = findNavController(), + settings = requireContext().settings() ) ) - val creditCardEditorState = - args.creditCard?.toCreditCardEditorState() ?: getInitialCreditCardEditorState() - CreditCardEditorView(view, interactor).bind(creditCardEditorState) + creditCardEditorState = + args.creditCard?.toCreditCardEditorState(storage) ?: getInitialCreditCardEditorState() + creditCardEditorView = CreditCardEditorView(view, interactor) + creditCardEditorView.bind(creditCardEditorState) + } + + /** + * Close any open dialogs or menus and reauthenticate if the fragment is paused and + * the user is not navigating to [CreditCardsManagementFragment]. + */ + override fun onPause() { + menu.close() + + redirectToReAuth( + listOf(R.id.creditCardsManagementFragment), + findNavController().currentDestination?.id, + R.id.creditCardEditorFragment + ) + + super.onPause() } override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) { inflater.inflate(R.menu.credit_card_editor, menu) + this.menu = menu menu.findItem(R.id.delete_credit_card_button).isVisible = isEditing } + @Suppress("MagicNumber") override fun onOptionsItemSelected(item: MenuItem): Boolean = when (item.itemId) { R.id.delete_credit_card_button -> { args.creditCard?.let { interactor.onDeleteCardButtonClicked(it.guid) } true } R.id.save_credit_card_button -> { - view?.hideKeyboard() - - val creditCard = args.creditCard - val creditCardFields = UpdatableCreditCardFields( - billingName = name_on_card_input.text.toString(), - cardNumber = card_number_input.text.toString(), - expiryMonth = (expiry_month_drop_down.selectedItemPosition + 1).toLong(), - expiryYear = expiry_year_drop_down.selectedItem.toString().toLong(), - cardType = CARD_TYPE_PLACEHOLDER - ) - - if (creditCard != null) { - interactor.onUpdateCreditCard(creditCard.guid, creditCardFields) - } else { - interactor.onSaveCreditCard(creditCardFields) - } - + creditCardEditorView.saveCreditCard(creditCardEditorState) true } else -> false @@ -100,9 +108,5 @@ class CreditCardEditorFragment : Fragment(R.layout.fragment_credit_card_editor) companion object { // Number of years to show in the expiry year dropdown. const val NUMBER_OF_YEARS_TO_SHOW = 10 - - // Placeholder for the card type. This will be replaced when we can identify the card type. - // This is dependent on https://github.com/mozilla-mobile/android-components/issues/9813. - const val CARD_TYPE_PLACEHOLDER = "" } } diff --git a/app/src/main/java/org/mozilla/fenix/settings/creditcards/CreditCardEditorState.kt b/app/src/main/java/org/mozilla/fenix/settings/creditcards/CreditCardEditorState.kt index ed9c62747..f3fc4c0c3 100644 --- a/app/src/main/java/org/mozilla/fenix/settings/creditcards/CreditCardEditorState.kt +++ b/app/src/main/java/org/mozilla/fenix/settings/creditcards/CreditCardEditorState.kt @@ -5,6 +5,7 @@ package org.mozilla.fenix.settings.creditcards import mozilla.components.concept.storage.CreditCard +import mozilla.components.service.sync.autofill.AutofillCreditCardsAddressesStorage import org.mozilla.fenix.settings.creditcards.CreditCardEditorFragment.Companion.NUMBER_OF_YEARS_TO_SHOW import java.util.Calendar @@ -30,7 +31,10 @@ data class CreditCardEditorState( /** * Returns a [CreditCardEditorState] from the given [CreditCard]. */ -fun CreditCard.toCreditCardEditorState(): CreditCardEditorState { +fun CreditCard.toCreditCardEditorState(storage: AutofillCreditCardsAddressesStorage): CreditCardEditorState { + val crypto = storage.getCreditCardCrypto() + val key = crypto.key() + val cardNumber = crypto.decrypt(key, encryptedCardNumber)?.number ?: "" val startYear = expiryYear.toInt() val endYear = startYear + NUMBER_OF_YEARS_TO_SHOW diff --git a/app/src/main/java/org/mozilla/fenix/settings/creditcards/CreditCardsManagementFragment.kt b/app/src/main/java/org/mozilla/fenix/settings/creditcards/CreditCardsManagementFragment.kt index be0ceaffa..e54f42e2a 100644 --- a/app/src/main/java/org/mozilla/fenix/settings/creditcards/CreditCardsManagementFragment.kt +++ b/app/src/main/java/org/mozilla/fenix/settings/creditcards/CreditCardsManagementFragment.kt @@ -8,7 +8,6 @@ import android.os.Bundle import android.view.LayoutInflater import android.view.View import android.view.ViewGroup -import androidx.fragment.app.Fragment import androidx.lifecycle.lifecycleScope import androidx.navigation.fragment.findNavController import kotlinx.android.synthetic.main.fragment_saved_cards.view.* @@ -17,8 +16,10 @@ import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.launch import mozilla.components.lib.state.ext.consumeFrom import org.mozilla.fenix.R +import org.mozilla.fenix.SecureFragment import org.mozilla.fenix.components.StoreProvider import org.mozilla.fenix.ext.components +import org.mozilla.fenix.ext.redirectToReAuth import org.mozilla.fenix.ext.showToolbar import org.mozilla.fenix.settings.creditcards.controller.DefaultCreditCardsManagementController import org.mozilla.fenix.settings.creditcards.interactor.CreditCardsManagementInteractor @@ -28,7 +29,7 @@ import org.mozilla.fenix.settings.creditcards.view.CreditCardsManagementView /** * Displays a list of saved credit cards. */ -class CreditCardsManagementFragment : Fragment() { +class CreditCardsManagementFragment : SecureFragment() { private lateinit var creditCardsStore: CreditCardsFragmentStore private lateinit var interactor: CreditCardsManagementInteractor @@ -61,6 +62,11 @@ class CreditCardsManagementFragment : Fragment() { @ExperimentalCoroutinesApi override fun onViewCreated(view: View, savedInstanceState: Bundle?) { consumeFrom(creditCardsStore) { state -> + if (!state.isLoading && state.creditCards.isEmpty()) { + findNavController().popBackStack() + return@consumeFrom + } + creditCardsView.update(state) } } @@ -70,6 +76,20 @@ class CreditCardsManagementFragment : Fragment() { showToolbar(getString(R.string.credit_cards_saved_cards)) } + /** + * When the fragment is paused, navigate back to the settings page to reauthenticate. + */ + override fun onPause() { + // Don't redirect if the user is navigating to the credit card editor fragment. + redirectToReAuth( + listOf(R.id.creditCardEditorFragment), + findNavController().currentDestination?.id, + R.id.creditCardsManagementFragment + ) + + super.onPause() + } + /** * Fetches all the credit cards from the autofill storage and updates the * [CreditCardsFragmentStore] with the list of credit cards. diff --git a/app/src/main/java/org/mozilla/fenix/settings/creditcards/CreditCardsSettingFragment.kt b/app/src/main/java/org/mozilla/fenix/settings/creditcards/CreditCardsSettingFragment.kt index bcb197137..8838c57de 100644 --- a/app/src/main/java/org/mozilla/fenix/settings/creditcards/CreditCardsSettingFragment.kt +++ b/app/src/main/java/org/mozilla/fenix/settings/creditcards/CreditCardsSettingFragment.kt @@ -4,27 +4,115 @@ package org.mozilla.fenix.settings.creditcards +import android.app.KeyguardManager +import android.content.Context +import android.content.DialogInterface +import android.content.Intent import android.os.Bundle +import android.provider.Settings +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import androidx.annotation.VisibleForTesting +import androidx.appcompat.app.AlertDialog +import androidx.lifecycle.lifecycleScope +import androidx.navigation.NavController import androidx.navigation.fragment.findNavController import androidx.preference.Preference -import androidx.preference.PreferenceFragmentCompat +import androidx.preference.SwitchPreference +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.delay +import kotlinx.coroutines.launch +import mozilla.components.lib.state.ext.consumeFrom import mozilla.components.service.fxa.SyncEngine +import org.mozilla.fenix.NavGraphDirections import org.mozilla.fenix.R -import org.mozilla.fenix.ext.getPreferenceKey +import org.mozilla.fenix.components.StoreProvider import org.mozilla.fenix.ext.navigateBlockingForAsyncNavGraph import org.mozilla.fenix.ext.requireComponents +import org.mozilla.fenix.ext.settings +import org.mozilla.fenix.ext.runIfFragmentIsAttached +import org.mozilla.fenix.ext.secure import org.mozilla.fenix.ext.showToolbar +import org.mozilla.fenix.settings.SharedPreferenceUpdater import org.mozilla.fenix.settings.SyncPreferenceView +import org.mozilla.fenix.settings.biometric.BiometricPromptFeature +import org.mozilla.fenix.settings.biometric.BiometricPromptPreferenceFragment import org.mozilla.fenix.settings.requirePreference /** * "Credit cards" settings fragment displays a list of settings related to autofilling, adding and - * syncing credit cards. + * syncing credit cards. Authentication for saved credit cards uses [BiometricPromptFeature] + * or [KeyguardManager]. */ -class CreditCardsSettingFragment : PreferenceFragmentCompat() { +@SuppressWarnings("TooManyFunctions") +class CreditCardsSettingFragment : BiometricPromptPreferenceFragment() { + + private lateinit var creditCardsStore: CreditCardsFragmentStore + private var isCreditCardsListLoaded: Boolean = false + + /** + * List of preferences to be enabled or disabled during authentication. + */ + private val creditCardPreferences: List = listOf( + R.string.pref_key_credit_cards_save_and_autofill_cards, + R.string.pref_key_credit_cards_sync_cards_across_devices, + R.string.pref_key_credit_cards_manage_cards + ) + + override fun unlockMessage() = getString(R.string.credit_cards_biometric_prompt_message) + + override fun navigateOnSuccess() { + runIfFragmentIsAttached { + viewLifecycleOwner.lifecycleScope.launch(Dispatchers.Main) { + // Workaround for likely biometric library bug + // https://github.com/mozilla-mobile/fenix/issues/8438 + delay(SHORT_DELAY_MS) + navigateToCreditCardManagementFragment() + } + } + } + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + creditCardsStore = StoreProvider.get(this) { + CreditCardsFragmentStore(CreditCardsListState(creditCards = emptyList())) + } + loadCreditCards() + } override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) { setPreferencesFromResource(R.xml.credit_cards_preferences, rootKey) + + requirePreference(R.string.pref_key_credit_cards_save_and_autofill_cards).apply { + isChecked = context.settings().shouldAutofillCreditCardDetails + onPreferenceChangeListener = SharedPreferenceUpdater() + } + } + + override fun onCreateView( + inflater: LayoutInflater, + container: ViewGroup?, + savedInstanceState: Bundle? + ): View? { + loadCreditCards() + return super.onCreateView(inflater, container, savedInstanceState) + } + + @ExperimentalCoroutinesApi + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + consumeFrom(creditCardsStore) { state -> + updateCardManagementPreference(state.creditCards.isNotEmpty(), findNavController()) + } + + setBiometricPrompt(view, creditCardPreferences) + } + + override fun onPause() { + super.onPause() + isCreditCardsListLoaded = false } override fun onResume() { @@ -36,42 +124,126 @@ class CreditCardsSettingFragment : PreferenceFragmentCompat() { syncPreference = requirePreference(R.string.pref_key_credit_cards_sync_cards_across_devices), lifecycleOwner = viewLifecycleOwner, accountManager = requireComponents.backgroundServices.accountManager, - syncEngine = SyncEngine.Passwords, + syncEngine = SyncEngine.CreditCards, + loggedOffTitle = requireContext() + .getString(R.string.preferences_credit_cards_sync_cards_across_devices), + loggedInTitle = requireContext() + .getString(R.string.preferences_credit_cards_sync_cards), onSignInToSyncClicked = { - val directions = - CreditCardsSettingFragmentDirections.actionCreditCardsSettingFragmentToTurnOnSyncFragment() - findNavController().navigateBlockingForAsyncNavGraph(directions) - }, - onSyncStatusClicked = { - val directions = - CreditCardsSettingFragmentDirections.actionGlobalAccountSettingsFragment() - findNavController().navigateBlockingForAsyncNavGraph(directions) + findNavController().navigateBlockingForAsyncNavGraph( + NavGraphDirections.actionGlobalTurnOnSync() + ) }, onReconnectClicked = { - val directions = + findNavController().navigateBlockingForAsyncNavGraph( CreditCardsSettingFragmentDirections.actionGlobalAccountProblemFragment() - findNavController().navigateBlockingForAsyncNavGraph(directions) + ) } ) + + togglePrefsEnabled(creditCardPreferences, true) } - @Suppress("MaxLineLength") - override fun onPreferenceTreeClick(preference: Preference): Boolean { - when (preference.key) { - getPreferenceKey(R.string.pref_key_credit_cards_add_credit_card) -> { - val directions = + /** + * Updates preferences visibility depending on credit cards being already saved or not. + */ + @VisibleForTesting + internal fun updateCardManagementPreference( + hasCreditCards: Boolean, + navController: NavController + ) { + val manageSavedCardsPreference = + requirePreference(R.string.pref_key_credit_cards_manage_cards) + + if (hasCreditCards) { + manageSavedCardsPreference.icon = null + manageSavedCardsPreference.title = + getString(R.string.preferences_credit_cards_manage_saved_cards) + } else { + manageSavedCardsPreference.setIcon(R.drawable.ic_new) + manageSavedCardsPreference.title = + getString(R.string.preferences_credit_cards_add_credit_card) + } + + manageSavedCardsPreference.setOnPreferenceClickListener { + if (hasCreditCards) { + verifyCredentialsOrShowSetupWarning(requireContext(), creditCardPreferences) + } else { + navController.navigateBlockingForAsyncNavGraph( CreditCardsSettingFragmentDirections .actionCreditCardsSettingFragmentToCreditCardEditorFragment() - findNavController().navigateBlockingForAsyncNavGraph(directions) + ) } - getPreferenceKey(R.string.pref_key_credit_cards_manage_saved_cards) -> { - val directions = - CreditCardsSettingFragmentDirections - .actionCreditCardsSettingFragmentToCreditCardsManagementFragment() - findNavController().navigateBlockingForAsyncNavGraph(directions) + super.onPreferenceTreeClick(it) + } + } + + /** + * Fetches all the credit cards from autofillStorage and updates the [CreditCardsListState] + * with the list of credit cards. + */ + private fun loadCreditCards() { + if (isCreditCardsListLoaded) { + return + } + + lifecycleScope.launch(Dispatchers.IO) { + val creditCards = requireComponents.core.autofillStorage.getAllCreditCards() + lifecycleScope.launch(Dispatchers.Main) { + creditCardsStore.dispatch(CreditCardsAction.UpdateCreditCards(creditCards)) } } - return super.onPreferenceTreeClick(preference) + isCreditCardsListLoaded = true + } + + /** + * Shows a dialog warning to set up a pin/password when the device is not secured. This is + * only used when BiometricPrompt is unavailable on the device. + */ + override fun showPinDialogWarning(context: Context) { + AlertDialog.Builder(context).apply { + setTitle(getString(R.string.credit_cards_warning_dialog_title)) + setMessage(getString(R.string.credit_cards_warning_dialog_message)) + + setNegativeButton(getString(R.string.credit_cards_warning_dialog_later)) { _: DialogInterface, _ -> + navigateToCreditCardManagementFragment() + } + + setPositiveButton(getString(R.string.credit_cards_warning_dialog_set_up_now)) { it: DialogInterface, _ -> + it.dismiss() + val intent = Intent(Settings.ACTION_SECURITY_SETTINGS) + startActivity(intent) + } + + create() + }.show().secure(activity) + context.settings().incrementSecureWarningCount() + } + + /** + * Shows a prompt to verify the device's pin/password and start activity based on the result. + * This is only used when BiometricPrompt is unavailable on the device. + * + * @param manager The device [KeyguardManager] + */ + @Suppress("Deprecation") + override fun showPinVerification(manager: KeyguardManager) { + val intent = manager.createConfirmDeviceCredentialIntent( + getString(R.string.credit_cards_biometric_prompt_message_pin), + getString(R.string.credit_cards_biometric_prompt_message) + ) + startActivityForResult(intent, BiometricPromptPreferenceFragment.PIN_REQUEST) + } + + private fun navigateToCreditCardManagementFragment() { + val directions = + CreditCardsSettingFragmentDirections + .actionCreditCardsSettingFragmentToCreditCardsManagementFragment() + findNavController().navigateBlockingForAsyncNavGraph(directions) + } + + companion object { + const val SHORT_DELAY_MS = 100L } } diff --git a/app/src/main/java/org/mozilla/fenix/settings/creditcards/String.kt b/app/src/main/java/org/mozilla/fenix/settings/creditcards/String.kt new file mode 100644 index 000000000..0702b6c5f --- /dev/null +++ b/app/src/main/java/org/mozilla/fenix/settings/creditcards/String.kt @@ -0,0 +1,57 @@ +/* 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 org.mozilla.fenix.settings.creditcards + +import androidx.annotation.VisibleForTesting +import mozilla.components.support.utils.creditCardIIN + +// Number of last digits to be shown when credit card number is obfuscated. +private const val LAST_VISIBLE_DIGITS_COUNT = 4 + +/** + * Strips characters other than digits from a string. + * Used to strip a credit card number user input of spaces and separators. + */ +fun String.toCreditCardNumber(): String { + return this.filter { it.isDigit() } +} + +/** + * Returns the last 4 digits from a formatted credit card number string. + */ +fun String.last4Digits(): String { + return this.takeLast(LAST_VISIBLE_DIGITS_COUNT) +} + +/** + * Returns true if the provided string is a valid credit card by checking if it has a matching + * credit card issuer network passes the Luhn Algorithm, and false otherwise. + */ +fun String.validateCreditCardNumber(): Boolean { + val creditCardNumber = this.toCreditCardNumber() + + if (creditCardNumber != this || creditCardNumber.creditCardIIN() == null) { + return false + } + + return luhnAlgorithmValidation(creditCardNumber) +} + +/** + * Implementation of Luhn Algorithm validation (https://en.wikipedia.org/wiki/Luhn_algorithm) + */ +@Suppress("MagicNumber") +@VisibleForTesting +internal fun luhnAlgorithmValidation(creditCardNumber: String): Boolean { + var checksum = 0 + val reversedCardNumber = creditCardNumber.reversed() + + for (index in reversedCardNumber.indices) { + val digit = Character.getNumericValue(reversedCardNumber[index]) + checksum += if (index % 2 == 0) digit else (digit * 2).let { (it / 10) + (it % 10) } + } + + return (checksum % 10) == 0 +} diff --git a/app/src/main/java/org/mozilla/fenix/settings/creditcards/controller/CreditCardEditorController.kt b/app/src/main/java/org/mozilla/fenix/settings/creditcards/controller/CreditCardEditorController.kt index bfa6ca66b..71e8175ec 100644 --- a/app/src/main/java/org/mozilla/fenix/settings/creditcards/controller/CreditCardEditorController.kt +++ b/app/src/main/java/org/mozilla/fenix/settings/creditcards/controller/CreditCardEditorController.kt @@ -9,10 +9,12 @@ import kotlinx.coroutines.CoroutineDispatcher import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch +import mozilla.components.concept.storage.NewCreditCardFields import mozilla.components.concept.storage.UpdatableCreditCardFields import mozilla.components.service.sync.autofill.AutofillCreditCardsAddressesStorage import org.mozilla.fenix.settings.creditcards.CreditCardEditorFragment import org.mozilla.fenix.settings.creditcards.interactor.CreditCardEditorInteractor +import org.mozilla.fenix.utils.Settings /** * [CreditCardEditorFragment] controller. An interface that handles the view manipulation of the @@ -33,7 +35,7 @@ interface CreditCardEditorController { /** * @see [CreditCardEditorInteractor.onSaveCreditCard] */ - fun handleSaveCreditCard(creditCardFields: UpdatableCreditCardFields) + fun handleSaveCreditCard(creditCardFields: NewCreditCardFields) /** * @see [CreditCardEditorInteractor.onUpdateCreditCard] @@ -48,12 +50,14 @@ interface CreditCardEditorController { * credit cards. * @param lifecycleScope [CoroutineScope] scope to launch coroutines. * @param navController [NavController] used for navigation. + * @param settings [Settings] application settings. * @param ioDispatcher [CoroutineDispatcher] used for executing async tasks. Defaults to [Dispatchers.IO]. */ class DefaultCreditCardEditorController( private val storage: AutofillCreditCardsAddressesStorage, private val lifecycleScope: CoroutineScope, private val navController: NavController, + private val settings: Settings, private val ioDispatcher: CoroutineDispatcher = Dispatchers.IO ) : CreditCardEditorController { @@ -62,6 +66,8 @@ class DefaultCreditCardEditorController( } override fun handleDeleteCreditCard(guid: String) { + settings.creditCardsDeletedCount += 1 + lifecycleScope.launch(ioDispatcher) { storage.deleteCreditCard(guid) @@ -71,7 +77,9 @@ class DefaultCreditCardEditorController( } } - override fun handleSaveCreditCard(creditCardFields: UpdatableCreditCardFields) { + override fun handleSaveCreditCard(creditCardFields: NewCreditCardFields) { + settings.creditCardsSavedCount += 1 + lifecycleScope.launch(ioDispatcher) { storage.addCreditCard(creditCardFields) diff --git a/app/src/main/java/org/mozilla/fenix/settings/creditcards/controller/CreditCardsManagementController.kt b/app/src/main/java/org/mozilla/fenix/settings/creditcards/controller/CreditCardsManagementController.kt index bcc0906a0..9e7416802 100644 --- a/app/src/main/java/org/mozilla/fenix/settings/creditcards/controller/CreditCardsManagementController.kt +++ b/app/src/main/java/org/mozilla/fenix/settings/creditcards/controller/CreditCardsManagementController.kt @@ -21,6 +21,11 @@ interface CreditCardsManagementController { * @see [CreditCardsManagementInteractor.onSelectCreditCard] */ fun handleCreditCardClicked(creditCard: CreditCard) + + /** + * @see [CreditCardsManagementInteractor.onAddCreditCardClick] + */ + fun handleAddCreditCardClicked() } /** @@ -31,6 +36,14 @@ class DefaultCreditCardsManagementController( ) : CreditCardsManagementController { override fun handleCreditCardClicked(creditCard: CreditCard) { + navigateToCreditCardEditor(creditCard) + } + + override fun handleAddCreditCardClicked() { + navigateToCreditCardEditor() + } + + private fun navigateToCreditCardEditor(creditCard: CreditCard? = null) { navController.navigateBlockingForAsyncNavGraph( CreditCardsManagementFragmentDirections .actionCreditCardsManagementFragmentToCreditCardEditorFragment( diff --git a/app/src/main/java/org/mozilla/fenix/settings/creditcards/interactor/CreditCardEditorInteractor.kt b/app/src/main/java/org/mozilla/fenix/settings/creditcards/interactor/CreditCardEditorInteractor.kt index 2633c57fe..9a4a3b1bc 100644 --- a/app/src/main/java/org/mozilla/fenix/settings/creditcards/interactor/CreditCardEditorInteractor.kt +++ b/app/src/main/java/org/mozilla/fenix/settings/creditcards/interactor/CreditCardEditorInteractor.kt @@ -4,6 +4,7 @@ package org.mozilla.fenix.settings.creditcards.interactor +import mozilla.components.concept.storage.NewCreditCardFields import mozilla.components.concept.storage.UpdatableCreditCardFields import org.mozilla.fenix.settings.creditcards.controller.CreditCardEditorController @@ -30,9 +31,9 @@ interface CreditCardEditorInteractor { * Saves the provided credit card field into the credit card storage. Called when a user * taps on the save menu item or "Save" button. * - * @param creditCardFields A [UpdatableCreditCardFields] record to add. + * @param creditCardFields A [NewCreditCardFields] record to add. */ - fun onSaveCreditCard(creditCardFields: UpdatableCreditCardFields) + fun onSaveCreditCard(creditCardFields: NewCreditCardFields) /** * Updates the provided credit card with the new credit card fields. Called when a user @@ -62,7 +63,7 @@ class DefaultCreditCardEditorInteractor( controller.handleDeleteCreditCard(guid) } - override fun onSaveCreditCard(creditCardFields: UpdatableCreditCardFields) { + override fun onSaveCreditCard(creditCardFields: NewCreditCardFields) { controller.handleSaveCreditCard(creditCardFields) } diff --git a/app/src/main/java/org/mozilla/fenix/settings/creditcards/interactor/CreditCardsManagementInteractor.kt b/app/src/main/java/org/mozilla/fenix/settings/creditcards/interactor/CreditCardsManagementInteractor.kt index 251d9de8c..63286d219 100644 --- a/app/src/main/java/org/mozilla/fenix/settings/creditcards/interactor/CreditCardsManagementInteractor.kt +++ b/app/src/main/java/org/mozilla/fenix/settings/creditcards/interactor/CreditCardsManagementInteractor.kt @@ -19,6 +19,12 @@ interface CreditCardsManagementInteractor { * @param creditCard The selected [CreditCard] to edit. */ fun onSelectCreditCard(creditCard: CreditCard) + + /** + * Navigates to the credit card editor to add a new credit card. Called when a user + * taps on 'Add credit card' button. + */ + fun onAddCreditCardClick() } /** @@ -34,4 +40,8 @@ class DefaultCreditCardsManagementInteractor( override fun onSelectCreditCard(creditCard: CreditCard) { controller.handleCreditCardClicked(creditCard) } + + override fun onAddCreditCardClick() { + controller.handleAddCreditCardClicked() + } } diff --git a/app/src/main/java/org/mozilla/fenix/settings/creditcards/view/CreditCardEditorView.kt b/app/src/main/java/org/mozilla/fenix/settings/creditcards/view/CreditCardEditorView.kt index adf19410c..8ea9d2fc4 100644 --- a/app/src/main/java/org/mozilla/fenix/settings/creditcards/view/CreditCardEditorView.kt +++ b/app/src/main/java/org/mozilla/fenix/settings/creditcards/view/CreditCardEditorView.kt @@ -4,17 +4,25 @@ package org.mozilla.fenix.settings.creditcards.view -import android.R import android.view.View import android.widget.ArrayAdapter +import androidx.annotation.VisibleForTesting import kotlinx.android.extensions.LayoutContainer import kotlinx.android.synthetic.main.fragment_credit_card_editor.* +import mozilla.components.concept.storage.CreditCardNumber +import mozilla.components.concept.storage.NewCreditCardFields import mozilla.components.concept.storage.UpdatableCreditCardFields +import mozilla.components.support.ktx.android.content.getColorFromAttr import mozilla.components.support.ktx.android.view.hideKeyboard +import mozilla.components.support.utils.creditCardIIN +import org.mozilla.fenix.R import org.mozilla.fenix.ext.toEditable -import org.mozilla.fenix.settings.creditcards.CreditCardEditorFragment.Companion.CARD_TYPE_PLACEHOLDER +import org.mozilla.fenix.settings.creditcards.CreditCardEditorFragment import org.mozilla.fenix.settings.creditcards.CreditCardEditorState import org.mozilla.fenix.settings.creditcards.interactor.CreditCardEditorInteractor +import org.mozilla.fenix.settings.creditcards.last4Digits +import org.mozilla.fenix.settings.creditcards.toCreditCardNumber +import org.mozilla.fenix.settings.creditcards.validateCreditCardNumber import java.text.SimpleDateFormat import java.util.Calendar import java.util.Locale @@ -46,21 +54,7 @@ class CreditCardEditorView( } save_button.setOnClickListener { - containerView.hideKeyboard() - - val creditCardFields = UpdatableCreditCardFields( - billingName = name_on_card_input.text.toString(), - cardNumber = card_number_input.text.toString(), - expiryMonth = (expiry_month_drop_down.selectedItemPosition + 1).toLong(), - expiryYear = expiry_year_drop_down.selectedItem.toString().toLong(), - cardType = CARD_TYPE_PLACEHOLDER - ) - - if (state.isEditing) { - interactor.onUpdateCreditCard(state.guid, creditCardFields) - } else { - interactor.onSaveCreditCard(creditCardFields) - } + saveCreditCard(state) } card_number_input.text = state.cardNumber.toEditable() @@ -70,6 +64,64 @@ class CreditCardEditorView( bindExpiryYearDropDown(state.expiryYears) } + /** + * Saves a new credit card or updates an existing one with data from the user input. + * + * @param state The state of the [CreditCardEditorFragment] containing the edited credit card + * information. + */ + internal fun saveCreditCard(state: CreditCardEditorState) { + containerView.hideKeyboard() + + if (validateCreditCard()) { + val cardNumber = card_number_input.text.toString().toCreditCardNumber() + + if (state.isEditing) { + val fields = UpdatableCreditCardFields( + billingName = name_on_card_input.text.toString(), + cardNumber = CreditCardNumber.Plaintext(cardNumber), + cardNumberLast4 = cardNumber.last4Digits(), + expiryMonth = (expiry_month_drop_down.selectedItemPosition + 1).toLong(), + expiryYear = expiry_year_drop_down.selectedItem.toString().toLong(), + cardType = cardNumber.creditCardIIN()?.creditCardIssuerNetwork?.name ?: "" + ) + interactor.onUpdateCreditCard(state.guid, fields) + } else { + val fields = NewCreditCardFields( + billingName = name_on_card_input.text.toString(), + plaintextCardNumber = CreditCardNumber.Plaintext(cardNumber), + cardNumberLast4 = cardNumber.last4Digits(), + expiryMonth = (expiry_month_drop_down.selectedItemPosition + 1).toLong(), + expiryYear = expiry_year_drop_down.selectedItem.toString().toLong(), + cardType = cardNumber.creditCardIIN()?.creditCardIssuerNetwork?.name ?: "" + ) + interactor.onSaveCreditCard(fields) + } + } + } + + /** + * Validates the credit card information entered by the user. + * + * @return true if the credit card is valid, false otherwise. + */ + @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE) + internal fun validateCreditCard(): Boolean { + var isValid = true + + if (card_number_input.text.toString().validateCreditCardNumber()) { + card_number_layout.error = null + card_number_title.setTextColor(containerView.context.getColorFromAttr(R.attr.primaryText)) + } else { + card_number_layout.error = + containerView.context.getString(R.string.credit_cards_number_validation_error_message) + card_number_title.setTextColor(containerView.context.getColorFromAttr(R.attr.destructive)) + isValid = false + } + + return isValid + } + /** * Setup the expiry month dropdown by formatting and populating it with the months in a calendar * year, and set the selection to the provided expiry month. @@ -78,7 +130,10 @@ class CreditCardEditorView( */ private fun bindExpiryMonthDropDown(expiryMonth: Int) { val adapter = - ArrayAdapter(containerView.context, R.layout.simple_spinner_dropdown_item) + ArrayAdapter( + containerView.context, + android.R.layout.simple_spinner_dropdown_item + ) val dateFormat = SimpleDateFormat("MMMM (MM)", Locale.getDefault()) val calendar = Calendar.getInstance() @@ -101,7 +156,10 @@ class CreditCardEditorView( */ private fun bindExpiryYearDropDown(expiryYears: Pair) { val adapter = - ArrayAdapter(containerView.context, R.layout.simple_spinner_dropdown_item) + ArrayAdapter( + containerView.context, + android.R.layout.simple_spinner_dropdown_item + ) val (startYear, endYear) = expiryYears for (year in startYear until endYear) { diff --git a/app/src/main/java/org/mozilla/fenix/settings/creditcards/view/CreditCardItemViewHolder.kt b/app/src/main/java/org/mozilla/fenix/settings/creditcards/view/CreditCardItemViewHolder.kt index b5d18ebe0..0e733bfb1 100644 --- a/app/src/main/java/org/mozilla/fenix/settings/creditcards/view/CreditCardItemViewHolder.kt +++ b/app/src/main/java/org/mozilla/fenix/settings/creditcards/view/CreditCardItemViewHolder.kt @@ -7,6 +7,7 @@ package org.mozilla.fenix.settings.creditcards.view import android.view.View import kotlinx.android.synthetic.main.credit_card_list_item.* import mozilla.components.concept.storage.CreditCard +import mozilla.components.support.utils.creditCardIssuerNetwork import org.mozilla.fenix.R import org.mozilla.fenix.settings.creditcards.interactor.CreditCardsManagementInteractor import org.mozilla.fenix.utils.view.ViewHolder @@ -23,7 +24,9 @@ class CreditCardItemViewHolder( ) : ViewHolder(view) { fun bind(creditCard: CreditCard) { - credit_card_number.text = creditCard.cardNumber + credit_card_logo.setImageResource(creditCard.cardType.creditCardIssuerNetwork().icon) + + credit_card_number.text = creditCard.obfuscatedCardNumber bindCreditCardExpiryDate(creditCard) diff --git a/app/src/main/java/org/mozilla/fenix/settings/creditcards/view/CreditCardsManagementView.kt b/app/src/main/java/org/mozilla/fenix/settings/creditcards/view/CreditCardsManagementView.kt index 8bc175076..42b40634d 100644 --- a/app/src/main/java/org/mozilla/fenix/settings/creditcards/view/CreditCardsManagementView.kt +++ b/app/src/main/java/org/mozilla/fenix/settings/creditcards/view/CreditCardsManagementView.kt @@ -31,6 +31,8 @@ class CreditCardsManagementView( adapter = creditCardsAdapter layoutManager = LinearLayoutManager(containerView.context) } + + add_credit_card_button.setOnClickListener { interactor.onAddCreditCardClick() } } /** diff --git a/app/src/main/java/org/mozilla/fenix/settings/logins/fragment/EditLoginFragment.kt b/app/src/main/java/org/mozilla/fenix/settings/logins/fragment/EditLoginFragment.kt index 36b5844db..9a60a4674 100644 --- a/app/src/main/java/org/mozilla/fenix/settings/logins/fragment/EditLoginFragment.kt +++ b/app/src/main/java/org/mozilla/fenix/settings/logins/fragment/EditLoginFragment.kt @@ -266,7 +266,8 @@ class EditLoginFragment : Fragment(R.layout.fragment_edit_login) { override fun onPause() { redirectToReAuth( listOf(R.id.loginDetailFragment), - findNavController().currentDestination?.id + findNavController().currentDestination?.id, + R.id.editLoginFragment ) super.onPause() } diff --git a/app/src/main/java/org/mozilla/fenix/settings/logins/fragment/LoginDetailFragment.kt b/app/src/main/java/org/mozilla/fenix/settings/logins/fragment/LoginDetailFragment.kt index 3826179c0..3daa239f0 100644 --- a/app/src/main/java/org/mozilla/fenix/settings/logins/fragment/LoginDetailFragment.kt +++ b/app/src/main/java/org/mozilla/fenix/settings/logins/fragment/LoginDetailFragment.kt @@ -131,7 +131,8 @@ class LoginDetailFragment : Fragment(R.layout.fragment_login_detail) { menu.close() redirectToReAuth( listOf(R.id.editLoginFragment, R.id.savedLoginsFragment), - findNavController().currentDestination?.id + findNavController().currentDestination?.id, + R.id.loginDetailFragment ) super.onPause() } diff --git a/app/src/main/java/org/mozilla/fenix/settings/logins/fragment/SavedLoginsAuthFragment.kt b/app/src/main/java/org/mozilla/fenix/settings/logins/fragment/SavedLoginsAuthFragment.kt index f92d070d4..a16664790 100644 --- a/app/src/main/java/org/mozilla/fenix/settings/logins/fragment/SavedLoginsAuthFragment.kt +++ b/app/src/main/java/org/mozilla/fenix/settings/logins/fragment/SavedLoginsAuthFragment.kt @@ -53,7 +53,7 @@ class SavedLoginsAuthFragment : PreferenceFragmentCompat() { * https://github.com/mozilla-mobile/fenix/issues/12312 */ private fun togglePrefsEnabledWhileAuthenticating(enabled: Boolean) { - requirePreference(R.string.pref_key_password_sync_logins).isEnabled = enabled + requirePreference(R.string.pref_key_sync_logins).isEnabled = enabled requirePreference(R.string.pref_key_save_logins_settings).isEnabled = enabled requirePreference(R.string.pref_key_saved_logins).isEnabled = enabled } @@ -124,20 +124,19 @@ class SavedLoginsAuthFragment : PreferenceFragmentCompat() { } SyncPreferenceView( - syncPreference = requirePreference(R.string.pref_key_password_sync_logins), + syncPreference = requirePreference(R.string.pref_key_sync_logins), lifecycleOwner = viewLifecycleOwner, accountManager = requireComponents.backgroundServices.accountManager, syncEngine = SyncEngine.Passwords, + loggedOffTitle = requireContext() + .getString(R.string.preferences_passwords_sync_logins_across_devices), + loggedInTitle = requireContext() + .getString(R.string.preferences_passwords_sync_logins), onSignInToSyncClicked = { val directions = SavedLoginsAuthFragmentDirections.actionSavedLoginsAuthFragmentToTurnOnSyncFragment() findNavController().navigateBlockingForAsyncNavGraph(directions) }, - onSyncStatusClicked = { - val directions = - SavedLoginsAuthFragmentDirections.actionGlobalAccountSettingsFragment() - findNavController().navigateBlockingForAsyncNavGraph(directions) - }, onReconnectClicked = { val directions = SavedLoginsAuthFragmentDirections.actionGlobalAccountProblemFragment() @@ -189,7 +188,7 @@ class SavedLoginsAuthFragment : PreferenceFragmentCompat() { } create() }.show().secure(activity) - context.settings().incrementShowLoginsSecureWarningCount() + context.settings().incrementSecureWarningCount() } @Suppress("Deprecation") // This is only used when BiometricPrompt is unavailable diff --git a/app/src/main/java/org/mozilla/fenix/settings/logins/fragment/SavedLoginsFragment.kt b/app/src/main/java/org/mozilla/fenix/settings/logins/fragment/SavedLoginsFragment.kt index 5cc4fbce1..3a3c4f6d9 100644 --- a/app/src/main/java/org/mozilla/fenix/settings/logins/fragment/SavedLoginsFragment.kt +++ b/app/src/main/java/org/mozilla/fenix/settings/logins/fragment/SavedLoginsFragment.kt @@ -148,7 +148,11 @@ class SavedLoginsFragment : Fragment() { sortLoginsMenuRoot.setOnClickListener(null) setHasOptionsMenu(false) - redirectToReAuth(listOf(R.id.loginDetailFragment), findNavController().currentDestination?.id) + redirectToReAuth( + listOf(R.id.loginDetailFragment), + findNavController().currentDestination?.id, + R.id.savedLoginsFragment + ) super.onPause() } diff --git a/app/src/main/java/org/mozilla/fenix/settings/quicksettings/QuickSettingsController.kt b/app/src/main/java/org/mozilla/fenix/settings/quicksettings/QuickSettingsController.kt index c8dbe8ac4..2bacc065d 100644 --- a/app/src/main/java/org/mozilla/fenix/settings/quicksettings/QuickSettingsController.kt +++ b/app/src/main/java/org/mozilla/fenix/settings/quicksettings/QuickSettingsController.kt @@ -6,7 +6,6 @@ package org.mozilla.fenix.settings.quicksettings import android.content.Context import androidx.annotation.VisibleForTesting -import androidx.core.net.toUri import androidx.navigation.NavController import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.launch @@ -17,6 +16,7 @@ import mozilla.components.feature.session.SessionUseCases.ReloadUrlUseCase import mozilla.components.feature.sitepermissions.SitePermissions import mozilla.components.feature.tabs.TabsUseCases.AddNewTabUseCase import mozilla.components.support.base.feature.OnNeedToRequestPermissions +import mozilla.components.support.ktx.kotlin.getOrigin import org.mozilla.fenix.components.PermissionStorage import org.mozilla.fenix.ext.navigateBlockingForAsyncNavGraph import org.mozilla.fenix.settings.PhoneFeature @@ -141,7 +141,7 @@ class DefaultQuickSettingsController( sitePermissions = if (permissions == null) { val tab = browserStore.state.findTabOrCustomTab(sessionId) - val origin = requireNotNull(tab?.content?.url?.toUri()?.host) { + val origin = requireNotNull(tab?.content?.url?.getOrigin()) { "An origin is required to change a autoplay settings from the door hanger" } val sitePermissions = diff --git a/app/src/main/java/org/mozilla/fenix/settings/search/SearchEngineFragment.kt b/app/src/main/java/org/mozilla/fenix/settings/search/SearchEngineFragment.kt index 41d648b57..b519d9c5d 100644 --- a/app/src/main/java/org/mozilla/fenix/settings/search/SearchEngineFragment.kt +++ b/app/src/main/java/org/mozilla/fenix/settings/search/SearchEngineFragment.kt @@ -5,6 +5,7 @@ package org.mozilla.fenix.settings.search import android.os.Bundle +import androidx.core.content.edit import androidx.navigation.fragment.findNavController import androidx.preference.CheckBoxPreference import androidx.preference.Preference @@ -18,6 +19,7 @@ import org.mozilla.fenix.ext.settings import org.mozilla.fenix.ext.showToolbar import org.mozilla.fenix.settings.SharedPreferenceUpdater import org.mozilla.fenix.settings.requirePreference +import org.mozilla.gecko.search.SearchWidgetProvider class SearchEngineFragment : PreferenceFragmentCompat() { @@ -83,7 +85,16 @@ class SearchEngineFragment : PreferenceFragmentCompat() { showSyncedTabsSuggestions.onPreferenceChangeListener = SharedPreferenceUpdater() showClipboardSuggestions.onPreferenceChangeListener = SharedPreferenceUpdater() searchSuggestionsInPrivatePreference.onPreferenceChangeListener = SharedPreferenceUpdater() - showVoiceSearchPreference.onPreferenceChangeListener = SharedPreferenceUpdater() + showVoiceSearchPreference.onPreferenceChangeListener = object : Preference.OnPreferenceChangeListener { + override fun onPreferenceChange(preference: Preference, newValue: Any?): Boolean { + val newBooleanValue = newValue as? Boolean ?: return false + requireContext().settings().preferences.edit { + putBoolean(preference.key, newBooleanValue) + } + SearchWidgetProvider.updateAllWidgets(requireContext()) + return true + } + } autocompleteURLsPreference.onPreferenceChangeListener = SharedPreferenceUpdater() searchSuggestionsPreference.setOnPreferenceClickListener { diff --git a/app/src/main/java/org/mozilla/fenix/settings/sitepermissions/Extensions.kt b/app/src/main/java/org/mozilla/fenix/settings/sitepermissions/Extensions.kt index 4f459f84e..dd31f5feb 100644 --- a/app/src/main/java/org/mozilla/fenix/settings/sitepermissions/Extensions.kt +++ b/app/src/main/java/org/mozilla/fenix/settings/sitepermissions/Extensions.kt @@ -6,8 +6,8 @@ package org.mozilla.fenix.settings.sitepermissions import android.view.View import android.widget.TextView -import androidx.core.net.toUri import androidx.core.text.HtmlCompat +import mozilla.components.support.ktx.kotlin.getOrigin import org.mozilla.fenix.R import org.mozilla.fenix.components.Components import org.mozilla.fenix.settings.PhoneFeature @@ -23,7 +23,7 @@ import org.mozilla.fenix.settings.PhoneFeature internal fun Components.tryReloadTabBy(origin: String) { core.store.state.tabs .sortedByDescending { it.lastAccess } - .find { it.content.url.toUri().host == origin } + .find { it.content.url.getOrigin() == origin } ?.let { useCases.sessionUseCases.reload(it.id) } diff --git a/app/src/main/java/org/mozilla/fenix/settings/sitepermissions/SitePermissionsDetailsExceptionsFragment.kt b/app/src/main/java/org/mozilla/fenix/settings/sitepermissions/SitePermissionsDetailsExceptionsFragment.kt index 49b7cdb43..76d0774f3 100644 --- a/app/src/main/java/org/mozilla/fenix/settings/sitepermissions/SitePermissionsDetailsExceptionsFragment.kt +++ b/app/src/main/java/org/mozilla/fenix/settings/sitepermissions/SitePermissionsDetailsExceptionsFragment.kt @@ -18,6 +18,7 @@ import kotlinx.coroutines.Dispatchers.Main import kotlinx.coroutines.launch import kotlinx.coroutines.withContext import mozilla.components.feature.sitepermissions.SitePermissions +import mozilla.components.support.ktx.kotlin.stripDefaultPort import org.mozilla.fenix.R import org.mozilla.fenix.ext.components import org.mozilla.fenix.ext.navigateBlockingForAsyncNavGraph @@ -55,7 +56,7 @@ class SitePermissionsDetailsExceptionsFragment : PreferenceFragmentCompat() { override fun onResume() { super.onResume() - showToolbar(sitePermissions.origin) + showToolbar(sitePermissions.origin.stripDefaultPort()) viewLifecycleOwner.lifecycleScope.launch(Main) { sitePermissions = requireNotNull(requireComponents.core.permissionStorage.findSitePermissionsBy(sitePermissions.origin)) diff --git a/app/src/main/java/org/mozilla/fenix/settings/sitepermissions/SitePermissionsExceptionsFragment.kt b/app/src/main/java/org/mozilla/fenix/settings/sitepermissions/SitePermissionsExceptionsFragment.kt index 2b73d4da2..d8bbc1eda 100644 --- a/app/src/main/java/org/mozilla/fenix/settings/sitepermissions/SitePermissionsExceptionsFragment.kt +++ b/app/src/main/java/org/mozilla/fenix/settings/sitepermissions/SitePermissionsExceptionsFragment.kt @@ -27,6 +27,7 @@ import androidx.recyclerview.widget.RecyclerView import kotlinx.coroutines.Dispatchers.Main import kotlinx.coroutines.launch import mozilla.components.feature.sitepermissions.SitePermissions +import mozilla.components.support.ktx.kotlin.stripDefaultPort import org.mozilla.fenix.NavHostActivity import org.mozilla.fenix.R import org.mozilla.fenix.ext.components @@ -142,9 +143,8 @@ class ExceptionsAdapter(private val clickListener: View.OnClickListener) : override fun onBindViewHolder(holder: SitePermissionsViewHolder, position: Int) { val sitePermissions = requireNotNull(getItem(position)) val context = holder.view.context - - context.components.core.icons.loadIntoView(holder.iconView, "https://${sitePermissions.origin}/") - holder.siteTextView.text = sitePermissions.origin + context.components.core.icons.loadIntoView(holder.iconView, sitePermissions.origin) + holder.siteTextView.text = sitePermissions.origin.stripDefaultPort() holder.view.tag = sitePermissions holder.view.setOnClickListener(clickListener) } diff --git a/app/src/main/java/org/mozilla/fenix/sync/SyncedTabsViewHolder.kt b/app/src/main/java/org/mozilla/fenix/sync/SyncedTabsViewHolder.kt index 375cec1e6..3b45a1e66 100644 --- a/app/src/main/java/org/mozilla/fenix/sync/SyncedTabsViewHolder.kt +++ b/app/src/main/java/org/mozilla/fenix/sync/SyncedTabsViewHolder.kt @@ -87,7 +87,7 @@ sealed class SyncedTabsViewHolder(itemView: View) : RecyclerView.ViewHolder(item } itemView.synced_tabs_group_name.text = device.device.displayName - itemView.synced_tabs_group_name.setCompoundDrawablesWithIntrinsicBounds( + itemView.synced_tabs_group_name.setCompoundDrawablesRelativeWithIntrinsicBounds( deviceLogoDrawable, 0, 0, diff --git a/app/src/main/java/org/mozilla/fenix/tabstray/AccessibleNewTabButtonBinding.kt b/app/src/main/java/org/mozilla/fenix/tabstray/AccessibleNewTabButtonBinding.kt new file mode 100644 index 000000000..9c1c3f4e0 --- /dev/null +++ b/app/src/main/java/org/mozilla/fenix/tabstray/AccessibleNewTabButtonBinding.kt @@ -0,0 +1,94 @@ +/* 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 org.mozilla.fenix.tabstray + +import android.view.View +import android.widget.ImageButton +import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.collect +import kotlinx.coroutines.flow.map +import mozilla.components.lib.state.helpers.AbstractBinding +import mozilla.components.support.ktx.kotlinx.coroutines.flow.ifAnyChanged +import org.mozilla.fenix.R +import org.mozilla.fenix.tabstray.browser.BrowserTrayInteractor +import org.mozilla.fenix.utils.Settings + +/** + * Do not show accessible new tab button when accessibility service is disabled + * + * This binding is coupled with [FloatingActionButtonBinding]. + * When [FloatingActionButtonBinding] is visible this should not be visible + */ +@OptIn(ExperimentalCoroutinesApi::class) +class AccessibleNewTabButtonBinding( + private val store: TabsTrayStore, + private val settings: Settings, + private val newTabButton: ImageButton, + private val browserTrayInteractor: BrowserTrayInteractor +) : AbstractBinding(store) { + + override fun start() { + if (!settings.accessibilityServicesEnabled) { + newTabButton.visibility = View.GONE + return + } + super.start() + } + + override suspend fun onState(flow: Flow) { + flow.map { it } + .ifAnyChanged { state -> + arrayOf( + state.selectedPage, + state.syncing + ) + } + .collect { state -> + setAccessibleNewTabButton(state.selectedPage, state.syncing) + } + } + + private fun setAccessibleNewTabButton(selectedPage: Page, syncing: Boolean) { + when (selectedPage) { + Page.NormalTabs -> { + newTabButton.apply { + visibility = View.VISIBLE + setImageResource(R.drawable.ic_new) + setOnClickListener { + browserTrayInteractor.onFabClicked(false) + } + } + } + Page.PrivateTabs -> { + newTabButton.apply { + visibility = View.VISIBLE + setImageResource(R.drawable.ic_new) + setOnClickListener { + browserTrayInteractor.onFabClicked(true) + } + } + } + Page.SyncedTabs -> { + newTabButton.apply { + visibility = + when (syncing) { + true -> View.GONE + false -> View.VISIBLE + } + + setImageResource(R.drawable.ic_fab_sync) + setOnClickListener { + // Notify the store observers (one of which is the SyncedTabsFeature), that + // a sync was requested. + if (!syncing) { + store.dispatch(TabsTrayAction.SyncNow) + } + } + } + } + } + } +} diff --git a/app/src/main/java/org/mozilla/fenix/tabstray/CloseOnLastTabBinding.kt b/app/src/main/java/org/mozilla/fenix/tabstray/CloseOnLastTabBinding.kt index d19958375..4c989709c 100644 --- a/app/src/main/java/org/mozilla/fenix/tabstray/CloseOnLastTabBinding.kt +++ b/app/src/main/java/org/mozilla/fenix/tabstray/CloseOnLastTabBinding.kt @@ -4,6 +4,7 @@ package org.mozilla.fenix.tabstray +import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.collect import kotlinx.coroutines.flow.drop @@ -12,12 +13,13 @@ import mozilla.components.browser.state.selector.normalTabs import mozilla.components.browser.state.selector.privateTabs import mozilla.components.browser.state.state.BrowserState import mozilla.components.browser.state.store.BrowserStore +import mozilla.components.lib.state.helpers.AbstractBinding import mozilla.components.support.ktx.kotlinx.coroutines.flow.ifChanged -import org.mozilla.fenix.components.AbstractBinding /** * A binding that closes the tabs tray when the last tab is closed. */ +@OptIn(ExperimentalCoroutinesApi::class) class CloseOnLastTabBinding( browserStore: BrowserStore, private val tabsTrayStore: TabsTrayStore, diff --git a/app/src/main/java/org/mozilla/fenix/tabstray/FloatingActionButtonBinding.kt b/app/src/main/java/org/mozilla/fenix/tabstray/FloatingActionButtonBinding.kt index 42d925368..e72e022c5 100644 --- a/app/src/main/java/org/mozilla/fenix/tabstray/FloatingActionButtonBinding.kt +++ b/app/src/main/java/org/mozilla/fenix/tabstray/FloatingActionButtonBinding.kt @@ -4,46 +4,50 @@ package org.mozilla.fenix.tabstray -import androidx.appcompat.content.res.AppCompatResources import com.google.android.material.floatingactionbutton.ExtendedFloatingActionButton -import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.ExperimentalCoroutinesApi -import kotlinx.coroutines.cancel +import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.collect import kotlinx.coroutines.flow.map -import mozilla.components.lib.state.ext.flowScoped -import mozilla.components.support.base.feature.LifecycleAwareFeature +import mozilla.components.lib.state.helpers.AbstractBinding import mozilla.components.support.ktx.kotlinx.coroutines.flow.ifAnyChanged import org.mozilla.fenix.R import org.mozilla.fenix.tabstray.browser.BrowserTrayInteractor +import org.mozilla.fenix.utils.Settings +/** + * Do not show fab when accessibility service is enabled + * + * This binding is coupled with [AccessibleNewTabButtonBinding]. + * When [AccessibleNewTabButtonBinding] is visible this should not be visible + */ +@OptIn(ExperimentalCoroutinesApi::class) class FloatingActionButtonBinding( private val store: TabsTrayStore, + private val settings: Settings, private val actionButton: ExtendedFloatingActionButton, private val browserTrayInteractor: BrowserTrayInteractor -) : LifecycleAwareFeature { +) : AbstractBinding(store) { - private var scope: CoroutineScope? = null - - @OptIn(ExperimentalCoroutinesApi::class) override fun start() { - setFab(store.state.selectedPage, store.state.syncing) - scope = store.flowScoped { flow -> - flow.map { it } - .ifAnyChanged { state -> - arrayOf( - state.selectedPage, - state.syncing - ) - } - .collect { state -> - setFab(state.selectedPage, state.syncing) - } + if (settings.accessibilityServicesEnabled) { + actionButton.hide() + return } + super.start() } - override fun stop() { - scope?.cancel() + override suspend fun onState(flow: Flow) { + flow.map { it } + .ifAnyChanged { state -> + arrayOf( + state.selectedPage, + state.syncing + ) + } + .collect { state -> + setFab(state.selectedPage, state.syncing) + } } private fun setFab(selectedPage: Page, syncing: Boolean) { @@ -52,7 +56,7 @@ class FloatingActionButtonBinding( actionButton.apply { shrink() show() - icon = AppCompatResources.getDrawable(context, R.drawable.ic_new) + setIconResource(R.drawable.ic_new) setOnClickListener { browserTrayInteractor.onFabClicked(false) } @@ -60,10 +64,10 @@ class FloatingActionButtonBinding( } Page.PrivateTabs -> { actionButton.apply { - text = context.getText(R.string.tab_drawer_fab_content) + setText(R.string.tab_drawer_fab_content) extend() show() - icon = AppCompatResources.getDrawable(context, R.drawable.ic_new) + setIconResource(R.drawable.ic_new) setOnClickListener { browserTrayInteractor.onFabClicked(true) } @@ -71,11 +75,15 @@ class FloatingActionButtonBinding( } Page.SyncedTabs -> { actionButton.apply { - text = if (syncing) context.getText(R.string.sync_syncing_in_progress) - else context.getText(R.string.tab_drawer_fab_sync) + setText( + when (syncing) { + true -> R.string.sync_syncing_in_progress + false -> R.string.tab_drawer_fab_sync + } + ) extend() show() - icon = AppCompatResources.getDrawable(context, R.drawable.ic_fab_sync) + setIconResource(R.drawable.ic_fab_sync) setOnClickListener { // Notify the store observers (one of which is the SyncedTabsFeature), that // a sync was requested. diff --git a/app/src/main/java/org/mozilla/fenix/tabstray/MenuIntegration.kt b/app/src/main/java/org/mozilla/fenix/tabstray/MenuIntegration.kt index 2a1630204..15c1a5424 100644 --- a/app/src/main/java/org/mozilla/fenix/tabstray/MenuIntegration.kt +++ b/app/src/main/java/org/mozilla/fenix/tabstray/MenuIntegration.kt @@ -15,11 +15,11 @@ import org.mozilla.fenix.utils.Do * A wrapper class that building the tabs tray menu that handles item clicks. */ class MenuIntegration( - private val context: Context, - private val browserStore: BrowserStore, - private val tabsTrayStore: TabsTrayStore, - private val tabLayout: TabLayout, - private val navigationInteractor: NavigationInteractor + @VisibleForTesting internal val context: Context, + @VisibleForTesting internal val browserStore: BrowserStore, + @VisibleForTesting internal val tabsTrayStore: TabsTrayStore, + @VisibleForTesting internal val tabLayout: TabLayout, + @VisibleForTesting internal val navigationInteractor: NavigationInteractor ) { private val tabsTrayItemMenu by lazy { TabsTrayMenu( diff --git a/app/src/main/java/org/mozilla/fenix/tabstray/NavigationInteractor.kt b/app/src/main/java/org/mozilla/fenix/tabstray/NavigationInteractor.kt index c88c42d94..d619eda80 100644 --- a/app/src/main/java/org/mozilla/fenix/tabstray/NavigationInteractor.kt +++ b/app/src/main/java/org/mozilla/fenix/tabstray/NavigationInteractor.kt @@ -7,7 +7,6 @@ package org.mozilla.fenix.tabstray import android.content.Context import androidx.navigation.NavController import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.launch import mozilla.components.browser.state.selector.getNormalOrPrivateTabs @@ -28,6 +27,7 @@ import org.mozilla.fenix.components.metrics.MetricController import org.mozilla.fenix.ext.navigateBlockingForAsyncNavGraph import org.mozilla.fenix.home.HomeFragment import org.mozilla.fenix.tabstray.ext.getTabSessionState +import kotlin.coroutines.CoroutineContext /** * An interactor that helps with navigating to different parts of the app from the tabs tray. @@ -100,10 +100,12 @@ class DefaultNavigationInteractor( private val bookmarksUseCase: BookmarksUseCase, private val tabsTrayStore: TabsTrayStore, private val collectionStorage: TabCollectionStorage, - private val accountManager: FxaAccountManager + private val accountManager: FxaAccountManager, + private val ioDispatcher: CoroutineContext ) : NavigationInteractor { override fun onTabTrayDismissed() { + metrics.track(Event.TabsTrayClosed) dismissTabTray() } @@ -190,14 +192,13 @@ class DefaultNavigationInteractor( override fun onSaveToBookmarks(tabs: Collection) { tabs.forEach { tab -> // We don't combine the context with lifecycleScope so that our jobs are not cancelled - // if we leave the fragment, i.e. we still want the bookmarks to be added. - CoroutineScope(Dispatchers.IO).launch { + // if we leave the fragment, i.e. we still want the bookmarks to be added if the + // tabs tray closes before the job is done. + CoroutineScope(ioDispatcher).launch { bookmarksUseCase.addBookmark(tab.url, tab.title) } } - tabsTrayStore.dispatch(TabsTrayAction.ExitSelectMode) - // TODO show successful snackbar here (regardless of operation success). } diff --git a/app/src/main/java/org/mozilla/fenix/tabstray/TabCounterBinding.kt b/app/src/main/java/org/mozilla/fenix/tabstray/TabCounterBinding.kt index e6b833c7d..0c50f9b50 100644 --- a/app/src/main/java/org/mozilla/fenix/tabstray/TabCounterBinding.kt +++ b/app/src/main/java/org/mozilla/fenix/tabstray/TabCounterBinding.kt @@ -4,41 +4,31 @@ package org.mozilla.fenix.tabstray -import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.ExperimentalCoroutinesApi -import kotlinx.coroutines.cancel +import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.collect import kotlinx.coroutines.flow.map import mozilla.components.browser.state.selector.normalTabs import mozilla.components.browser.state.state.BrowserState import mozilla.components.browser.state.store.BrowserStore -import mozilla.components.lib.state.ext.flowScoped -import mozilla.components.support.base.feature.LifecycleAwareFeature +import mozilla.components.lib.state.helpers.AbstractBinding import mozilla.components.support.ktx.kotlinx.coroutines.flow.ifChanged import mozilla.components.ui.tabcounter.TabCounter /** * Updates the tab counter to the size of [BrowserState.normalTabs]. */ +@OptIn(ExperimentalCoroutinesApi::class) class TabCounterBinding( private val store: BrowserStore, private val counter: TabCounter -) : LifecycleAwareFeature { +) : AbstractBinding(store) { - private var scope: CoroutineScope? = null - - @OptIn(ExperimentalCoroutinesApi::class) - override fun start() { - scope = store.flowScoped { flow -> - flow.map { it.normalTabs } - .ifChanged() - .collect { - counter.setCount(it.size) - } - } - } - - override fun stop() { - scope?.cancel() + override suspend fun onState(flow: Flow) { + flow.map { it.normalTabs } + .ifChanged() + .collect { + counter.setCount(it.size) + } } } diff --git a/app/src/main/java/org/mozilla/fenix/tabstray/TabLayoutMediator.kt b/app/src/main/java/org/mozilla/fenix/tabstray/TabLayoutMediator.kt index 8e27666f7..4bfeabe2b 100644 --- a/app/src/main/java/org/mozilla/fenix/tabstray/TabLayoutMediator.kt +++ b/app/src/main/java/org/mozilla/fenix/tabstray/TabLayoutMediator.kt @@ -78,7 +78,7 @@ internal class TabLayoutObserver( true } - interactor.setCurrentTrayPosition(tab.position, animate) + interactor.onTrayPositionSelected(tab.position, animate) Do exhaustive when (Page.positionToPage(tab.position)) { Page.NormalTabs -> metrics.track(Event.TabsTrayNormalModeTapped) diff --git a/app/src/main/java/org/mozilla/fenix/tabstray/TabsTrayController.kt b/app/src/main/java/org/mozilla/fenix/tabstray/TabsTrayController.kt index 0999ad47e..138e36ff6 100644 --- a/app/src/main/java/org/mozilla/fenix/tabstray/TabsTrayController.kt +++ b/app/src/main/java/org/mozilla/fenix/tabstray/TabsTrayController.kt @@ -4,37 +4,76 @@ package org.mozilla.fenix.tabstray +import androidx.annotation.VisibleForTesting import androidx.navigation.NavController -import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.ExperimentalCoroutinesApi +import mozilla.components.browser.state.selector.findTab +import mozilla.components.browser.state.selector.getNormalOrPrivateTabs +import mozilla.components.browser.state.store.BrowserStore import mozilla.components.concept.base.profiler.Profiler -import mozilla.components.service.fxa.manager.FxaAccountManager +import mozilla.components.concept.tabstray.Tab +import mozilla.components.feature.tabs.TabsUseCases +import org.mozilla.fenix.R import org.mozilla.fenix.browser.browsingmode.BrowsingMode import org.mozilla.fenix.browser.browsingmode.BrowsingModeManager import org.mozilla.fenix.components.metrics.Event import org.mozilla.fenix.components.metrics.MetricController import org.mozilla.fenix.ext.navigateBlockingForAsyncNavGraph +import org.mozilla.fenix.home.HomeFragment import org.mozilla.fenix.tabtray.TabTrayDialogFragmentDirections interface TabsTrayController { /** - * Called when user clicks the new tab button. + * Called to open a new tab. */ - fun onNewTabTapped(isPrivate: Boolean) + fun handleOpeningNewTab(isPrivate: Boolean) + + /** + * Set the current tray item to the clamped [position]. + * + * @param position The position on the tray to focus. + * @param smoothScroll If true, animate the scrolling from the current tab to [position]. + */ + fun handleTrayScrollingToPosition(position: Int, smoothScroll: Boolean) + + /** + * Navigate from TabsTray to Browser. + */ + fun handleNavigateToBrowser() + + /** + * Deletes the [Tab] with the specified [tabId]. + * + * @param tabId The id of the [Tab] to be removed from TabsTray. + */ + fun handleTabDeletion(tabId: String) + + /** + * Deletes a list of [tabs]. + * + * @param tabs List of [Tab]s (sessions) to be removed. + */ + fun handleMultipleTabsDeletion(tabs: Collection) } class DefaultTabsTrayController( - private val store: TabsTrayStore, + private val trayStore: TabsTrayStore, + private val browserStore: BrowserStore, private val browsingModeManager: BrowsingModeManager, private val navController: NavController, + private val navigateToHomeAndDeleteSession: (String) -> Unit, private val profiler: Profiler?, private val navigationInteractor: NavigationInteractor, private val metrics: MetricController, - private val ioScope: CoroutineScope, - private val accountManager: FxaAccountManager + private val tabsUseCases: TabsUseCases, + private val selectTabPosition: (Int, Boolean) -> Unit, + private val dismissTray: () -> Unit, + private val showUndoSnackbarForTab: (Boolean) -> Unit + ) : TabsTrayController { - override fun onNewTabTapped(isPrivate: Boolean) { + override fun handleOpeningNewTab(isPrivate: Boolean) { val startTime = profiler?.getProfilerTime() browsingModeManager.mode = BrowsingMode.fromBoolean(isPrivate) navController.navigateBlockingForAsyncNavGraph( @@ -47,7 +86,67 @@ class DefaultTabsTrayController( sendNewTabEvent(isPrivate) } - private fun sendNewTabEvent(isPrivateModeSelected: Boolean) { + override fun handleTrayScrollingToPosition(position: Int, smoothScroll: Boolean) { + selectTabPosition(position, smoothScroll) + trayStore.dispatch(TabsTrayAction.PageSelected(Page.positionToPage(position))) + } + + /** + * Dismisses the tabs tray and navigates to the browser. + */ + override fun handleNavigateToBrowser() { + dismissTray() + + if (navController.currentDestination?.id == R.id.browserFragment) { + return + } else if (!navController.popBackStack(R.id.browserFragment, false)) { + navController.navigateBlockingForAsyncNavGraph(R.id.browserFragment) + } + } + + /** + * Deletes the [Tab] with the specified [tabId]. + * + * @param tabId The id of the [Tab] to be removed from TabsTray. + * This method has no effect if the tab does not exist. + */ + override fun handleTabDeletion(tabId: String) { + val tab = browserStore.state.findTab(tabId) + + tab?.let { + if (browserStore.state.getNormalOrPrivateTabs(it.content.private).size != 1) { + tabsUseCases.removeTab(tabId) + showUndoSnackbarForTab(it.content.private) + } else { + dismissTabsTrayAndNavigateHome(tabId) + } + } + } + + /** + * Deletes a list of [tabs] offering an undo option. + * + * @param tabs List of [Tab]s (sessions) to be removed. This method has no effect for tabs that do not exist. + */ + @ExperimentalCoroutinesApi + override fun handleMultipleTabsDeletion(tabs: Collection) { + val isPrivate = tabs.any { it.private } + + // If user closes all the tabs from selected tabs page dismiss tray and navigate home. + if (tabs.size == browserStore.state.getNormalOrPrivateTabs(isPrivate).size) { + dismissTabsTrayAndNavigateHome( + if (isPrivate) HomeFragment.ALL_PRIVATE_TABS else HomeFragment.ALL_NORMAL_TABS + ) + } else { + tabs.map { it.id }.let { + tabsUseCases.removeTabs(it) + } + } + showUndoSnackbarForTab(isPrivate) + } + + @VisibleForTesting + internal fun sendNewTabEvent(isPrivateModeSelected: Boolean) { val eventToSend = if (isPrivateModeSelected) { Event.NewPrivateTabTapped } else { @@ -56,4 +155,10 @@ class DefaultTabsTrayController( metrics.track(eventToSend) } + + @VisibleForTesting + internal fun dismissTabsTrayAndNavigateHome(sessionId: String) { + dismissTray() + navigateToHomeAndDeleteSession(sessionId) + } } diff --git a/app/src/main/java/org/mozilla/fenix/tabstray/TabsTrayFragment.kt b/app/src/main/java/org/mozilla/fenix/tabstray/TabsTrayFragment.kt index bae954a3b..c067fd0c2 100644 --- a/app/src/main/java/org/mozilla/fenix/tabstray/TabsTrayFragment.kt +++ b/app/src/main/java/org/mozilla/fenix/tabstray/TabsTrayFragment.kt @@ -10,13 +10,15 @@ import android.os.Bundle import android.view.LayoutInflater import android.view.View import android.view.ViewGroup +import androidx.annotation.VisibleForTesting import androidx.appcompat.app.AppCompatDialogFragment import androidx.constraintlayout.widget.ConstraintLayout +import androidx.core.view.isVisible import androidx.fragment.app.activityViewModels import androidx.lifecycle.lifecycleScope import androidx.navigation.fragment.findNavController import com.google.android.material.bottomsheet.BottomSheetBehavior -import kotlinx.android.synthetic.main.component_tabstray.view.* +import com.google.android.material.tabs.TabLayout import kotlinx.android.synthetic.main.component_tabstray2.* import kotlinx.android.synthetic.main.component_tabstray2.view.* import kotlinx.android.synthetic.main.component_tabstray2.view.tab_tray_overflow @@ -25,15 +27,10 @@ import kotlinx.android.synthetic.main.component_tabstray_fab.* import kotlinx.android.synthetic.main.fragment_tab_tray_dialog.* import kotlinx.android.synthetic.main.tabs_tray_tab_counter2.* import kotlinx.android.synthetic.main.tabstray_multiselect_items.* -import kotlinx.android.synthetic.main.tabstray_multiselect_items.view.* import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.plus -import mozilla.components.browser.state.selector.findTab -import mozilla.components.browser.state.selector.getNormalOrPrivateTabs import mozilla.components.browser.state.selector.normalTabs import mozilla.components.browser.state.selector.privateTabs -import mozilla.components.browser.state.state.TabSessionState -import mozilla.components.concept.tabstray.Tab +import mozilla.components.browser.state.store.BrowserStore import mozilla.components.support.base.feature.ViewBoundFeatureWrapper import org.mozilla.fenix.HomeActivity import org.mozilla.fenix.NavGraphDirections @@ -50,23 +47,24 @@ import org.mozilla.fenix.tabstray.browser.DefaultBrowserTrayInteractor import org.mozilla.fenix.tabstray.browser.SelectionHandleBinding import org.mozilla.fenix.tabstray.browser.SelectionBannerBinding import org.mozilla.fenix.tabstray.browser.SelectionBannerBinding.VisibilityModifier -import org.mozilla.fenix.tabstray.ext.getTrayPosition import org.mozilla.fenix.tabstray.ext.showWithTheme import org.mozilla.fenix.utils.allowUndo import kotlin.math.max @Suppress("TooManyFunctions", "LargeClass") -class TabsTrayFragment : AppCompatDialogFragment(), TabsTrayInteractor { +class TabsTrayFragment : AppCompatDialogFragment() { private var fabView: View? = null - private lateinit var tabsTrayStore: TabsTrayStore + @VisibleForTesting internal lateinit var tabsTrayStore: TabsTrayStore private lateinit var browserTrayInteractor: BrowserTrayInteractor + private lateinit var tabsTrayInteractor: TabsTrayInteractor private lateinit var tabsTrayController: DefaultTabsTrayController private lateinit var behavior: BottomSheetBehavior private val tabLayoutMediator = ViewBoundFeatureWrapper() private val tabCounterBinding = ViewBoundFeatureWrapper() private val floatingActionButtonBinding = ViewBoundFeatureWrapper() + private val newTabButtonBinding = ViewBoundFeatureWrapper() private val selectionBannerBinding = ViewBoundFeatureWrapper() private val selectionHandleBinding = ViewBoundFeatureWrapper() private val tabsTrayCtaBinding = ViewBoundFeatureWrapper() @@ -117,23 +115,30 @@ class TabsTrayFragment : AppCompatDialogFragment(), TabsTrayInteractor { dismissTabTrayAndNavigateHome = ::dismissTabsTrayAndNavigateHome, bookmarksUseCase = requireComponents.useCases.bookmarksUseCases, collectionStorage = requireComponents.core.tabCollectionStorage, - accountManager = requireComponents.backgroundServices.accountManager + accountManager = requireComponents.backgroundServices.accountManager, + ioDispatcher = Dispatchers.IO ) tabsTrayController = DefaultTabsTrayController( - store = tabsTrayStore, + trayStore = tabsTrayStore, + browserStore = requireComponents.core.store, browsingModeManager = activity.browsingModeManager, navController = findNavController(), + navigateToHomeAndDeleteSession = ::navigateToHomeAndDeleteSession, navigationInteractor = navigationInteractor, profiler = requireComponents.core.engine.profiler, - accountManager = requireComponents.backgroundServices.accountManager, metrics = requireComponents.analytics.metrics, - ioScope = lifecycleScope + Dispatchers.IO + tabsUseCases = requireComponents.useCases.tabsUseCases, + selectTabPosition = ::selectTabPosition, + dismissTray = ::dismissTabsTray, + showUndoSnackbarForTab = ::showUndoSnackbarForTab ) + tabsTrayInteractor = DefaultTabsTrayInteractor(tabsTrayController) + browserTrayInteractor = DefaultBrowserTrayInteractor( tabsTrayStore, - this@TabsTrayFragment, + tabsTrayInteractor, tabsTrayController, requireComponents.useCases.tabsUseCases.selectTab, requireComponents.settings, @@ -144,7 +149,7 @@ class TabsTrayFragment : AppCompatDialogFragment(), TabsTrayInteractor { setupPager( view.context, tabsTrayStore, - this, + tabsTrayInteractor, browserTrayInteractor, navigationInteractor ) @@ -184,7 +189,7 @@ class TabsTrayFragment : AppCompatDialogFragment(), TabsTrayInteractor { tabLayoutMediator.set( feature = TabLayoutMediator( tabLayout = tab_layout, - interactor = this, + interactor = tabsTrayInteractor, browsingModeManager = activity.browsingModeManager, tabsTrayStore = tabsTrayStore, metrics = requireComponents.analytics.metrics @@ -204,6 +209,7 @@ class TabsTrayFragment : AppCompatDialogFragment(), TabsTrayInteractor { floatingActionButtonBinding.set( feature = FloatingActionButtonBinding( store = tabsTrayStore, + settings = requireComponents.settings, actionButton = new_tab_button, browserTrayInteractor = browserTrayInteractor ), @@ -211,12 +217,23 @@ class TabsTrayFragment : AppCompatDialogFragment(), TabsTrayInteractor { view = view ) + newTabButtonBinding.set( + feature = AccessibleNewTabButtonBinding( + store = tabsTrayStore, + settings = requireComponents.settings, + newTabButton = tab_tray_new_tab, + browserTrayInteractor = browserTrayInteractor + ), + owner = this, + view = view + ) + selectionBannerBinding.set( feature = SelectionBannerBinding( context = requireContext(), store = tabsTrayStore, navInteractor = navigationInteractor, - tabsTrayInteractor = this, + tabsTrayInteractor = tabsTrayInteractor, containerView = view, backgroundView = topBar, showOnSelectViews = VisibilityModifier( @@ -247,49 +264,10 @@ class TabsTrayFragment : AppCompatDialogFragment(), TabsTrayInteractor { ) } - override fun setCurrentTrayPosition(position: Int, smoothScroll: Boolean) { - tabsTray.setCurrentItem(position, smoothScroll) - tab_layout.getTabAt(position)?.select() - tabsTrayStore.dispatch(TabsTrayAction.PageSelected(Page.positionToPage(position))) - } - - override fun navigateToBrowser() { - dismissTabsTray() - - val navController = findNavController() - - if (navController.currentDestination?.id == R.id.browserFragment) { - return - } - - if (!navController.popBackStack(R.id.browserFragment, false)) { - navController.navigateBlockingForAsyncNavGraph(R.id.browserFragment) - } - } - - override fun onDeleteTab(tabId: String) { - val browserStore = requireComponents.core.store - val tab = browserStore.state.findTab(tabId) - - tab?.let { - if (browserStore.state.getNormalOrPrivateTabs(it.content.private).size != 1) { - requireComponents.useCases.tabsUseCases.removeTab(tabId) - showUndoSnackbarForTab(it) - } else { - dismissTabsTrayAndNavigateHome(tabId) - } - } - } - - override fun onDeleteTabs(tabs: Collection) { - tabs.forEach { - onDeleteTab(it.id) - } - } - - private fun showUndoSnackbarForTab(removedTab: TabSessionState) { + @VisibleForTesting + internal fun showUndoSnackbarForTab(isPrivate: Boolean) { val snackbarMessage = - when (removedTab.content.private) { + when (isPrivate) { true -> getString(R.string.snackbar_private_tab_closed) false -> getString(R.string.snackbar_tab_closed) } @@ -300,15 +278,18 @@ class TabsTrayFragment : AppCompatDialogFragment(), TabsTrayInteractor { getString(R.string.snackbar_deleted_undo), { requireComponents.useCases.tabsUseCases.undo.invoke() - tabLayoutMediator.withFeature { it.selectTabAtPosition(removedTab.getTrayPosition()) } + tabLayoutMediator.withFeature { it.selectTabAtPosition( + if (isPrivate) Page.PrivateTabs.ordinal else Page.NormalTabs.ordinal + ) } }, operation = { }, elevation = ELEVATION, - anchorView = new_tab_button + anchorView = if (new_tab_button.isVisible) new_tab_button else null ) } - private fun setupPager( + @VisibleForTesting + internal fun setupPager( context: Context, store: TabsTrayStore, trayInteractor: TabsTrayInteractor, @@ -328,12 +309,13 @@ class TabsTrayFragment : AppCompatDialogFragment(), TabsTrayInteractor { } } - private fun setupMenu(view: View, navigationInteractor: NavigationInteractor) { + @VisibleForTesting + internal fun setupMenu(view: View, navigationInteractor: NavigationInteractor) { view.tab_tray_overflow.setOnClickListener { anchor -> requireComponents.analytics.metrics.track(Event.TabsTrayMenuOpened) - val menu = MenuIntegration( + val menu = getTrayMenu( context = requireContext(), browserStore = requireComponents.core.store, tabsTrayStore = tabsTrayStore, @@ -345,23 +327,47 @@ class TabsTrayFragment : AppCompatDialogFragment(), TabsTrayInteractor { } } - private fun setupBackgroundDismissalListener(block: (View) -> Unit) { + @VisibleForTesting + internal fun getTrayMenu( + context: Context, + browserStore: BrowserStore, + tabsTrayStore: TabsTrayStore, + tabLayout: TabLayout, + navigationInteractor: NavigationInteractor + ) = MenuIntegration(context, browserStore, tabsTrayStore, tabLayout, navigationInteractor) + + @VisibleForTesting + internal fun setupBackgroundDismissalListener(block: (View) -> Unit) { tabLayout.setOnClickListener(block) handle.setOnClickListener(block) } - private val homeViewModel: HomeScreenViewModel by activityViewModels() + @VisibleForTesting + internal fun dismissTabsTrayAndNavigateHome(sessionId: String) { + navigateToHomeAndDeleteSession(sessionId) + dismissTabsTray() + } + + internal val homeViewModel: HomeScreenViewModel by activityViewModels() - private fun dismissTabsTrayAndNavigateHome(sessionId: String) { + @VisibleForTesting + internal fun navigateToHomeAndDeleteSession(sessionId: String) { homeViewModel.sessionToDelete = sessionId val directions = NavGraphDirections.actionGlobalHome() findNavController().navigateBlockingForAsyncNavGraph(directions) - dismissTabsTray() } - private fun dismissTabsTray() { + @VisibleForTesting + internal fun selectTabPosition(position: Int, smoothScroll: Boolean) { + tabsTray.setCurrentItem(position, smoothScroll) + tab_layout.getTabAt(position)?.select() + } + + @VisibleForTesting + internal fun dismissTabsTray() { + // This should always be the last thing we do because nothing (e.g. telemetry) + // is guaranteed after that. dismissAllowingStateLoss() - requireComponents.analytics.metrics.track(Event.TabsTrayClosed) } companion object { @@ -372,6 +378,7 @@ class TabsTrayFragment : AppCompatDialogFragment(), TabsTrayInteractor { private const val EXPAND_AT_GRID_SIZE = 3 // Elevation for undo toasts - private const val ELEVATION = 80f + @VisibleForTesting + internal const val ELEVATION = 80f } } diff --git a/app/src/main/java/org/mozilla/fenix/tabstray/TabsTrayInfoBannerBinding.kt b/app/src/main/java/org/mozilla/fenix/tabstray/TabsTrayInfoBannerBinding.kt index a1251f37e..be92f2105 100644 --- a/app/src/main/java/org/mozilla/fenix/tabstray/TabsTrayInfoBannerBinding.kt +++ b/app/src/main/java/org/mozilla/fenix/tabstray/TabsTrayInfoBannerBinding.kt @@ -9,16 +9,15 @@ import android.view.View.VISIBLE import android.view.ViewGroup import androidx.annotation.VisibleForTesting import kotlin.math.max -import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.ExperimentalCoroutinesApi -import kotlinx.coroutines.cancel +import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.collect import kotlinx.coroutines.flow.map import mozilla.components.browser.state.selector.normalTabs import mozilla.components.browser.state.selector.privateTabs +import mozilla.components.browser.state.state.BrowserState import mozilla.components.browser.state.store.BrowserStore -import mozilla.components.lib.state.ext.flowScoped -import mozilla.components.support.base.feature.LifecycleAwareFeature +import mozilla.components.lib.state.helpers.AbstractBinding import mozilla.components.support.ktx.kotlinx.coroutines.flow.ifChanged import org.mozilla.fenix.R import org.mozilla.fenix.browser.infobanner.InfoBanner @@ -26,34 +25,27 @@ import org.mozilla.fenix.components.metrics.Event import org.mozilla.fenix.components.metrics.MetricController import org.mozilla.fenix.utils.Settings +@OptIn(ExperimentalCoroutinesApi::class) class TabsTrayInfoBannerBinding( private val context: Context, - private val store: BrowserStore, + store: BrowserStore, private val infoBannerView: ViewGroup, private val settings: Settings, private val navigationInteractor: NavigationInteractor, private val metrics: MetricController? -) : LifecycleAwareFeature { - private var scope: CoroutineScope? = null +) : AbstractBinding(store) { @VisibleForTesting internal var banner: InfoBanner? = null - @ExperimentalCoroutinesApi - override fun start() { - scope = store.flowScoped { flow -> - flow.map { state -> max(state.normalTabs.size, state.privateTabs.size) } - .ifChanged() - .collect { tabCount -> - if (tabCount >= TAB_COUNT_SHOW_CFR) { - displayInfoBannerIfNeeded(settings) - } + override suspend fun onState(flow: Flow) { + flow.map { state -> max(state.normalTabs.size, state.privateTabs.size) } + .ifChanged() + .collect { tabCount -> + if (tabCount >= TAB_COUNT_SHOW_CFR) { + displayInfoBannerIfNeeded(settings) } - } - } - - override fun stop() { - scope?.cancel() + } } private fun displayInfoBannerIfNeeded(settings: Settings) { diff --git a/app/src/main/java/org/mozilla/fenix/tabstray/TabsTrayInteractor.kt b/app/src/main/java/org/mozilla/fenix/tabstray/TabsTrayInteractor.kt index 5c3a7371a..f8223e4b6 100644 --- a/app/src/main/java/org/mozilla/fenix/tabstray/TabsTrayInteractor.kt +++ b/app/src/main/java/org/mozilla/fenix/tabstray/TabsTrayInteractor.kt @@ -13,12 +13,12 @@ interface TabsTrayInteractor { * @param position The position on the tray to focus. * @param smoothScroll If true, animate the scrolling from the current tab to [position]. */ - fun setCurrentTrayPosition(position: Int, smoothScroll: Boolean) + fun onTrayPositionSelected(position: Int, smoothScroll: Boolean) /** * Dismisses the tabs tray and navigates to the browser. */ - fun navigateToBrowser() + fun onBrowserTabSelected() /** * Invoked when a tab is removed from the tabs tray with the given [tabId]. @@ -30,3 +30,28 @@ interface TabsTrayInteractor { */ fun onDeleteTabs(tabs: Collection) } + +/** + * Interactor to be called for any tabs tray user actions. + * + * @property controller [TabsTrayController] to which user actions can be delegated for actual app update. + */ +class DefaultTabsTrayInteractor( + private val controller: TabsTrayController +) : TabsTrayInteractor { + override fun onTrayPositionSelected(position: Int, smoothScroll: Boolean) { + controller.handleTrayScrollingToPosition(position, smoothScroll) + } + + override fun onBrowserTabSelected() { + controller.handleNavigateToBrowser() + } + + override fun onDeleteTab(tabId: String) { + controller.handleTabDeletion(tabId) + } + + override fun onDeleteTabs(tabs: Collection) { + controller.handleMultipleTabsDeletion(tabs) + } +} diff --git a/app/src/main/java/org/mozilla/fenix/tabstray/TrayItem.kt b/app/src/main/java/org/mozilla/fenix/tabstray/TrayItem.kt deleted file mode 100644 index 032a63492..000000000 --- a/app/src/main/java/org/mozilla/fenix/tabstray/TrayItem.kt +++ /dev/null @@ -1,13 +0,0 @@ -/* 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 org.mozilla.fenix.tabstray - -import android.view.View -import android.view.ViewGroup - -/** - * A [View] or [ViewGroup] that can be add in the Tabs Tray. - */ -interface TrayItem diff --git a/app/src/main/java/org/mozilla/fenix/tabstray/TrayPagerAdapter.kt b/app/src/main/java/org/mozilla/fenix/tabstray/TrayPagerAdapter.kt index 7b72b8144..43d74280e 100644 --- a/app/src/main/java/org/mozilla/fenix/tabstray/TrayPagerAdapter.kt +++ b/app/src/main/java/org/mozilla/fenix/tabstray/TrayPagerAdapter.kt @@ -7,6 +7,7 @@ package org.mozilla.fenix.tabstray import android.content.Context import android.view.LayoutInflater import android.view.ViewGroup +import androidx.annotation.VisibleForTesting import androidx.recyclerview.widget.RecyclerView import mozilla.components.browser.state.selector.normalTabs import mozilla.components.browser.state.selector.privateTabs @@ -16,48 +17,48 @@ import org.mozilla.fenix.sync.SyncedTabsAdapter import org.mozilla.fenix.tabstray.browser.BrowserTabsAdapter import org.mozilla.fenix.tabstray.browser.BrowserTrayInteractor import org.mozilla.fenix.tabstray.syncedtabs.TabClickDelegate -import org.mozilla.fenix.tabstray.viewholders.AbstractTrayViewHolder -import org.mozilla.fenix.tabstray.viewholders.NormalBrowserTabViewHolder -import org.mozilla.fenix.tabstray.viewholders.PrivateBrowserTabViewHolder -import org.mozilla.fenix.tabstray.viewholders.SyncedTabViewHolder +import org.mozilla.fenix.tabstray.viewholders.AbstractPageViewHolder +import org.mozilla.fenix.tabstray.viewholders.NormalBrowserPageViewHolder +import org.mozilla.fenix.tabstray.viewholders.PrivateBrowserPageViewHolder +import org.mozilla.fenix.tabstray.viewholders.SyncedTabsPageViewHolder class TrayPagerAdapter( - private val context: Context, - private val store: TabsTrayStore, - private val browserInteractor: BrowserTrayInteractor, - private val navInteractor: NavigationInteractor, - private val interactor: TabsTrayInteractor, - private val browserStore: BrowserStore -) : RecyclerView.Adapter() { + @VisibleForTesting internal val context: Context, + @VisibleForTesting internal val store: TabsTrayStore, + @VisibleForTesting internal val browserInteractor: BrowserTrayInteractor, + @VisibleForTesting internal val navInteractor: NavigationInteractor, + @VisibleForTesting internal val interactor: TabsTrayInteractor, + @VisibleForTesting internal val browserStore: BrowserStore +) : RecyclerView.Adapter() { private val normalAdapter by lazy { BrowserTabsAdapter(context, browserInteractor, store) } private val privateAdapter by lazy { BrowserTabsAdapter(context, browserInteractor, store) } private val syncedTabsAdapter by lazy { SyncedTabsAdapter(TabClickDelegate(navInteractor)) } - override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): AbstractTrayViewHolder { + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): AbstractPageViewHolder { val itemView = LayoutInflater.from(parent.context).inflate(viewType, parent, false) val selectedTab = browserStore.state.selectedTab return when (viewType) { - NormalBrowserTabViewHolder.LAYOUT_ID -> { - NormalBrowserTabViewHolder( + NormalBrowserPageViewHolder.LAYOUT_ID -> { + NormalBrowserPageViewHolder( itemView, store, interactor, browserStore.state.normalTabs.indexOf(selectedTab) ) } - PrivateBrowserTabViewHolder.LAYOUT_ID -> { - PrivateBrowserTabViewHolder( + PrivateBrowserPageViewHolder.LAYOUT_ID -> { + PrivateBrowserPageViewHolder( itemView, store, interactor, browserStore.state.privateTabs.indexOf(selectedTab) ) } - SyncedTabViewHolder.LAYOUT_ID -> { - SyncedTabViewHolder( + SyncedTabsPageViewHolder.LAYOUT_ID -> { + SyncedTabsPageViewHolder( itemView, store ) @@ -66,7 +67,7 @@ class TrayPagerAdapter( } } - override fun onBindViewHolder(viewHolder: AbstractTrayViewHolder, position: Int) { + override fun onBindViewHolder(viewHolder: AbstractPageViewHolder, position: Int) { val adapter = when (position) { POSITION_NORMAL_TABS -> normalAdapter POSITION_PRIVATE_TABS -> privateAdapter @@ -78,9 +79,9 @@ class TrayPagerAdapter( override fun getItemViewType(position: Int): Int { return when (position) { - POSITION_NORMAL_TABS -> NormalBrowserTabViewHolder.LAYOUT_ID - POSITION_PRIVATE_TABS -> PrivateBrowserTabViewHolder.LAYOUT_ID - POSITION_SYNCED_TABS -> SyncedTabViewHolder.LAYOUT_ID + POSITION_NORMAL_TABS -> NormalBrowserPageViewHolder.LAYOUT_ID + POSITION_PRIVATE_TABS -> PrivateBrowserPageViewHolder.LAYOUT_ID + POSITION_SYNCED_TABS -> SyncedTabsPageViewHolder.LAYOUT_ID else -> throw IllegalStateException("Unknown position.") } } diff --git a/app/src/main/java/org/mozilla/fenix/tabstray/TabsTrayViewHolder.kt b/app/src/main/java/org/mozilla/fenix/tabstray/browser/AbstractBrowserTabViewHolder.kt similarity index 97% rename from app/src/main/java/org/mozilla/fenix/tabstray/TabsTrayViewHolder.kt rename to app/src/main/java/org/mozilla/fenix/tabstray/browser/AbstractBrowserTabViewHolder.kt index e0c443526..75b0ba9ea 100644 --- a/app/src/main/java/org/mozilla/fenix/tabstray/TabsTrayViewHolder.kt +++ b/app/src/main/java/org/mozilla/fenix/tabstray/browser/AbstractBrowserTabViewHolder.kt @@ -2,7 +2,7 @@ * 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 org.mozilla.fenix.tabstray +package org.mozilla.fenix.tabstray.browser import android.view.View import android.widget.ImageButton @@ -37,13 +37,14 @@ import org.mozilla.fenix.ext.showAndEnable import org.mozilla.fenix.ext.toShortUrl import org.mozilla.fenix.selection.SelectionHolder import org.mozilla.fenix.selection.SelectionInteractor -import org.mozilla.fenix.tabstray.browser.BrowserTrayInteractor +import org.mozilla.fenix.tabstray.TabsTrayState +import org.mozilla.fenix.tabstray.TabsTrayStore import org.mozilla.fenix.tabstray.ext.isSelect /** * A RecyclerView ViewHolder implementation for "tab" items. */ -abstract class TabsTrayViewHolder( +abstract class AbstractBrowserTabViewHolder( itemView: View, private val imageLoader: ImageLoader, private val trayStore: TabsTrayStore, diff --git a/app/src/main/java/org/mozilla/fenix/tabstray/browser/TabsTrayGridViewHolder.kt b/app/src/main/java/org/mozilla/fenix/tabstray/browser/BrowserTabGridViewHolder.kt similarity index 93% rename from app/src/main/java/org/mozilla/fenix/tabstray/browser/TabsTrayGridViewHolder.kt rename to app/src/main/java/org/mozilla/fenix/tabstray/browser/BrowserTabGridViewHolder.kt index 51915b03d..3257df562 100644 --- a/app/src/main/java/org/mozilla/fenix/tabstray/browser/TabsTrayGridViewHolder.kt +++ b/app/src/main/java/org/mozilla/fenix/tabstray/browser/BrowserTabGridViewHolder.kt @@ -16,20 +16,19 @@ import org.mozilla.fenix.R import org.mozilla.fenix.ext.increaseTapArea import kotlin.math.max import kotlinx.android.synthetic.main.tab_tray_grid_item.view.tab_tray_grid_item -import org.mozilla.fenix.tabstray.TabsTrayViewHolder import org.mozilla.fenix.selection.SelectionHolder import org.mozilla.fenix.tabstray.TabsTrayStore /** * A RecyclerView ViewHolder implementation for "tab" items with grid layout. */ -class TabsTrayGridViewHolder( +class BrowserTabGridViewHolder( imageLoader: ImageLoader, override val browserTrayInteractor: BrowserTrayInteractor, store: TabsTrayStore, selectionHolder: SelectionHolder? = null, itemView: View -) : TabsTrayViewHolder(itemView, imageLoader, store, selectionHolder) { +) : AbstractBrowserTabViewHolder(itemView, imageLoader, store, selectionHolder) { private val closeButton: AppCompatImageButton = itemView.findViewById(R.id.mozac_browser_tabstray_close) diff --git a/app/src/main/java/org/mozilla/fenix/tabstray/browser/TabsTrayListViewHolder.kt b/app/src/main/java/org/mozilla/fenix/tabstray/browser/BrowserTabListViewHolder.kt similarity index 90% rename from app/src/main/java/org/mozilla/fenix/tabstray/browser/TabsTrayListViewHolder.kt rename to app/src/main/java/org/mozilla/fenix/tabstray/browser/BrowserTabListViewHolder.kt index cc65f6846..da3f13ba8 100644 --- a/app/src/main/java/org/mozilla/fenix/tabstray/browser/TabsTrayListViewHolder.kt +++ b/app/src/main/java/org/mozilla/fenix/tabstray/browser/BrowserTabListViewHolder.kt @@ -9,7 +9,6 @@ import androidx.core.content.ContextCompat import mozilla.components.concept.base.images.ImageLoader import mozilla.components.concept.tabstray.Tab import org.mozilla.fenix.R -import org.mozilla.fenix.tabstray.TabsTrayViewHolder import org.mozilla.fenix.selection.SelectionHolder import org.mozilla.fenix.tabstray.TabsTrayStore import kotlin.math.max @@ -17,13 +16,13 @@ import kotlin.math.max /** * A RecyclerView ViewHolder implementation for "tab" items with list layout. */ -class TabsTrayListViewHolder( +class BrowserTabListViewHolder( imageLoader: ImageLoader, override val browserTrayInteractor: BrowserTrayInteractor, store: TabsTrayStore, selectionHolder: SelectionHolder? = null, itemView: View -) : TabsTrayViewHolder(itemView, imageLoader, store, selectionHolder) { +) : AbstractBrowserTabViewHolder(itemView, imageLoader, store, selectionHolder) { override val thumbnailSize: Int get() = max( itemView.resources.getDimensionPixelSize(R.dimen.tab_tray_list_item_thumbnail_height), diff --git a/app/src/main/java/org/mozilla/fenix/tabstray/browser/BrowserTabsAdapter.kt b/app/src/main/java/org/mozilla/fenix/tabstray/browser/BrowserTabsAdapter.kt index 3eb5550f3..b69f845bf 100644 --- a/app/src/main/java/org/mozilla/fenix/tabstray/browser/BrowserTabsAdapter.kt +++ b/app/src/main/java/org/mozilla/fenix/tabstray/browser/BrowserTabsAdapter.kt @@ -20,7 +20,6 @@ import org.mozilla.fenix.R import org.mozilla.fenix.ext.components import org.mozilla.fenix.selection.SelectionHolder import org.mozilla.fenix.tabstray.TabsTrayStore -import org.mozilla.fenix.tabstray.TabsTrayViewHolder /** * A [RecyclerView.Adapter] for browser tabs. @@ -30,7 +29,7 @@ class BrowserTabsAdapter( private val interactor: BrowserTrayInteractor, private val store: TabsTrayStore, delegate: Observable = ObserverRegistry() -) : TabsAdapter(delegate) { +) : TabsAdapter(delegate) { /** * The layout types for the tabs. @@ -56,18 +55,18 @@ class BrowserTabsAdapter( } } - override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): TabsTrayViewHolder { + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): AbstractBrowserTabViewHolder { val view = LayoutInflater.from(parent.context).inflate(viewType, parent, false) return when (viewType) { ViewType.GRID.layoutRes -> - TabsTrayGridViewHolder(imageLoader, interactor, store, selectionHolder, view) + BrowserTabGridViewHolder(imageLoader, interactor, store, selectionHolder, view) else -> - TabsTrayListViewHolder(imageLoader, interactor, store, selectionHolder, view) + BrowserTabListViewHolder(imageLoader, interactor, store, selectionHolder, view) } } - override fun onBindViewHolder(holder: TabsTrayViewHolder, position: Int) { + override fun onBindViewHolder(holder: AbstractBrowserTabViewHolder, position: Int) { super.onBindViewHolder(holder, position) holder.tab?.let { tab -> @@ -85,7 +84,7 @@ class BrowserTabsAdapter( * Over-ridden [onBindViewHolder] that uses the payloads to notify the selected tab how to * display itself. */ - override fun onBindViewHolder(holder: TabsTrayViewHolder, position: Int, payloads: List) { + override fun onBindViewHolder(holder: AbstractBrowserTabViewHolder, position: Int, payloads: List) { val tabs = tabs ?: return if (tabs.list.isEmpty()) return diff --git a/app/src/main/java/org/mozilla/fenix/tabstray/browser/BrowserTrayInteractor.kt b/app/src/main/java/org/mozilla/fenix/tabstray/browser/BrowserTrayInteractor.kt index 49cb4784d..ec03088f2 100644 --- a/app/src/main/java/org/mozilla/fenix/tabstray/browser/BrowserTrayInteractor.kt +++ b/app/src/main/java/org/mozilla/fenix/tabstray/browser/BrowserTrayInteractor.kt @@ -22,7 +22,7 @@ import org.mozilla.fenix.tabstray.TabsTrayState.Mode import org.mozilla.fenix.tabstray.TabsTrayStore /** - * For interacting with UI that is specifically for [BaseBrowserTrayList] and other browser + * For interacting with UI that is specifically for [BrowserTrayList] and other browser * tab tray views. */ interface BrowserTrayInteractor : SelectionInteractor, UserInteractionHandler { @@ -57,7 +57,7 @@ class DefaultBrowserTrayInteractor( private val selectTabWrapper by lazy { SelectTabUseCaseWrapper(metrics, selectTab) { - trayInteractor.navigateToBrowser() + trayInteractor.onBrowserTabSelected() } } @@ -73,7 +73,6 @@ class DefaultBrowserTrayInteractor( */ override fun open(item: Tab) { selectTabWrapper.invoke(item.id) - trayInteractor.navigateToBrowser() } /** @@ -133,6 +132,6 @@ class DefaultBrowserTrayInteractor( * See [BrowserTrayInteractor.onFabClicked] */ override fun onFabClicked(isPrivate: Boolean) { - controller.onNewTabTapped(isPrivate) + controller.handleOpeningNewTab(isPrivate) } } diff --git a/app/src/main/java/org/mozilla/fenix/tabstray/browser/BaseBrowserTrayList.kt b/app/src/main/java/org/mozilla/fenix/tabstray/browser/BrowserTrayList.kt similarity index 85% rename from app/src/main/java/org/mozilla/fenix/tabstray/browser/BaseBrowserTrayList.kt rename to app/src/main/java/org/mozilla/fenix/tabstray/browser/BrowserTrayList.kt index 81029500f..4d561ed76 100644 --- a/app/src/main/java/org/mozilla/fenix/tabstray/browser/BaseBrowserTrayList.kt +++ b/app/src/main/java/org/mozilla/fenix/tabstray/browser/BrowserTrayList.kt @@ -12,27 +12,20 @@ import mozilla.components.feature.tabs.tabstray.TabsFeature import org.mozilla.fenix.ext.components import org.mozilla.fenix.tabstray.TabsTrayInteractor import org.mozilla.fenix.tabstray.TabsTrayStore -import org.mozilla.fenix.tabstray.TrayItem import org.mozilla.fenix.tabstray.ext.filterFromConfig -abstract class BaseBrowserTrayList @JvmOverloads constructor( +class BrowserTrayList @JvmOverloads constructor( context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0 -) : RecyclerView(context, attrs, defStyleAttr), TrayItem { +) : RecyclerView(context, attrs, defStyleAttr) { /** * The browser tab types we would want to show. */ enum class BrowserTabType { NORMAL, PRIVATE } - /** - * A configuration for classes that extend [BaseBrowserTrayList]. - */ - data class Configuration(val browserTabType: BrowserTabType) - - abstract val configuration: Configuration - + lateinit var browserTabType: BrowserTabType lateinit var interactor: TabsTrayInteractor lateinit var tabsTrayStore: TabsTrayStore @@ -43,7 +36,7 @@ abstract class BaseBrowserTrayList @JvmOverloads constructor( context.components.analytics.metrics, context.components.useCases.tabsUseCases.selectTab ) { - interactor.navigateToBrowser() + interactor.onBrowserTabSelected() } val removeTabUseCase = RemoveTabUseCaseWrapper( @@ -57,7 +50,7 @@ abstract class BaseBrowserTrayList @JvmOverloads constructor( context.components.core.store, selectTabUseCase, removeTabUseCase, - { it.filterFromConfig(configuration) }, + { it.filterFromConfig(browserTabType) }, { } ) } diff --git a/app/src/main/java/org/mozilla/fenix/tabstray/browser/NormalBrowserTrayList.kt b/app/src/main/java/org/mozilla/fenix/tabstray/browser/NormalBrowserTrayList.kt deleted file mode 100644 index eed7f8586..000000000 --- a/app/src/main/java/org/mozilla/fenix/tabstray/browser/NormalBrowserTrayList.kt +++ /dev/null @@ -1,19 +0,0 @@ -/* 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 org.mozilla.fenix.tabstray.browser - -import android.content.Context -import android.util.AttributeSet - -/** - * A browser tabs list that displays normal tabs. - */ -class NormalBrowserTrayList @JvmOverloads constructor( - context: Context, - attrs: AttributeSet? = null, - defStyleAttr: Int = 0 -) : BaseBrowserTrayList(context, attrs, defStyleAttr) { - override val configuration: Configuration = Configuration(BrowserTabType.NORMAL) -} diff --git a/app/src/main/java/org/mozilla/fenix/tabstray/browser/PrivateBrowserTrayList.kt b/app/src/main/java/org/mozilla/fenix/tabstray/browser/PrivateBrowserTrayList.kt deleted file mode 100644 index 0b8f73e72..000000000 --- a/app/src/main/java/org/mozilla/fenix/tabstray/browser/PrivateBrowserTrayList.kt +++ /dev/null @@ -1,19 +0,0 @@ -/* 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 org.mozilla.fenix.tabstray.browser - -import android.content.Context -import android.util.AttributeSet - -/** - * A browser tabs list that displays private tabs. - */ -class PrivateBrowserTrayList @JvmOverloads constructor( - context: Context, - attrs: AttributeSet? = null, - defStyleAttr: Int = 0 -) : BaseBrowserTrayList(context, attrs, defStyleAttr) { - override val configuration: Configuration = Configuration(BrowserTabType.PRIVATE) -} diff --git a/app/src/main/java/org/mozilla/fenix/tabstray/browser/SelectedItemAdapterBinding.kt b/app/src/main/java/org/mozilla/fenix/tabstray/browser/SelectedItemAdapterBinding.kt index a725364dc..cfb785a6e 100644 --- a/app/src/main/java/org/mozilla/fenix/tabstray/browser/SelectedItemAdapterBinding.kt +++ b/app/src/main/java/org/mozilla/fenix/tabstray/browser/SelectedItemAdapterBinding.kt @@ -4,44 +4,36 @@ package org.mozilla.fenix.tabstray.browser -import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.ExperimentalCoroutinesApi -import kotlinx.coroutines.cancel +import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.collect import kotlinx.coroutines.flow.drop import kotlinx.coroutines.flow.map import mozilla.components.browser.tabstray.TabsAdapter.Companion.PAYLOAD_DONT_HIGHLIGHT_SELECTED_ITEM import mozilla.components.browser.tabstray.TabsAdapter.Companion.PAYLOAD_HIGHLIGHT_SELECTED_ITEM -import mozilla.components.lib.state.ext.flowScoped -import mozilla.components.support.base.feature.LifecycleAwareFeature +import mozilla.components.lib.state.helpers.AbstractBinding import mozilla.components.support.ktx.kotlinx.coroutines.flow.ifChanged +import org.mozilla.fenix.tabstray.TabsTrayState import org.mozilla.fenix.tabstray.TabsTrayState.Mode import org.mozilla.fenix.tabstray.TabsTrayStore /** * Notifies the adapter when the selection mode changes. */ +@OptIn(ExperimentalCoroutinesApi::class) class SelectedItemAdapterBinding( - val store: TabsTrayStore, + store: TabsTrayStore, val adapter: BrowserTabsAdapter -) : LifecycleAwareFeature { - private var scope: CoroutineScope? = null +) : AbstractBinding(store) { - @OptIn(ExperimentalCoroutinesApi::class) - override fun start() { - scope = store.flowScoped { flow -> - flow.map { it.mode } - // ignore initial mode update; the adapter is already in an updated state. - .drop(1) - .ifChanged() - .collect { mode -> - notifyAdapter(mode) - } - } - } - - override fun stop() { - scope?.cancel() + override suspend fun onState(flow: Flow) { + flow.map { it.mode } + // ignore initial mode update; the adapter is already in an updated state. + .drop(1) + .ifChanged() + .collect { mode -> + notifyAdapter(mode) + } } private fun notifyAdapter(mode: Mode) = with(adapter) { diff --git a/app/src/main/java/org/mozilla/fenix/tabstray/browser/SelectionBannerBinding.kt b/app/src/main/java/org/mozilla/fenix/tabstray/browser/SelectionBannerBinding.kt index 8850049a4..0bf301d0a 100644 --- a/app/src/main/java/org/mozilla/fenix/tabstray/browser/SelectionBannerBinding.kt +++ b/app/src/main/java/org/mozilla/fenix/tabstray/browser/SelectionBannerBinding.kt @@ -12,13 +12,14 @@ import androidx.core.view.isVisible import kotlinx.android.synthetic.main.component_tabstray2.view.exit_multi_select import kotlinx.android.synthetic.main.component_tabstray2.view.multiselect_title import kotlinx.android.synthetic.main.tabstray_multiselect_items.view.* +import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.collect import kotlinx.coroutines.flow.drop import kotlinx.coroutines.flow.map +import mozilla.components.lib.state.helpers.AbstractBinding import mozilla.components.support.ktx.kotlinx.coroutines.flow.ifChanged import org.mozilla.fenix.R -import org.mozilla.fenix.components.AbstractBinding import org.mozilla.fenix.tabstray.NavigationInteractor import org.mozilla.fenix.tabstray.TabsTrayInteractor import org.mozilla.fenix.tabstray.TabsTrayState @@ -41,6 +42,7 @@ import org.mozilla.fenix.tabstray.ext.showWithTheme * @property showOnSelectViews A variable list of views that will be made visible when in select mode. * @property showOnNormalViews A variable list of views that will be made visible when in normal mode. */ +@OptIn(ExperimentalCoroutinesApi::class) @Suppress("LongParameterList") class SelectionBannerBinding( private val context: Context, diff --git a/app/src/main/java/org/mozilla/fenix/tabstray/browser/SelectionHandleBinding.kt b/app/src/main/java/org/mozilla/fenix/tabstray/browser/SelectionHandleBinding.kt index 6560b8d93..0e850a1d2 100644 --- a/app/src/main/java/org/mozilla/fenix/tabstray/browser/SelectionHandleBinding.kt +++ b/app/src/main/java/org/mozilla/fenix/tabstray/browser/SelectionHandleBinding.kt @@ -10,13 +10,14 @@ import androidx.constraintlayout.widget.ConstraintLayout import androidx.constraintlayout.widget.ConstraintSet import androidx.core.content.ContextCompat import androidx.core.view.updateLayoutParams +import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.collect import kotlinx.coroutines.flow.drop import kotlinx.coroutines.flow.map +import mozilla.components.lib.state.helpers.AbstractBinding import mozilla.components.support.ktx.kotlinx.coroutines.flow.ifChanged import org.mozilla.fenix.R -import org.mozilla.fenix.components.AbstractBinding import org.mozilla.fenix.tabstray.TabsTrayState import org.mozilla.fenix.tabstray.TabsTrayState.Mode import org.mozilla.fenix.tabstray.TabsTrayStore @@ -31,6 +32,7 @@ private const val NORMAL_HANDLE_PERCENT_WIDTH = 0.1F * @property handle The "handle" of the Tabs Tray that is used to drag the tray open/close. * @property containerLayout The [ConstraintLayout] that contains the "handle". */ +@OptIn(ExperimentalCoroutinesApi::class) class SelectionHandleBinding( store: TabsTrayStore, private val handle: View, diff --git a/app/src/main/java/org/mozilla/fenix/tabstray/browser/SelectionMenuIntegration.kt b/app/src/main/java/org/mozilla/fenix/tabstray/browser/SelectionMenuIntegration.kt index a865ebae7..40fee99e8 100644 --- a/app/src/main/java/org/mozilla/fenix/tabstray/browser/SelectionMenuIntegration.kt +++ b/app/src/main/java/org/mozilla/fenix/tabstray/browser/SelectionMenuIntegration.kt @@ -8,6 +8,7 @@ import android.content.Context import androidx.annotation.VisibleForTesting import mozilla.components.browser.menu.BrowserMenuBuilder import org.mozilla.fenix.tabstray.NavigationInteractor +import org.mozilla.fenix.tabstray.TabsTrayAction import org.mozilla.fenix.tabstray.TabsTrayInteractor import org.mozilla.fenix.tabstray.TabsTrayStore import org.mozilla.fenix.utils.Do @@ -30,12 +31,14 @@ class SelectionMenuIntegration( @VisibleForTesting internal fun handleMenuClicked(item: SelectionMenu.Item) { Do exhaustive when (item) { - is SelectionMenu.Item.BookmarkTabs -> navInteractor.onSaveToBookmarks( - store.state.mode.selectedTabs - ) - is SelectionMenu.Item.DeleteTabs -> trayInteractor.onDeleteTabs( - store.state.mode.selectedTabs - ) + is SelectionMenu.Item.BookmarkTabs -> { + navInteractor.onSaveToBookmarks(store.state.mode.selectedTabs) + store.dispatch(TabsTrayAction.ExitSelectMode) + } + is SelectionMenu.Item.DeleteTabs -> { + trayInteractor.onDeleteTabs(store.state.mode.selectedTabs) + store.dispatch(TabsTrayAction.ExitSelectMode) + } } } } diff --git a/app/src/main/java/org/mozilla/fenix/tabstray/browser/SwipeToDeleteBinding.kt b/app/src/main/java/org/mozilla/fenix/tabstray/browser/SwipeToDeleteBinding.kt index fd7052e81..b5276ecd5 100644 --- a/app/src/main/java/org/mozilla/fenix/tabstray/browser/SwipeToDeleteBinding.kt +++ b/app/src/main/java/org/mozilla/fenix/tabstray/browser/SwipeToDeleteBinding.kt @@ -4,13 +4,11 @@ package org.mozilla.fenix.tabstray.browser -import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.ExperimentalCoroutinesApi -import kotlinx.coroutines.cancel +import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.collect import kotlinx.coroutines.flow.map -import mozilla.components.lib.state.ext.flowScoped -import mozilla.components.support.base.feature.LifecycleAwareFeature +import mozilla.components.lib.state.helpers.AbstractBinding import mozilla.components.support.ktx.kotlinx.coroutines.flow.ifChanged import org.mozilla.fenix.tabstray.TabsTrayState import org.mozilla.fenix.tabstray.TabsTrayStore @@ -18,25 +16,18 @@ import org.mozilla.fenix.tabstray.TabsTrayStore /** * Notifies whether a tab is accessible for using the swipe-to-delete gesture. */ +@OptIn(ExperimentalCoroutinesApi::class) class SwipeToDeleteBinding( private val store: TabsTrayStore -) : LifecycleAwareFeature { - private var scope: CoroutineScope? = null +) : AbstractBinding(store) { var isSwipeable = false private set - @OptIn(ExperimentalCoroutinesApi::class) - override fun start() { - scope = store.flowScoped { flow -> - flow.map { it.mode } - .ifChanged() - .collect { mode -> - isSwipeable = mode == TabsTrayState.Mode.Normal - } - } - } - - override fun stop() { - scope?.cancel() + override suspend fun onState(flow: Flow) { + flow.map { it.mode } + .ifChanged() + .collect { mode -> + isSwipeable = mode == TabsTrayState.Mode.Normal + } } } diff --git a/app/src/main/java/org/mozilla/fenix/tabstray/ext/TabSessionState.kt b/app/src/main/java/org/mozilla/fenix/tabstray/ext/TabSessionState.kt index 777e4f47e..663fb6e21 100644 --- a/app/src/main/java/org/mozilla/fenix/tabstray/ext/TabSessionState.kt +++ b/app/src/main/java/org/mozilla/fenix/tabstray/ext/TabSessionState.kt @@ -6,17 +6,17 @@ package org.mozilla.fenix.tabstray.ext import mozilla.components.browser.state.state.TabSessionState import org.mozilla.fenix.tabstray.Page -import org.mozilla.fenix.tabstray.browser.BaseBrowserTrayList.BrowserTabType.PRIVATE -import org.mozilla.fenix.tabstray.browser.BaseBrowserTrayList.Configuration +import org.mozilla.fenix.tabstray.browser.BrowserTrayList.BrowserTabType +import org.mozilla.fenix.tabstray.browser.BrowserTrayList.BrowserTabType.PRIVATE -fun TabSessionState.filterFromConfig(configuration: Configuration): Boolean { - val isPrivate = configuration.browserTabType == PRIVATE +fun TabSessionState.filterFromConfig(type: BrowserTabType): Boolean { + val isPrivate = type == PRIVATE return content.private == isPrivate } fun TabSessionState.getTrayPosition(): Int = when (content.private) { - true -> Page.NormalTabs.ordinal + true -> Page.PrivateTabs.ordinal false -> Page.NormalTabs.ordinal } diff --git a/app/src/main/java/org/mozilla/fenix/tabstray/syncedtabs/SyncButtonBinding.kt b/app/src/main/java/org/mozilla/fenix/tabstray/syncedtabs/SyncButtonBinding.kt index e07c7008f..435286584 100644 --- a/app/src/main/java/org/mozilla/fenix/tabstray/syncedtabs/SyncButtonBinding.kt +++ b/app/src/main/java/org/mozilla/fenix/tabstray/syncedtabs/SyncButtonBinding.kt @@ -4,12 +4,13 @@ package org.mozilla.fenix.tabstray.syncedtabs +import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.collect import kotlinx.coroutines.flow.map import mozilla.components.feature.syncedtabs.view.SyncedTabsView +import mozilla.components.lib.state.helpers.AbstractBinding import mozilla.components.support.ktx.kotlinx.coroutines.flow.ifChanged -import org.mozilla.fenix.components.AbstractBinding import org.mozilla.fenix.tabstray.TabsTrayState import org.mozilla.fenix.tabstray.TabsTrayStore @@ -19,6 +20,7 @@ import org.mozilla.fenix.tabstray.TabsTrayStore * * This binding is useful for connecting with [SyncedTabsView.Listener]. */ +@OptIn(ExperimentalCoroutinesApi::class) class SyncButtonBinding( tabsTrayStore: TabsTrayStore, private val onSyncNow: () -> Unit diff --git a/app/src/main/java/org/mozilla/fenix/tabstray/syncedtabs/SyncedTabsTrayLayout.kt b/app/src/main/java/org/mozilla/fenix/tabstray/syncedtabs/SyncedTabsTrayLayout.kt index d659f28a9..5314fd7aa 100644 --- a/app/src/main/java/org/mozilla/fenix/tabstray/syncedtabs/SyncedTabsTrayLayout.kt +++ b/app/src/main/java/org/mozilla/fenix/tabstray/syncedtabs/SyncedTabsTrayLayout.kt @@ -27,14 +27,13 @@ import org.mozilla.fenix.sync.ext.toStringRes import org.mozilla.fenix.tabstray.TabsTrayAction import org.mozilla.fenix.tabstray.TabsTrayFragment import org.mozilla.fenix.tabstray.TabsTrayStore -import org.mozilla.fenix.tabstray.TrayItem import org.mozilla.fenix.utils.view.LifecycleViewProvider class SyncedTabsTrayLayout @JvmOverloads constructor( context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0 -) : ConstraintLayout(context, attrs, defStyleAttr), SyncedTabsView, TrayItem, +) : ConstraintLayout(context, attrs, defStyleAttr), SyncedTabsView, Observable by ObserverRegistry() { private val lifecycleProvider = LifecycleViewProvider(this) diff --git a/app/src/main/java/org/mozilla/fenix/tabstray/viewholders/BaseBrowserTabViewHolder.kt b/app/src/main/java/org/mozilla/fenix/tabstray/viewholders/AbstractBrowserPageViewHolder.kt similarity index 90% rename from app/src/main/java/org/mozilla/fenix/tabstray/viewholders/BaseBrowserTabViewHolder.kt rename to app/src/main/java/org/mozilla/fenix/tabstray/viewholders/AbstractBrowserPageViewHolder.kt index faecdd921..9e06a3104 100644 --- a/app/src/main/java/org/mozilla/fenix/tabstray/viewholders/BaseBrowserTabViewHolder.kt +++ b/app/src/main/java/org/mozilla/fenix/tabstray/viewholders/AbstractBrowserPageViewHolder.kt @@ -13,19 +13,19 @@ import androidx.recyclerview.widget.RecyclerView import org.mozilla.fenix.R import org.mozilla.fenix.tabstray.TabsTrayInteractor import org.mozilla.fenix.tabstray.TabsTrayStore -import org.mozilla.fenix.tabstray.browser.BaseBrowserTrayList +import org.mozilla.fenix.tabstray.browser.BrowserTrayList /** * A shared view holder for browser tabs tray list. */ -abstract class BaseBrowserTabViewHolder( +abstract class AbstractBrowserPageViewHolder( containerView: View, tabsTrayStore: TabsTrayStore, interactor: TabsTrayInteractor, private val currentTabIndex: Int -) : AbstractTrayViewHolder(containerView) { +) : AbstractPageViewHolder(containerView) { - private val trayList: BaseBrowserTrayList = itemView.findViewById(R.id.tray_list_item) + protected val trayList: BrowserTrayList = itemView.findViewById(R.id.tray_list_item) private val emptyList: TextView = itemView.findViewById(R.id.tab_tray_empty_view) abstract val emptyStringText: String diff --git a/app/src/main/java/org/mozilla/fenix/tabstray/viewholders/AbstractTrayViewHolder.kt b/app/src/main/java/org/mozilla/fenix/tabstray/viewholders/AbstractPageViewHolder.kt similarity index 93% rename from app/src/main/java/org/mozilla/fenix/tabstray/viewholders/AbstractTrayViewHolder.kt rename to app/src/main/java/org/mozilla/fenix/tabstray/viewholders/AbstractPageViewHolder.kt index ebe7725e5..ff6055d90 100644 --- a/app/src/main/java/org/mozilla/fenix/tabstray/viewholders/AbstractTrayViewHolder.kt +++ b/app/src/main/java/org/mozilla/fenix/tabstray/viewholders/AbstractPageViewHolder.kt @@ -12,7 +12,7 @@ import org.mozilla.fenix.tabstray.TrayPagerAdapter /** * An abstract [RecyclerView.ViewHolder] for [TrayPagerAdapter] items. */ -abstract class AbstractTrayViewHolder constructor( +abstract class AbstractPageViewHolder constructor( override val containerView: View ) : RecyclerView.ViewHolder(containerView), LayoutContainer { diff --git a/app/src/main/java/org/mozilla/fenix/tabstray/viewholders/NormalBrowserTabViewHolder.kt b/app/src/main/java/org/mozilla/fenix/tabstray/viewholders/NormalBrowserPageViewHolder.kt similarity index 88% rename from app/src/main/java/org/mozilla/fenix/tabstray/viewholders/NormalBrowserTabViewHolder.kt rename to app/src/main/java/org/mozilla/fenix/tabstray/viewholders/NormalBrowserPageViewHolder.kt index 61a1f1a4e..4edb2a9c2 100644 --- a/app/src/main/java/org/mozilla/fenix/tabstray/viewholders/NormalBrowserTabViewHolder.kt +++ b/app/src/main/java/org/mozilla/fenix/tabstray/viewholders/NormalBrowserPageViewHolder.kt @@ -11,23 +11,28 @@ import org.mozilla.fenix.R import org.mozilla.fenix.selection.SelectionHolder import org.mozilla.fenix.tabstray.TabsTrayInteractor import org.mozilla.fenix.tabstray.TabsTrayStore +import org.mozilla.fenix.tabstray.browser.BrowserTrayList.BrowserTabType.NORMAL import org.mozilla.fenix.tabstray.browser.BrowserTabsAdapter /** * View holder for the normal tabs tray list. */ -class NormalBrowserTabViewHolder( +class NormalBrowserPageViewHolder( containerView: View, private val store: TabsTrayStore, interactor: TabsTrayInteractor, currentTabIndex: Int -) : BaseBrowserTabViewHolder( +) : AbstractBrowserPageViewHolder( containerView, store, interactor, currentTabIndex ), SelectionHolder { + init { + trayList.browserTabType = NORMAL + } + /** * Holds the list of selected tabs. * diff --git a/app/src/main/java/org/mozilla/fenix/tabstray/viewholders/PrivateBrowserTabViewHolder.kt b/app/src/main/java/org/mozilla/fenix/tabstray/viewholders/PrivateBrowserPageViewHolder.kt similarity index 80% rename from app/src/main/java/org/mozilla/fenix/tabstray/viewholders/PrivateBrowserTabViewHolder.kt rename to app/src/main/java/org/mozilla/fenix/tabstray/viewholders/PrivateBrowserPageViewHolder.kt index b49bc8fc1..c213ee512 100644 --- a/app/src/main/java/org/mozilla/fenix/tabstray/viewholders/PrivateBrowserTabViewHolder.kt +++ b/app/src/main/java/org/mozilla/fenix/tabstray/viewholders/PrivateBrowserPageViewHolder.kt @@ -8,21 +8,27 @@ import android.view.View import org.mozilla.fenix.R import org.mozilla.fenix.tabstray.TabsTrayInteractor import org.mozilla.fenix.tabstray.TabsTrayStore +import org.mozilla.fenix.tabstray.browser.BrowserTrayList.BrowserTabType.PRIVATE /** * View holder for the private tabs tray list. */ -class PrivateBrowserTabViewHolder( +class PrivateBrowserPageViewHolder( containerView: View, store: TabsTrayStore, interactor: TabsTrayInteractor, currentTabIndex: Int -) : BaseBrowserTabViewHolder( +) : AbstractBrowserPageViewHolder( containerView, store, interactor, currentTabIndex ) { + + init { + trayList.browserTabType = PRIVATE + } + override val emptyStringText: String get() = itemView.resources.getString(R.string.no_private_tabs_description) diff --git a/app/src/main/java/org/mozilla/fenix/tabstray/viewholders/SyncedTabViewHolder.kt b/app/src/main/java/org/mozilla/fenix/tabstray/viewholders/SyncedTabsPageViewHolder.kt similarity index 92% rename from app/src/main/java/org/mozilla/fenix/tabstray/viewholders/SyncedTabViewHolder.kt rename to app/src/main/java/org/mozilla/fenix/tabstray/viewholders/SyncedTabsPageViewHolder.kt index 066fce9fa..601f78d21 100644 --- a/app/src/main/java/org/mozilla/fenix/tabstray/viewholders/SyncedTabViewHolder.kt +++ b/app/src/main/java/org/mozilla/fenix/tabstray/viewholders/SyncedTabsPageViewHolder.kt @@ -10,10 +10,10 @@ import kotlinx.android.synthetic.main.component_sync_tabs_tray_layout.* import org.mozilla.fenix.R import org.mozilla.fenix.tabstray.TabsTrayStore -class SyncedTabViewHolder( +class SyncedTabsPageViewHolder( containerView: View, private val tabsTrayStore: TabsTrayStore -) : AbstractTrayViewHolder(containerView) { +) : AbstractPageViewHolder(containerView) { override fun bind( adapter: RecyclerView.Adapter, diff --git a/app/src/main/java/org/mozilla/fenix/utils/Settings.kt b/app/src/main/java/org/mozilla/fenix/utils/Settings.kt index c67a40e32..6fbd03afa 100644 --- a/app/src/main/java/org/mozilla/fenix/utils/Settings.kt +++ b/app/src/main/java/org/mozilla/fenix/utils/Settings.kt @@ -34,7 +34,7 @@ import org.mozilla.fenix.components.settings.counterPreference import org.mozilla.fenix.components.settings.featureFlagPreference import org.mozilla.fenix.components.toolbar.ToolbarPosition import org.mozilla.fenix.experiments.ExperimentBranch -import org.mozilla.fenix.experiments.Experiments +import org.mozilla.fenix.experiments.FeatureId import org.mozilla.fenix.ext.components import org.mozilla.fenix.ext.getPreferenceKey import org.mozilla.fenix.ext.withExperiment @@ -249,7 +249,7 @@ class Settings(private val appContext: Context) : PreferencesHolder { get() = loginsSecureWarningSyncCount.underMaxCount() val shouldShowSecurityPinWarning: Boolean - get() = loginsSecureWarningCount.underMaxCount() + get() = secureWarningCount.underMaxCount() var shouldShowPrivacyPopWindow by booleanPreference( appContext.getPreferenceKey(R.string.pref_key_privacy_pop_window), @@ -312,10 +312,10 @@ class Settings(private val appContext: Context) : PreferencesHolder { val browsers = BrowsersCache.all(appContext) val experiments = appContext.components.analytics.experiments val isExperimentBranch = - experiments.withExperiment(Experiments.DEFAULT_BROWSER) { experimentBranch -> + experiments.withExperiment(FeatureId.DEFAULT_BROWSER) { experimentBranch -> (experimentBranch == ExperimentBranch.DEFAULT_BROWSER_NEW_TAB_BANNER) } - return isExperimentBranch && + return isExperimentBranch == true && !userDismissedExperimentCard && !browsers.isFirefoxDefaultBrowser && numberOfAppLaunches > APP_LAUNCHES_TO_SHOW_DEFAULT_BROWSER_CARD @@ -357,6 +357,11 @@ class Settings(private val appContext: Context) : PreferencesHolder { featureFlag = FeatureFlags.tabsTrayRewrite ) + var allowThirdPartyRootCerts by booleanPreference( + appContext.getPreferenceKey(R.string.pref_key_allow_third_party_root_certs), + default = false + ) + fun getTabTimeout(): Long = when { closeTabsAfterOneDay -> ONE_DAY_MS closeTabsAfterOneWeek -> ONE_WEEK_MS @@ -657,12 +662,12 @@ class Settings(private val appContext: Context) : PreferencesHolder { ) @VisibleForTesting(otherwise = PRIVATE) - internal val loginsSecureWarningCount = counterPreference( - appContext.getPreferenceKey(R.string.pref_key_logins_secure_warning), + internal val secureWarningCount = counterPreference( + appContext.getPreferenceKey(R.string.pref_key_secure_warning), maxCount = 1 ) - fun incrementShowLoginsSecureWarningCount() = loginsSecureWarningCount.increment() + fun incrementSecureWarningCount() = secureWarningCount.increment() fun incrementShowLoginsSecureWarningSyncCount() = loginsSecureWarningSyncCount.increment() @@ -986,7 +991,7 @@ class Settings(private val appContext: Context) : PreferencesHolder { ) /** - * Storing number of installed add-ons for telemetry purposes + * Stores the number of installed add-ons for telemetry purposes */ var installedAddonsCount by intPreference( appContext.getPreferenceKey(R.string.pref_key_installed_addons_count), @@ -994,7 +999,7 @@ class Settings(private val appContext: Context) : PreferencesHolder { ) /** - * Storing the list of installed add-ons for telemetry purposes + * Stores the list of installed add-ons for telemetry purposes */ var installedAddonsList by stringPreference( appContext.getPreferenceKey(R.string.pref_key_installed_addons_list), @@ -1002,7 +1007,7 @@ class Settings(private val appContext: Context) : PreferencesHolder { ) /** - * Storing number of enabled add-ons for telemetry purposes + * Stores the number of enabled add-ons for telemetry purposes */ var enabledAddonsCount by intPreference( appContext.getPreferenceKey(R.string.pref_key_enabled_addons_count), @@ -1010,13 +1015,37 @@ class Settings(private val appContext: Context) : PreferencesHolder { ) /** - * Storing the list of enabled add-ons for telemetry purposes + * Stores the list of enabled add-ons for telemetry purposes */ var enabledAddonsList by stringPreference( appContext.getPreferenceKey(R.string.pref_key_enabled_addons_list), default = "" ) + /** + * Stores the number of credit cards that have been saved manually by the user. + */ + var creditCardsSavedCount by intPreference( + appContext.getPreferenceKey(R.string.pref_key_credit_cards_saved_count), + 0 + ) + + /** + * Stores the number of credit cards that have been deleted by the user. + */ + var creditCardsDeletedCount by intPreference( + appContext.getPreferenceKey(R.string.pref_key_credit_cards_deleted_count), + 0 + ) + + /** + * Stores the number of times that user has autofilled a credit card. + */ + var creditCardsAutofilledCount by intPreference( + appContext.getPreferenceKey(R.string.pref_key_credit_cards_autofilled_count), + 0 + ) + private var savedLoginsSortingStrategyString by stringPreference( appContext.getPreferenceKey(R.string.pref_key_saved_logins_sorting_strategy), default = SavedLoginsSortingStrategyMenu.Item.AlphabeticallySort.strategyString @@ -1057,12 +1086,6 @@ class Settings(private val appContext: Context) : PreferencesHolder { default = true ) - var creditCardsFeature by featureFlagPreference( - appContext.getPreferenceKey(R.string.pref_key_show_credit_cards_feature), - default = false, - featureFlag = FeatureFlags.creditCardsFeature - ) - var addressFeature by featureFlagPreference( appContext.getPreferenceKey(R.string.pref_key_show_address_feature), default = false, @@ -1077,4 +1100,20 @@ class Settings(private val appContext: Context) : PreferencesHolder { appContext.getPreferenceKey(R.string.pref_key_open_next_tab_desktop_mode), default = false ) + + var signedInFxaAccount by booleanPreference( + appContext.getPreferenceKey(R.string.pref_key_fxa_signed_in), + default = false + ) + + /** + * Storing the user choice from the "Credit cards" settings for whether save and autofill cards + * should be enabled or not. + * If set to `true` when the user focuses on credit card fields in the webpage an Android prompt letting her + * select the card details to be automatically filled will appear. + */ + var shouldAutofillCreditCardDetails by booleanPreference( + appContext.getPreferenceKey(R.string.pref_key_credit_cards_save_and_autofill_cards), + default = true + ) } diff --git a/app/src/main/java/org/mozilla/gecko/search/SearchWidgetProvider.kt b/app/src/main/java/org/mozilla/gecko/search/SearchWidgetProvider.kt index 57a62160d..87d39ae32 100644 --- a/app/src/main/java/org/mozilla/gecko/search/SearchWidgetProvider.kt +++ b/app/src/main/java/org/mozilla/gecko/search/SearchWidgetProvider.kt @@ -8,6 +8,7 @@ import android.app.PendingIntent import android.appwidget.AppWidgetManager import android.appwidget.AppWidgetManager.OPTION_APPWIDGET_MIN_WIDTH import android.appwidget.AppWidgetProvider +import android.content.ComponentName import android.content.Context import android.content.Intent import android.os.Build @@ -98,7 +99,12 @@ class SearchWidgetProvider : AppWidgetProvider() { /** * Builds pending intent that starts a new voice search. */ - private fun createVoiceSearchIntent(context: Context): PendingIntent? { + @VisibleForTesting + internal fun createVoiceSearchIntent(context: Context): PendingIntent? { + if (!context.settings().shouldShowVoiceSearch) { + return null + } + val voiceIntent = Intent(context, VoiceSearchActivity::class.java).apply { flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK putExtra(SPEECH_PROCESSING, true) @@ -172,6 +178,20 @@ class SearchWidgetProvider : AppWidgetProvider() { private const val REQUEST_CODE_NEW_TAB = 0 private const val REQUEST_CODE_VOICE = 1 + fun updateAllWidgets(context: Context) { + val widgetManager = AppWidgetManager.getInstance(context) + val widgetIds = widgetManager.getAppWidgetIds(ComponentName(context, SearchWidgetProvider::class.java)) + + if (widgetIds.isNotEmpty()) { + context.sendBroadcast( + Intent(context, SearchWidgetProvider::class.java).apply { + action = AppWidgetManager.ACTION_APPWIDGET_UPDATE + putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, widgetIds) + } + ) + } + } + @VisibleForTesting internal fun getLayoutSize(@Dimension(unit = DP) dp: Int) = when { dp >= DP_LARGE -> SearchWidgetProviderSize.LARGE diff --git a/app/src/main/res/anim/fade_in.xml b/app/src/main/res/anim/fade_in.xml index 8024b31fd..b5e953477 100644 --- a/app/src/main/res/anim/fade_in.xml +++ b/app/src/main/res/anim/fade_in.xml @@ -5,4 +5,4 @@ \ No newline at end of file + android:duration="250" /> diff --git a/app/src/main/res/anim/fade_out.xml b/app/src/main/res/anim/fade_out.xml index 4c00bc4a6..7dd6477c2 100644 --- a/app/src/main/res/anim/fade_out.xml +++ b/app/src/main/res/anim/fade_out.xml @@ -5,4 +5,4 @@ \ No newline at end of file + android:duration="250" /> diff --git a/app/src/main/res/anim/placeholder_animation.xml b/app/src/main/res/anim/placeholder_animation.xml index 80c254842..348af4210 100644 --- a/app/src/main/res/anim/placeholder_animation.xml +++ b/app/src/main/res/anim/placeholder_animation.xml @@ -6,4 +6,4 @@ xmlns:android="http://schemas.android.com/apk/res/android" android:fromXDelta="0" android:toXDelta="0" - android:duration="900" /> \ No newline at end of file + android:duration="900" /> diff --git a/app/src/main/res/anim/slide_out_right.xml b/app/src/main/res/anim/slide_out_right.xml index 240992691..0e8b6ccbc 100644 --- a/app/src/main/res/anim/slide_out_right.xml +++ b/app/src/main/res/anim/slide_out_right.xml @@ -8,4 +8,4 @@ android:duration="275"/> - \ No newline at end of file + diff --git a/app/src/main/res/anim/zoom_in_fade.xml b/app/src/main/res/anim/zoom_in_fade.xml index 5248878fd..3482fd7e3 100644 --- a/app/src/main/res/anim/zoom_in_fade.xml +++ b/app/src/main/res/anim/zoom_in_fade.xml @@ -16,4 +16,4 @@ android:fromYScale="100%" android:toYScale="113%" android:duration="125" /> - \ No newline at end of file + diff --git a/app/src/main/res/anim/zoom_out_fade.xml b/app/src/main/res/anim/zoom_out_fade.xml index 720b5bf3c..993dafc81 100644 --- a/app/src/main/res/anim/zoom_out_fade.xml +++ b/app/src/main/res/anim/zoom_out_fade.xml @@ -16,4 +16,4 @@ android:fromYScale="108%" android:toYScale="100%" android:duration="175" /> - \ No newline at end of file + diff --git a/app/src/main/res/color/onboarding_illustration_color.xml b/app/src/main/res/color/onboarding_illustration_color.xml index 040718d7a..5a8c8da54 100644 --- a/app/src/main/res/color/onboarding_illustration_color.xml +++ b/app/src/main/res/color/onboarding_illustration_color.xml @@ -5,4 +5,4 @@ - \ No newline at end of file + diff --git a/app/src/main/res/color/readerview_private_button_color.xml b/app/src/main/res/color/readerview_private_button_color.xml index 48b2a921e..afd227af8 100644 --- a/app/src/main/res/color/readerview_private_button_color.xml +++ b/app/src/main/res/color/readerview_private_button_color.xml @@ -5,4 +5,4 @@ - \ No newline at end of file + diff --git a/app/src/main/res/color/readerview_private_radio_color.xml b/app/src/main/res/color/readerview_private_radio_color.xml index 0136866d0..56b5f8a12 100644 --- a/app/src/main/res/color/readerview_private_radio_color.xml +++ b/app/src/main/res/color/readerview_private_radio_color.xml @@ -5,4 +5,4 @@ - \ No newline at end of file + diff --git a/app/src/main/res/color/saved_login_clear_edit_text_tint.xml b/app/src/main/res/color/saved_login_clear_edit_text_tint.xml index ada9ebc97..1a800496d 100644 --- a/app/src/main/res/color/saved_login_clear_edit_text_tint.xml +++ b/app/src/main/res/color/saved_login_clear_edit_text_tint.xml @@ -7,4 +7,4 @@ android:color="?primaryText" /> - \ No newline at end of file + diff --git a/app/src/main/res/color/tab_checkbox_tint.xml b/app/src/main/res/color/tab_checkbox_tint.xml index 3eff7db2a..fe33814e7 100644 --- a/app/src/main/res/color/tab_checkbox_tint.xml +++ b/app/src/main/res/color/tab_checkbox_tint.xml @@ -4,4 +4,4 @@ - \ No newline at end of file + diff --git a/app/src/main/res/color/tab_icon.xml b/app/src/main/res/color/tab_icon.xml index 48ad13b5b..ed703e81e 100644 --- a/app/src/main/res/color/tab_icon.xml +++ b/app/src/main/res/color/tab_icon.xml @@ -5,4 +5,4 @@ - \ No newline at end of file + diff --git a/app/src/main/res/drawable-v24/shield_light.xml b/app/src/main/res/drawable-v24/shield_light.xml index e04aca611..0e322f569 100644 --- a/app/src/main/res/drawable-v24/shield_light.xml +++ b/app/src/main/res/drawable-v24/shield_light.xml @@ -78,4 +78,4 @@ - \ No newline at end of file + diff --git a/app/src/main/res/drawable-v26/ic_launcher_private_background.xml b/app/src/main/res/drawable-v26/ic_launcher_private_background.xml index ab3c79093..26ba3b670 100644 --- a/app/src/main/res/drawable-v26/ic_launcher_private_background.xml +++ b/app/src/main/res/drawable-v26/ic_launcher_private_background.xml @@ -23,4 +23,3 @@ - diff --git a/app/src/main/res/drawable-v26/ic_static_shortcut_private_tab.xml b/app/src/main/res/drawable-v26/ic_static_shortcut_private_tab.xml index 479544f20..0fc49198c 100644 --- a/app/src/main/res/drawable-v26/ic_static_shortcut_private_tab.xml +++ b/app/src/main/res/drawable-v26/ic_static_shortcut_private_tab.xml @@ -6,4 +6,4 @@ - \ No newline at end of file + diff --git a/app/src/main/res/drawable-v26/ic_static_shortcut_tab.xml b/app/src/main/res/drawable-v26/ic_static_shortcut_tab.xml index cb4d26633..2351ce27c 100644 --- a/app/src/main/res/drawable-v26/ic_static_shortcut_tab.xml +++ b/app/src/main/res/drawable-v26/ic_static_shortcut_tab.xml @@ -6,4 +6,4 @@ - \ No newline at end of file + diff --git a/app/src/main/res/drawable/add_tabs_to_collection_background.xml b/app/src/main/res/drawable/add_tabs_to_collection_background.xml index 43cde06e7..d50f08972 100644 --- a/app/src/main/res/drawable/add_tabs_to_collection_background.xml +++ b/app/src/main/res/drawable/add_tabs_to_collection_background.xml @@ -6,4 +6,4 @@ - \ No newline at end of file + diff --git a/app/src/main/res/drawable/bottom_sheet_dialog_fragment_background.xml b/app/src/main/res/drawable/bottom_sheet_dialog_fragment_background.xml index 0c9ac22a3..93ba489d3 100644 --- a/app/src/main/res/drawable/bottom_sheet_dialog_fragment_background.xml +++ b/app/src/main/res/drawable/bottom_sheet_dialog_fragment_background.xml @@ -5,4 +5,4 @@ android:topLeftRadius="@dimen/bottom_sheet_corner_radius" android:topRightRadius="@dimen/bottom_sheet_corner_radius" /> - \ No newline at end of file + diff --git a/app/src/main/res/drawable/button_background.xml b/app/src/main/res/drawable/button_background.xml index d50c66558..927fa280d 100644 --- a/app/src/main/res/drawable/button_background.xml +++ b/app/src/main/res/drawable/button_background.xml @@ -6,4 +6,4 @@ - \ No newline at end of file + diff --git a/app/src/main/res/drawable/button_background_grey.xml b/app/src/main/res/drawable/button_background_grey.xml index 6dcdce8a8..916a19155 100644 --- a/app/src/main/res/drawable/button_background_grey.xml +++ b/app/src/main/res/drawable/button_background_grey.xml @@ -6,4 +6,4 @@ - \ No newline at end of file + diff --git a/app/src/main/res/drawable/crash_reporter_button.xml b/app/src/main/res/drawable/crash_reporter_button.xml index 81511ea2c..976bc05cd 100644 --- a/app/src/main/res/drawable/crash_reporter_button.xml +++ b/app/src/main/res/drawable/crash_reporter_button.xml @@ -13,4 +13,4 @@ - \ No newline at end of file + diff --git a/app/src/main/res/drawable/device_background.xml b/app/src/main/res/drawable/device_background.xml index 8cc5ad492..c9c973af2 100644 --- a/app/src/main/res/drawable/device_background.xml +++ b/app/src/main/res/drawable/device_background.xml @@ -7,4 +7,4 @@ - \ No newline at end of file + diff --git a/app/src/main/res/drawable/dialog_background.xml b/app/src/main/res/drawable/dialog_background.xml index aa3fcf5c6..98156a1b9 100644 --- a/app/src/main/res/drawable/dialog_background.xml +++ b/app/src/main/res/drawable/dialog_background.xml @@ -6,4 +6,4 @@ - \ No newline at end of file + diff --git a/app/src/main/res/drawable/dialog_button_background.xml b/app/src/main/res/drawable/dialog_button_background.xml index e4aaec8f3..faafaaf7f 100644 --- a/app/src/main/res/drawable/dialog_button_background.xml +++ b/app/src/main/res/drawable/dialog_button_background.xml @@ -6,4 +6,4 @@ - \ No newline at end of file + diff --git a/app/src/main/res/drawable/favicon_background.xml b/app/src/main/res/drawable/favicon_background.xml index 5efbdace9..5aebd70dd 100644 --- a/app/src/main/res/drawable/favicon_background.xml +++ b/app/src/main/res/drawable/favicon_background.xml @@ -6,4 +6,4 @@ - \ No newline at end of file + diff --git a/app/src/main/res/drawable/home_search_background.xml b/app/src/main/res/drawable/home_search_background.xml index 19e41a79f..20619c9f3 100644 --- a/app/src/main/res/drawable/home_search_background.xml +++ b/app/src/main/res/drawable/home_search_background.xml @@ -5,4 +5,4 @@ - \ No newline at end of file + diff --git a/app/src/main/res/drawable/ic_autoplay.xml b/app/src/main/res/drawable/ic_autoplay.xml index 86ea0d369..f3d5a487f 100644 --- a/app/src/main/res/drawable/ic_autoplay.xml +++ b/app/src/main/res/drawable/ic_autoplay.xml @@ -12,4 +12,4 @@ android:id="@+id/disabled" android:drawable="@drawable/ic_autoplay_disabled" /> - \ No newline at end of file + diff --git a/app/src/main/res/drawable/ic_back_button.xml b/app/src/main/res/drawable/ic_back_button.xml new file mode 100644 index 000000000..95f2e380a --- /dev/null +++ b/app/src/main/res/drawable/ic_back_button.xml @@ -0,0 +1,13 @@ + + + + + diff --git a/app/src/main/res/drawable/ic_desktop.xml b/app/src/main/res/drawable/ic_desktop.xml index 76629aa8e..de303bb1e 100644 --- a/app/src/main/res/drawable/ic_desktop.xml +++ b/app/src/main/res/drawable/ic_desktop.xml @@ -9,4 +9,4 @@ android:viewportHeight="24"> - \ No newline at end of file + diff --git a/app/src/main/res/drawable/ic_drawer_pull_tab.xml b/app/src/main/res/drawable/ic_drawer_pull_tab.xml index b3a54e018..015f3ef7c 100644 --- a/app/src/main/res/drawable/ic_drawer_pull_tab.xml +++ b/app/src/main/res/drawable/ic_drawer_pull_tab.xml @@ -9,4 +9,4 @@ - \ No newline at end of file + diff --git a/app/src/main/res/drawable/ic_home.xml b/app/src/main/res/drawable/ic_home.xml index 57149e629..2348db076 100644 --- a/app/src/main/res/drawable/ic_home.xml +++ b/app/src/main/res/drawable/ic_home.xml @@ -10,4 +10,4 @@ - \ No newline at end of file + diff --git a/app/src/main/res/drawable/ic_link.xml b/app/src/main/res/drawable/ic_link.xml index 0e034b502..7cf4c3232 100644 --- a/app/src/main/res/drawable/ic_link.xml +++ b/app/src/main/res/drawable/ic_link.xml @@ -11,4 +11,4 @@ android:id="@+id/disabled" android:drawable="@drawable/ic_link_disabled" /> - \ No newline at end of file + diff --git a/app/src/main/res/drawable/ic_new_pin.xml b/app/src/main/res/drawable/ic_new_pin.xml new file mode 100644 index 000000000..15940a2a2 --- /dev/null +++ b/app/src/main/res/drawable/ic_new_pin.xml @@ -0,0 +1,13 @@ + + + + + diff --git a/app/src/main/res/drawable/ic_static_shortcut_background.xml b/app/src/main/res/drawable/ic_static_shortcut_background.xml index a186424a7..32a587e21 100644 --- a/app/src/main/res/drawable/ic_static_shortcut_background.xml +++ b/app/src/main/res/drawable/ic_static_shortcut_background.xml @@ -7,4 +7,4 @@ android:shape="oval"> - \ No newline at end of file + diff --git a/app/src/main/res/drawable/ic_static_shortcut_private_tab.xml b/app/src/main/res/drawable/ic_static_shortcut_private_tab.xml index beaaf6582..d9f67886f 100644 --- a/app/src/main/res/drawable/ic_static_shortcut_private_tab.xml +++ b/app/src/main/res/drawable/ic_static_shortcut_private_tab.xml @@ -6,4 +6,4 @@ - \ No newline at end of file + diff --git a/app/src/main/res/drawable/ic_static_shortcut_tab.xml b/app/src/main/res/drawable/ic_static_shortcut_tab.xml index 15759ffc3..c78a6647b 100644 --- a/app/src/main/res/drawable/ic_static_shortcut_tab.xml +++ b/app/src/main/res/drawable/ic_static_shortcut_tab.xml @@ -6,4 +6,4 @@ - \ No newline at end of file + diff --git a/app/src/main/res/drawable/ic_top_sites.xml b/app/src/main/res/drawable/ic_top_sites.xml index af3d6c0b4..59a02d306 100644 --- a/app/src/main/res/drawable/ic_top_sites.xml +++ b/app/src/main/res/drawable/ic_top_sites.xml @@ -11,4 +11,3 @@ android:fillColor="?primaryText" android:pathData="M21.28 20.22l-5.472-5.472 2.986-2.986c0.527-0.528 0.68-1.285 0.398-1.976a1.796 1.796 0 0 0-1.665-1.133l-2.475-0.029-3.775-3.776 1.068-1.068a0.75 0.75 0 1 0-1.061-1.061L2.72 11.287a0.75 0.75 0 0 0 1.06 1.061l1.079-1.079 3.775 3.775 0.029 2.475a1.794 1.794 0 0 0 1.135 1.665 1.795 1.795 0 0 0 1.973-0.398l2.977-2.977 5.472 5.472a0.748 0.748 0 0 0 1.06 0 0.75 0.75 0 0 0 0-1.061zm-10.569-2.495a0.304 0.304 0 0 1-0.348 0.07 0.307 0.307 0 0 1-0.2-0.294l-0.037-3.086-4.207-4.207 4.299-4.299 4.206 4.207 3.086 0.037a0.306 0.306 0 0 1 0.294 0.199 0.31 0.31 0 0 1-0.07 0.349l-7.023 7.024z" /> - diff --git a/app/src/main/res/drawable/migration_button_background.xml b/app/src/main/res/drawable/migration_button_background.xml index e70aee5b4..99596c710 100644 --- a/app/src/main/res/drawable/migration_button_background.xml +++ b/app/src/main/res/drawable/migration_button_background.xml @@ -6,4 +6,4 @@ - \ No newline at end of file + diff --git a/app/src/main/res/drawable/mozac_ic_warning_with_bottom_padding.xml b/app/src/main/res/drawable/mozac_ic_warning_with_bottom_padding.xml index 408f4c077..d285b129b 100644 --- a/app/src/main/res/drawable/mozac_ic_warning_with_bottom_padding.xml +++ b/app/src/main/res/drawable/mozac_ic_warning_with_bottom_padding.xml @@ -6,4 +6,4 @@ - \ No newline at end of file + diff --git a/app/src/main/res/drawable/private_home_background_gradient.xml b/app/src/main/res/drawable/private_home_background_gradient.xml index bf2877bae..267bc2096 100644 --- a/app/src/main/res/drawable/private_home_background_gradient.xml +++ b/app/src/main/res/drawable/private_home_background_gradient.xml @@ -13,4 +13,4 @@ android:type="linear" /> - \ No newline at end of file + diff --git a/app/src/main/res/drawable/recent_apps_background.xml b/app/src/main/res/drawable/recent_apps_background.xml index a7c314420..2be5826a3 100644 --- a/app/src/main/res/drawable/recent_apps_background.xml +++ b/app/src/main/res/drawable/recent_apps_background.xml @@ -3,6 +3,6 @@ - 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/. --> - + - \ No newline at end of file + diff --git a/app/src/main/res/drawable/rounded_bottom_corners.xml b/app/src/main/res/drawable/rounded_bottom_corners.xml index 4ce4f140b..1407f4e20 100644 --- a/app/src/main/res/drawable/rounded_bottom_corners.xml +++ b/app/src/main/res/drawable/rounded_bottom_corners.xml @@ -6,4 +6,4 @@ - \ No newline at end of file + diff --git a/app/src/main/res/drawable/rounded_grey_corners_transparent_center.xml b/app/src/main/res/drawable/rounded_grey_corners_transparent_center.xml index e933d4ef2..e803ff8df 100644 --- a/app/src/main/res/drawable/rounded_grey_corners_transparent_center.xml +++ b/app/src/main/res/drawable/rounded_grey_corners_transparent_center.xml @@ -10,4 +10,4 @@ android:width="1dp" android:color="?toolbarDivider"/> - \ No newline at end of file + diff --git a/app/src/main/res/drawable/rounded_search_widget_background.xml b/app/src/main/res/drawable/rounded_search_widget_background.xml index e37f2029b..a21f3705d 100644 --- a/app/src/main/res/drawable/rounded_search_widget_background.xml +++ b/app/src/main/res/drawable/rounded_search_widget_background.xml @@ -6,4 +6,4 @@ - \ No newline at end of file + diff --git a/app/src/main/res/drawable/search_url_background.xml b/app/src/main/res/drawable/search_url_background.xml index 955ed4696..fd279d445 100644 --- a/app/src/main/res/drawable/search_url_background.xml +++ b/app/src/main/res/drawable/search_url_background.xml @@ -9,4 +9,4 @@ android:bottomLeftRadius="8dp" android:topLeftRadius="8dp" android:topRightRadius="8dp"/> - \ No newline at end of file + diff --git a/app/src/main/res/drawable/session_border.xml b/app/src/main/res/drawable/session_border.xml index daa19bd86..5b7de5836 100644 --- a/app/src/main/res/drawable/session_border.xml +++ b/app/src/main/res/drawable/session_border.xml @@ -6,4 +6,4 @@ - \ No newline at end of file + diff --git a/app/src/main/res/drawable/shield_light.xml b/app/src/main/res/drawable/shield_light.xml index f621f8390..34cbdc10e 100644 --- a/app/src/main/res/drawable/shield_light.xml +++ b/app/src/main/res/drawable/shield_light.xml @@ -28,4 +28,4 @@ android:valueType="colorType" /> - \ No newline at end of file + diff --git a/app/src/main/res/drawable/top_sites_background.xml b/app/src/main/res/drawable/top_sites_background.xml deleted file mode 100644 index c5ff9918d..000000000 --- a/app/src/main/res/drawable/top_sites_background.xml +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - - diff --git a/app/src/main/res/drawable/url_background.xml b/app/src/main/res/drawable/url_background.xml index 3058f12e5..d543eb368 100644 --- a/app/src/main/res/drawable/url_background.xml +++ b/app/src/main/res/drawable/url_background.xml @@ -10,4 +10,4 @@ android:bottomRightRadius="8dp" android:topLeftRadius="8dp" android:topRightRadius="8dp" /> - \ No newline at end of file + diff --git a/app/src/main/res/font/metropolis.xml b/app/src/main/res/font/metropolis.xml index bdb818c34..5ccbd737a 100644 --- a/app/src/main/res/font/metropolis.xml +++ b/app/src/main/res/font/metropolis.xml @@ -74,4 +74,4 @@ app:fontStyle="normal" app:fontWeight="100" /> - \ No newline at end of file + diff --git a/app/src/main/res/layout/activity_privacy_content_display.xml b/app/src/main/res/layout/activity_privacy_content_display.xml index c6ff55e47..cee2f0499 100644 --- a/app/src/main/res/layout/activity_privacy_content_display.xml +++ b/app/src/main/res/layout/activity_privacy_content_display.xml @@ -22,7 +22,7 @@ android:background="@android:color/transparent" android:id="@+id/privacyContentCloseButton" android:src="@drawable/ic_close" - android:contentDescription="close" + android:contentDescription="@string/privacy_content_close_button_content_description" tools:ignore="AndroidSrcXmlDetector" /> diff --git a/app/src/main/res/layout/browser_toolbar_popup_window.xml b/app/src/main/res/layout/browser_toolbar_popup_window.xml index 3cd156001..28ed26d0f 100644 --- a/app/src/main/res/layout/browser_toolbar_popup_window.xml +++ b/app/src/main/res/layout/browser_toolbar_popup_window.xml @@ -50,4 +50,4 @@ android:text="@string/browser_toolbar_long_press_popup_paste_and_go" android:textAllCaps="false" android:textColor="?primaryText" /> - \ No newline at end of file + diff --git a/app/src/main/res/layout/collection_header.xml b/app/src/main/res/layout/collection_header.xml index e2d7af88d..9122f0455 100644 --- a/app/src/main/res/layout/collection_header.xml +++ b/app/src/main/res/layout/collection_header.xml @@ -8,4 +8,4 @@ android:layout_height="48dp" android:gravity="center_vertical" android:text="@string/collections_header" - android:textAppearance="@style/HeaderTextStyle" /> \ No newline at end of file + android:textAppearance="@style/HeaderTextStyle" /> diff --git a/app/src/main/res/layout/component_browser_top_toolbar.xml b/app/src/main/res/layout/component_browser_top_toolbar.xml index 77f460296..0152ecdb1 100644 --- a/app/src/main/res/layout/component_browser_top_toolbar.xml +++ b/app/src/main/res/layout/component_browser_top_toolbar.xml @@ -20,4 +20,3 @@ app:browserToolbarProgressBarGravity="bottom" app:browserToolbarSecureColor="?primaryText" app:browserToolbarTrackingProtectionAndSecurityIndicatorSeparatorColor="?toolbarDivider" /> - diff --git a/app/src/main/res/layout/component_credit_cards.xml b/app/src/main/res/layout/component_credit_cards.xml index 34471f4b5..0e791b496 100644 --- a/app/src/main/res/layout/component_credit_cards.xml +++ b/app/src/main/res/layout/component_credit_cards.xml @@ -2,12 +2,12 @@ - + android:layout_height="wrap_content"> + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintEnd_toEndOf="parent"/> + app:layout_constrainedHeight="true" + tools:listitem="@layout/credit_card_list_item" + app:layout_constraintTop_toBottomOf="@id/progress_bar" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintBottom_toTopOf="@id/add_credit_card_button"/> - + + + diff --git a/app/src/main/res/layout/component_locale_settings.xml b/app/src/main/res/layout/component_locale_settings.xml index 338f2868c..5cde4858c 100644 --- a/app/src/main/res/layout/component_locale_settings.xml +++ b/app/src/main/res/layout/component_locale_settings.xml @@ -18,4 +18,4 @@ app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" /> - \ No newline at end of file + diff --git a/app/src/main/res/layout/component_permissions_blocked_by_android.xml b/app/src/main/res/layout/component_permissions_blocked_by_android.xml index 7ddd84db2..57bdd497b 100644 --- a/app/src/main/res/layout/component_permissions_blocked_by_android.xml +++ b/app/src/main/res/layout/component_permissions_blocked_by_android.xml @@ -63,4 +63,3 @@ android:text="@string/phone_feature_go_to_settings" /> - diff --git a/app/src/main/res/layout/component_tabhistory.xml b/app/src/main/res/layout/component_tabhistory.xml index 073753f5c..f01a2efcf 100644 --- a/app/src/main/res/layout/component_tabhistory.xml +++ b/app/src/main/res/layout/component_tabhistory.xml @@ -28,4 +28,3 @@ android:paddingTop="19dp" tools:listitem="@layout/history_list_item" /> - diff --git a/app/src/main/res/layout/component_tabstray_fab.xml b/app/src/main/res/layout/component_tabstray_fab.xml index 6a6fbfcf0..ce63c8aa6 100644 --- a/app/src/main/res/layout/component_tabstray_fab.xml +++ b/app/src/main/res/layout/component_tabstray_fab.xml @@ -17,6 +17,7 @@ android:elevation="99dp" android:text="@string/tab_drawer_fab_content" android:textColor="@color/photonWhite" + android:visibility="gone" app:elevation="99dp" app:borderWidth="0dp" app:icon="@drawable/ic_new" diff --git a/app/src/main/res/layout/credit_card_list_item.xml b/app/src/main/res/layout/credit_card_list_item.xml index 386eed434..121e4b494 100644 --- a/app/src/main/res/layout/credit_card_list_item.xml +++ b/app/src/main/res/layout/credit_card_list_item.xml @@ -10,19 +10,30 @@ android:background="?android:attr/selectableItemBackground" android:minHeight="?android:attr/listPreferredItemHeight"> + + @@ -38,7 +49,7 @@ android:textColor="?secondaryText" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" - app:layout_constraintStart_toStartOf="parent" + app:layout_constraintStart_toEndOf="@+id/credit_card_logo" app:layout_constraintTop_toBottomOf="@id/credit_card_number" app:layout_constraintVertical_chainStyle="packed" tools:text="02/2022" /> diff --git a/app/src/main/res/layout/delete_exceptions_button.xml b/app/src/main/res/layout/delete_exceptions_button.xml index 7b4bee99e..6b69a49a6 100644 --- a/app/src/main/res/layout/delete_exceptions_button.xml +++ b/app/src/main/res/layout/delete_exceptions_button.xml @@ -8,4 +8,3 @@ style="@style/NeutralButton" android:layout_marginHorizontal="16dp" android:text="@string/preferences_tracking_protection_exceptions_turn_on_for_all" /> - diff --git a/app/src/main/res/layout/download_list_item.xml b/app/src/main/res/layout/download_list_item.xml index 89c5da55c..bf2dc7d2d 100644 --- a/app/src/main/res/layout/download_list_item.xml +++ b/app/src/main/res/layout/download_list_item.xml @@ -21,4 +21,4 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:minHeight="@dimen/library_item_height" /> - \ No newline at end of file + diff --git a/app/src/main/res/layout/etp_dropdown_item.xml b/app/src/main/res/layout/etp_dropdown_item.xml index e0ce6d9f9..33790393d 100644 --- a/app/src/main/res/layout/etp_dropdown_item.xml +++ b/app/src/main/res/layout/etp_dropdown_item.xml @@ -11,4 +11,4 @@ android:paddingStart="15dp" android:gravity="center_vertical" android:background="@drawable/etp_spinner_item_background" - android:textSize="14sp" /> \ No newline at end of file + android:textSize="14sp" /> diff --git a/app/src/main/res/layout/fragment_browser.xml b/app/src/main/res/layout/fragment_browser.xml index 32d2bd4c4..cd4c91f5b 100644 --- a/app/src/main/res/layout/fragment_browser.xml +++ b/app/src/main/res/layout/fragment_browser.xml @@ -18,7 +18,7 @@ android:id="@+id/browserLayout" android:layout_width="match_parent" android:layout_height="0dp" - app:layout_constraintBottom_toTopOf="@+id/loginSelectBar" + app:layout_constraintBottom_toTopOf="@+id/creditCardSelectBar" app:layout_constraintTop_toTopOf="parent" tools:context="browser.BrowserFragment"> @@ -62,13 +62,21 @@ + + + app:layout_constraintTop_toBottomOf="@id/creditCardSelectBar" /> - - - - - - + + + android:orientation="vertical"> - + - - - - - - - + android:textSize="12sp" + app:fontFamily="@font/metropolis_semibold" /> - - - - - - + app:errorEnabled="true" + app:hintEnabled="false"> - + + + + + + - + android:paddingBottom="11dp" + android:textColor="?primaryText" + app:hintEnabled="false"> - - - - - + android:ellipsize="end" + android:fontFamily="sans-serif" + android:imeOptions="flagNoExtractUi" + android:letterSpacing="0.01" + android:lineSpacingExtra="8sp" + android:maxLines="1" + android:singleLine="true" + android:textColor="?primaryText" + android:textSize="16sp" /> + + + + + + android:baselineAligned="false" + android:orientation="horizontal"> - + android:layout_marginEnd="24dp" + android:layout_weight="1" + android:orientation="vertical"> - + - - + - - - - + - + - + - + - - - - - + + - + + + + + + + + + - + + diff --git a/app/src/main/res/layout/fragment_locale_settings.xml b/app/src/main/res/layout/fragment_locale_settings.xml index eb8b403c7..d235e7043 100644 --- a/app/src/main/res/layout/fragment_locale_settings.xml +++ b/app/src/main/res/layout/fragment_locale_settings.xml @@ -16,4 +16,4 @@ app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" /> - \ No newline at end of file + diff --git a/app/src/main/res/layout/fragment_manage_site_permissions_feature_phone.xml b/app/src/main/res/layout/fragment_manage_site_permissions_feature_phone.xml index f1019b488..9dab31a01 100644 --- a/app/src/main/res/layout/fragment_manage_site_permissions_feature_phone.xml +++ b/app/src/main/res/layout/fragment_manage_site_permissions_feature_phone.xml @@ -80,4 +80,4 @@ - \ No newline at end of file + diff --git a/app/src/main/res/layout/fragment_search.xml b/app/src/main/res/layout/fragment_search.xml index 6a7e8be88..da0653431 100644 --- a/app/src/main/res/layout/fragment_search.xml +++ b/app/src/main/res/layout/fragment_search.xml @@ -202,4 +202,4 @@ android:textOn="@string/search_engine_button" app:drawableStartCompat="@drawable/ic_search" /> - \ No newline at end of file + diff --git a/app/src/main/res/layout/fragment_site_permissions_exceptions_item.xml b/app/src/main/res/layout/fragment_site_permissions_exceptions_item.xml index ed6da05d1..476a6bcc3 100644 --- a/app/src/main/res/layout/fragment_site_permissions_exceptions_item.xml +++ b/app/src/main/res/layout/fragment_site_permissions_exceptions_item.xml @@ -31,4 +31,3 @@ tools:text="mozilla.com" /> - diff --git a/app/src/main/res/layout/layout_add_credit_card.xml b/app/src/main/res/layout/layout_add_credit_card.xml new file mode 100644 index 000000000..9d9803653 --- /dev/null +++ b/app/src/main/res/layout/layout_add_credit_card.xml @@ -0,0 +1,38 @@ + + + + + + + + + diff --git a/app/src/main/res/layout/layout_percentage_seek_bar.xml b/app/src/main/res/layout/layout_percentage_seek_bar.xml index 12db43e26..64a611065 100644 --- a/app/src/main/res/layout/layout_percentage_seek_bar.xml +++ b/app/src/main/res/layout/layout_percentage_seek_bar.xml @@ -66,7 +66,7 @@ - \ No newline at end of file + diff --git a/app/src/main/res/layout/locale_settings_item.xml b/app/src/main/res/layout/locale_settings_item.xml index 511ae58c5..ca15df65a 100644 --- a/app/src/main/res/layout/locale_settings_item.xml +++ b/app/src/main/res/layout/locale_settings_item.xml @@ -56,4 +56,4 @@ app:layout_constraintVertical_chainStyle="packed" tools:text="English (United States)" /> - \ No newline at end of file + diff --git a/app/src/main/res/layout/migration_list_item.xml b/app/src/main/res/layout/migration_list_item.xml index 1060a1ad3..811790ec2 100644 --- a/app/src/main/res/layout/migration_list_item.xml +++ b/app/src/main/res/layout/migration_list_item.xml @@ -33,4 +33,4 @@ app:layout_constraintStart_toEndOf="@+id/migration_status_image" app:layout_constraintTop_toTopOf="parent" tools:text="@sample/migration_items" /> - \ No newline at end of file + diff --git a/app/src/main/res/layout/normal_browser_tray_list.xml b/app/src/main/res/layout/normal_browser_tray_list.xml index a8a12f582..532d794c5 100644 --- a/app/src/main/res/layout/normal_browser_tray_list.xml +++ b/app/src/main/res/layout/normal_browser_tray_list.xml @@ -3,7 +3,7 @@ android:layout_width="match_parent" android:layout_height="match_parent"> - - \ No newline at end of file + diff --git a/app/src/main/res/layout/preference_cat_style.xml b/app/src/main/res/layout/preference_cat_style.xml index b0b640ed7..98934ae20 100644 --- a/app/src/main/res/layout/preference_cat_style.xml +++ b/app/src/main/res/layout/preference_cat_style.xml @@ -10,4 +10,4 @@ android:layout_height="@dimen/section_header_height" android:layout_marginStart="@dimen/top_bar_alignment_margin_start" android:gravity="start|center_vertical" - app:allowDividerAbove="true" /> \ No newline at end of file + app:allowDividerAbove="true" /> diff --git a/app/src/main/res/layout/preference_category_no_icon_style.xml b/app/src/main/res/layout/preference_category_no_icon_style.xml index b5f7df4ab..fee6140d9 100644 --- a/app/src/main/res/layout/preference_category_no_icon_style.xml +++ b/app/src/main/res/layout/preference_category_no_icon_style.xml @@ -10,4 +10,4 @@ android:layout_height="@dimen/section_header_height" android:layout_marginStart="@dimen/top_bar_no_icon_alignment_margin_start" android:gravity="start|center_vertical" - app:allowDividerAbove="true" /> \ No newline at end of file + app:allowDividerAbove="true" /> diff --git a/app/src/main/res/layout/preference_credit_cards_add_credit_card.xml b/app/src/main/res/layout/preference_credit_cards_add_credit_card.xml deleted file mode 100644 index 41c8b247c..000000000 --- a/app/src/main/res/layout/preference_credit_cards_add_credit_card.xml +++ /dev/null @@ -1,40 +0,0 @@ - - - - - - - - diff --git a/app/src/main/res/layout/preference_search_engine_chooser.xml b/app/src/main/res/layout/preference_search_engine_chooser.xml index 650f700f4..0fdae27f9 100644 --- a/app/src/main/res/layout/preference_search_engine_chooser.xml +++ b/app/src/main/res/layout/preference_search_engine_chooser.xml @@ -13,4 +13,4 @@ android:layout_width="match_parent" android:layout_height="wrap_content" /> - \ No newline at end of file + diff --git a/app/src/main/res/layout/preference_sync.xml b/app/src/main/res/layout/preference_sync.xml new file mode 100644 index 000000000..bd13e71ce --- /dev/null +++ b/app/src/main/res/layout/preference_sync.xml @@ -0,0 +1,14 @@ + + + + diff --git a/app/src/main/res/layout/private_browser_tray_list.xml b/app/src/main/res/layout/private_browser_tray_list.xml index 21ce16541..532d794c5 100644 --- a/app/src/main/res/layout/private_browser_tray_list.xml +++ b/app/src/main/res/layout/private_browser_tray_list.xml @@ -3,7 +3,7 @@ android:layout_width="match_parent" android:layout_height="match_parent"> - \ No newline at end of file + android:textColor="?accentUsedOnDarkBackground" /> diff --git a/app/src/main/res/layout/recently_closed_nav_item.xml b/app/src/main/res/layout/recently_closed_nav_item.xml index 02ad905ae..6230b4d5f 100644 --- a/app/src/main/res/layout/recently_closed_nav_item.xml +++ b/app/src/main/res/layout/recently_closed_nav_item.xml @@ -63,4 +63,4 @@ app:layout_constraintTop_toBottomOf="@id/recently_closed_tabs_header" app:layout_goneMarginEnd="@dimen/library_item_icon_margin_horizontal" tools:text="2 tabs" /> - \ No newline at end of file + diff --git a/app/src/main/res/layout/search_suggestions_hint.xml b/app/src/main/res/layout/search_suggestions_hint.xml index 14bf46202..914a63125 100644 --- a/app/src/main/res/layout/search_suggestions_hint.xml +++ b/app/src/main/res/layout/search_suggestions_hint.xml @@ -102,4 +102,4 @@ app:layout_constraintTop_toTopOf="@id/allow" /> - \ No newline at end of file + diff --git a/app/src/main/res/layout/search_widget_small_no_mic.xml b/app/src/main/res/layout/search_widget_small_no_mic.xml index 89c056207..d0bd2d81a 100644 --- a/app/src/main/res/layout/search_widget_small_no_mic.xml +++ b/app/src/main/res/layout/search_widget_small_no_mic.xml @@ -16,4 +16,4 @@ android:layout_height="40dp" android:layout_gravity="center" android:contentDescription="@string/search_widget_content_description" /> - \ No newline at end of file + diff --git a/app/src/main/res/layout/share_close.xml b/app/src/main/res/layout/share_close.xml index 8bc84de86..918f0c9f3 100644 --- a/app/src/main/res/layout/share_close.xml +++ b/app/src/main/res/layout/share_close.xml @@ -48,4 +48,4 @@ app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toStartOf="parent" app:layout_constraintTop_toBottomOf="@+id/title" /> - \ No newline at end of file + diff --git a/app/src/main/res/layout/share_tab_item.xml b/app/src/main/res/layout/share_tab_item.xml index 47735c24f..48315f2f2 100644 --- a/app/src/main/res/layout/share_tab_item.xml +++ b/app/src/main/res/layout/share_tab_item.xml @@ -48,4 +48,4 @@ app:layout_constraintTop_toBottomOf="@id/share_tab_title" app:layout_constraintEnd_toEndOf="parent"/> - \ No newline at end of file + diff --git a/app/src/main/res/layout/share_to_apps.xml b/app/src/main/res/layout/share_to_apps.xml index 3f654bcfa..54d257d2b 100644 --- a/app/src/main/res/layout/share_to_apps.xml +++ b/app/src/main/res/layout/share_to_apps.xml @@ -101,4 +101,3 @@ - diff --git a/app/src/main/res/layout/tab_history_list_item.xml b/app/src/main/res/layout/tab_history_list_item.xml index 3bdef8369..a58a46d22 100644 --- a/app/src/main/res/layout/tab_history_list_item.xml +++ b/app/src/main/res/layout/tab_history_list_item.xml @@ -8,4 +8,3 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:minHeight="@dimen/library_item_height" /> - diff --git a/app/src/main/res/layout/tab_tray_grid_item.xml b/app/src/main/res/layout/tab_tray_grid_item.xml index 35cdb4c8f..e3a4da115 100644 --- a/app/src/main/res/layout/tab_tray_grid_item.xml +++ b/app/src/main/res/layout/tab_tray_grid_item.xml @@ -51,10 +51,11 @@ A FrameLayout here is an efficient way of having a views stack while allowing: - \ No newline at end of file + diff --git a/app/src/main/res/layout/tabs_tray_tab_counter2.xml b/app/src/main/res/layout/tabs_tray_tab_counter2.xml index 25036e94f..c8ea417bd 100644 --- a/app/src/main/res/layout/tabs_tray_tab_counter2.xml +++ b/app/src/main/res/layout/tabs_tray_tab_counter2.xml @@ -5,7 +5,7 @@ @@ -16,4 +16,4 @@ android:layout_height="wrap_content" mozac:tabCounterTintColor="@color/tab_icon" /> - \ No newline at end of file + diff --git a/app/src/main/res/layout/top_site_item.xml b/app/src/main/res/layout/top_site_item.xml index f02af96fd..97f178960 100644 --- a/app/src/main/res/layout/top_site_item.xml +++ b/app/src/main/res/layout/top_site_item.xml @@ -12,48 +12,35 @@ android:layout_marginBottom="@dimen/top_sites_item_margin_bottom" android:orientation="vertical"> - + app:layout_constraintTop_toTopOf="parent"> + + + - - - - - + app:layout_constraintTop_toBottomOf="@id/favicon_card" + tools:ignore="RtlCompat,SmallSp" /> diff --git a/app/src/main/res/layout/view_synced_tabs_group.xml b/app/src/main/res/layout/view_synced_tabs_group.xml index fe0083253..91abefcc5 100644 --- a/app/src/main/res/layout/view_synced_tabs_group.xml +++ b/app/src/main/res/layout/view_synced_tabs_group.xml @@ -22,6 +22,7 @@ android:textAppearance="@style/Header14TextStyle" android:textColor="@color/primary_text_normal_theme" android:textSize="12sp" + android:textDirection="locale" app:drawableStartCompat="@drawable/mozac_ic_device_desktop" app:drawableTint="@color/primary_text_normal_theme" app:layout_constraintEnd_toEndOf="parent" diff --git a/app/src/main/res/layout/view_synced_tabs_no_item.xml b/app/src/main/res/layout/view_synced_tabs_no_item.xml index 769081cd6..362e45190 100644 --- a/app/src/main/res/layout/view_synced_tabs_no_item.xml +++ b/app/src/main/res/layout/view_synced_tabs_no_item.xml @@ -18,4 +18,4 @@ android:textColor="?secondaryText" android:textSize="12sp" /> - \ No newline at end of file + diff --git a/app/src/main/res/layout/view_synced_tabs_title.xml b/app/src/main/res/layout/view_synced_tabs_title.xml index 7082a78b0..80cfee5aa 100644 --- a/app/src/main/res/layout/view_synced_tabs_title.xml +++ b/app/src/main/res/layout/view_synced_tabs_title.xml @@ -30,4 +30,4 @@ app:srcCompat="@drawable/mozac_ic_refresh" app:tint="?primaryText" /> - \ No newline at end of file + diff --git a/app/src/main/res/menu/download_select_multi.xml b/app/src/main/res/menu/download_select_multi.xml index e0087d5c2..d5cd26234 100644 --- a/app/src/main/res/menu/download_select_multi.xml +++ b/app/src/main/res/menu/download_select_multi.xml @@ -12,4 +12,4 @@ android:id="@+id/delete_downloads_multi_select" android:title="@string/download_delete_item_1" app:showAsAction="never" /> - \ No newline at end of file + diff --git a/app/src/main/res/menu/login_save.xml b/app/src/main/res/menu/login_save.xml index fb9682757..644dbf941 100644 --- a/app/src/main/res/menu/login_save.xml +++ b/app/src/main/res/menu/login_save.xml @@ -11,4 +11,4 @@ app:iconTint="@color/save_enabled_ic_color" android:title="@string/save_changes_to_login" app:showAsAction="always" /> - \ No newline at end of file + diff --git a/app/src/main/res/menu/tab_tray_menu.xml b/app/src/main/res/menu/tab_tray_menu.xml index 35c8e87ff..9022adce5 100644 --- a/app/src/main/res/menu/tab_tray_menu.xml +++ b/app/src/main/res/menu/tab_tray_menu.xml @@ -22,4 +22,4 @@ android:id="@+id/tab_tray_close_menu_item" android:title="@string/tab_tray_menu_item_close" app:showAsAction="never" /> - \ No newline at end of file + diff --git a/app/src/main/res/mipmap-anydpi-v26/ic_launcher_private.xml b/app/src/main/res/mipmap-anydpi-v26/ic_launcher_private.xml index a527ca92e..66196fc1d 100644 --- a/app/src/main/res/mipmap-anydpi-v26/ic_launcher_private.xml +++ b/app/src/main/res/mipmap-anydpi-v26/ic_launcher_private.xml @@ -6,4 +6,4 @@ - \ No newline at end of file + diff --git a/app/src/main/res/mipmap-anydpi-v26/ic_launcher_private_round.xml b/app/src/main/res/mipmap-anydpi-v26/ic_launcher_private_round.xml index a527ca92e..66196fc1d 100644 --- a/app/src/main/res/mipmap-anydpi-v26/ic_launcher_private_round.xml +++ b/app/src/main/res/mipmap-anydpi-v26/ic_launcher_private_round.xml @@ -6,4 +6,4 @@ - \ No newline at end of file + diff --git a/app/src/main/res/navigation/nav_graph.xml b/app/src/main/res/navigation/nav_graph.xml index a302b5d2f..cc865eaa1 100644 --- a/app/src/main/res/navigation/nav_graph.xml +++ b/app/src/main/res/navigation/nav_graph.xml @@ -126,6 +126,9 @@ + @@ -1017,15 +1020,18 @@ android:label="@string/preferences_nimbus_experiments" tools:layout="@layout/mozac_service_nimbus_experiments"> + android:id="@+id/action_nimbusExperimentsFragment_to_nimbusBranchesFragment" + app:destination="@+id/nimbusBranchesFragment" /> + @@ -1037,13 +1043,6 @@ android:id="@+id/creditCardsSettingFragment" android:name="org.mozilla.fenix.settings.creditcards.CreditCardsSettingFragment" android:label="@string/preferences_credit_cards"> - %s en privao %s (en privao) + Más opciones @@ -95,13 +96,6 @@ Escartar - - Cambia la distribución de les llingüetes abiertes. Vete a axustes y esbilla\'l rexáu na vista de llingüetes. - - Dir a Axustes - - Escartar - Llingüeta nueva @@ -428,9 +422,6 @@ Deprender más - - Desactivóse globalmente, vete a Axustes p\'activala - Telemetría @@ -523,8 +514,6 @@ Llingüeta nueva Atopar na llibrería - - Llingüetes sincronizaes Llista de llectura @@ -571,6 +560,10 @@ Dempués d\'un mes + + Siempres + + Enxamás Zarrales a mano @@ -766,8 +759,6 @@ Desanicióse %1$s Amestar una carpeta - - Creóse\'l marcador. ¡Guardóse\'l marcador! @@ -1431,10 +1422,6 @@ en llinia y con nós. Autocompletáu de formularios Sincronización d\'anicios de sesión - - - - Non Calca equí pa reconectar @@ -1564,6 +1551,18 @@ en llinia y con nós. Tarxetes guardaes + + Rellena esti campu + + Configurar + + Dempués + + + Desbloquéu del preséu + + Desbloquia pa usar les tarxetes de creitu atroxaes + Amestar un motor de busca @@ -1722,20 +1721,10 @@ en llinia y con nós. Quitar - - Aprovecha %s al máximu. - Calca pa más detalles - - Coleiciona les coses que t\'importen - - Agrupa busques, sitios y llingüetes asemeyaos p\'acceder aína a ellos dempués. - - Aniciesti sesión como %s n\'otru Firefox d\'esti teléfonu. ¿Quedríes aniciar sesión con esta cuenta? - - Pues amestar fácilmente esti sitiu web a la pantalla d\'aniciu del preséu p\'acceder nel intre y restolalu como si fore una aplicación. + + Zarrar - + diff --git a/app/src/main/res/values-be/strings.xml b/app/src/main/res/values-be/strings.xml index 1c303a0e5..9d0f5b2e4 100644 --- a/app/src/main/res/values-be/strings.xml +++ b/app/src/main/res/values-be/strings.xml @@ -5,6 +5,7 @@ Прыватны %s %s (прыватна) + Дадаткова @@ -48,6 +49,16 @@ Вылучана + + + Нядаўна захаваныя + + Нядаўна захаваныя закладкі + + Паказаць усе + + Паказаць усе захаваныя закладкі + %1$s распрацаваны Mozilla. @@ -91,14 +102,6 @@ Адхіліць - - Змяніце выклад адкрытых картак. Перайдзіце ў налады і абярыце сетку ў раздзеле выгляду картак. - - Перайсці ў налады - - - Закрыць - Новая картка @@ -107,6 +110,12 @@ Папулярныя сайты + + + Назад да + + Паказаць усе + Адкрытыя карткі @@ -184,6 +193,10 @@ Змяніць + + + Хатні экран + Немагчыма злучыцца. Невядомая схема URL. @@ -412,6 +425,11 @@ and the third is the device model. --> %1$s на %2$s %3$s + + Крэдытныя карты + + Адрасы + Атрыманыя карткі @@ -442,9 +460,6 @@ Даведацца больш - - Выключана паўсюль. Перайдзіце ў Налады, каб уключыць. - Тэлеметрыя @@ -455,6 +470,8 @@ Маркетынгавыя дадзеныя Дзяліцца звесткамі пра магчымасці, якімі вы карыстаецеся ў %1$s, з нашым пастаўшчыком мабільнага маркетынгу Leanplum. + + Дзеліцца асноўнымі звесткамі аб выкарыстанні з Adjust, нашым пастаўшчыком мабільнага маркетынгу Даследаванні @@ -546,8 +563,6 @@ Новая картка Знайсці на старонцы - - Сінхранізаваныя карткі Спіс для чытання @@ -592,6 +607,15 @@ Праз месяц + + + Запускаць на хатнім экране + + Праз чатыры гадзіны + + Заўжды + + Ніколі Закрываць уручную @@ -801,8 +825,6 @@ %1$s выдалена Дадаць папку - - Закладка створана. Закладка захавана! @@ -1471,10 +1493,8 @@ Аўтазапаўненне Сінхранізацыя лагінаў - - Уключана - - Выключана + + Сінхранізаваць лагіны паміж прыладамі Перападлучыцца @@ -1578,6 +1598,8 @@ Дадзеныя зашыфраваны Сінхранізаваць карты паміж прыладамі + + Сінхранізаваць карты Дадаць крэдытную карту @@ -1592,6 +1614,10 @@ Нумар карты Тэрмін дзеяння + + Месяц заканчэння тэрміну дзеяння + + Год заканчэння тэрміну дзеяння Імя на карце @@ -1609,6 +1635,27 @@ Захаваныя карты + + Калі ласка, увядзіце сапраўдны нумар крэдытнай карты + + + Калі ласка, запоўніце гэтае поле + + Разблакуйце, каб пабачыць захаваныя карты + + Абараніце свае крэдытныя карты + + Наладзьце графічны ключ, пін або пароль для блакавання прылады, каб абараніць захаваныя крэдытныя карты, калі хтось іншы атрымае доступ да вашай прылады. + + Наладзіць зараз + + Пазней + + + Разблакуйце сваю прыладу + + Разблакуйце, каб выкарыстаць захаваную інфармацыю крэдытнай карты + Дадаць пашукавік @@ -1780,19 +1827,13 @@ Выдаліць - - Атрымайце максімум ад %s. - Пстрыкніце, каб атрымаць падрабязнасці - - Збірайце важныя для вас рэчы - - Групуйце падобныя пошукі, сайты і карткі для хуткага доступу. - - Вы ўвайшлі як %s у іншым браўзеры Firefox на гэтым тэлефоне. Ці хочаце аўтарызавацца з дапамогай гэтага ўліковага запісу? - - Вы можаце лёгка дадаць гэты вэб-сайт на хатні экран свайго тэлефона, каб мець да яго імгненны доступ і аглядаць хутчэй, нібыта гэта асобная праграма. + + Перайсці ўверх + + + Закрыць + diff --git a/app/src/main/res/values-bg/strings.xml b/app/src/main/res/values-bg/strings.xml index e53e87a2f..68cf77eaf 100644 --- a/app/src/main/res/values-bg/strings.xml +++ b/app/src/main/res/values-bg/strings.xml @@ -5,6 +5,7 @@ Поверителен %s %s (поверителен) + Повече настройки @@ -21,10 +22,6 @@ Поверителните раздели ще бъдат показани тук. - - Baidu - - JD 1 отворен раздел. Докоснете за превключване на раздели. @@ -54,6 +51,16 @@ Избран + + + Последно запазени + + Последно запазени отметки + + Показване на всички + + Бутон за показване на всички запазени отметки + %1$s е произведен от @fork-maintainers. @@ -62,7 +69,7 @@ Вие сте в поверителен прозорец - %1$s изчиства историята на търсенето и разглеждането, когато ги затворите или излезете от приложението. Въпреки че това не ви прави анонимни за уеб сайтовете или доставчиците на интернет услуги, улеснява запазването на анонимността на действия ви в мрежата, от останалите ползващи същото устройство. + %1$s изчиства вашата история на търсене и разглеждане от поверителните раздели, когато ги затворите или излезете от приложението. Това не ви прави невидими за уебсайтовете или мрежовите доставчици, но запазва поверителността на вашата дейност онлайн от други ползватели на същото устройството. Разпространени легенди относно поверителното разглеждане Изтриване на сесията @@ -98,20 +105,19 @@ Прекратяване - - Променете изгледа на отворените раздели. Отворете настройки и изберете „мрежа“ в „преглед на раздел“. - - Към настройки - - Прекратяване - Нов раздел Нов поверителен раздел - Най-посещавани страници + Предпочитани страници + + + + Върнете се към + + Показване на всички @@ -130,6 +136,8 @@ Редактиране на отметка Добавки + + Разширения Няма добавки @@ -179,6 +187,18 @@ Външен вид + + Настройки на режим за четене + + + Добавяне + + Редактиране + + + + Начален екран + Грешка при свързване. Неразпознат протокол. @@ -217,6 +237,11 @@ Научете повече + + Търсене с %s + + Търсете директно от адресната лента + Отваряне на раздел във Firefox @@ -364,6 +389,12 @@ Списъкът с добавки е променен. Излизане от приложението за прилагане на промените… + + + Добавката не се поддържа + + Добавката вече е инсталирана + Синхронизиране @@ -398,6 +429,11 @@ and the third is the device model. --> %1$s на %2$s %3$s + + Банкови карти + + Адреси + Получени раздели @@ -428,9 +464,6 @@ Научете повече - - Изключено глобално, посетете Настройки, за да го включите. - Телеметрия @@ -441,6 +474,8 @@ Маркетингови данни Споделя данни за използваните от вас възможности на %1$s чрез Leanplum, нашият партньор за мобилен маркетинг. + + Споделя данни за употребата с Adjust, нашия доставчик на мобилен маркетинг Проучвания @@ -526,8 +561,10 @@ Други отметки История - - Синхронизирани раздели + + Нов раздел + + Търсене в страницата Списък за четене @@ -573,6 +610,15 @@ След един месец + + + Отваряне на началната страница + + След четири часа + + Винаги + + Никога Ръчно затваряне @@ -589,12 +635,16 @@ Поверителни сесии Поверителни раздели + + Синхронизирани раздели Добавяне на раздел Отваря поверителен раздел Поверителен + + Синхронизирани Отворени раздели @@ -605,6 +655,8 @@ Споделяне на всички раздели Последно затворени раздели + + Настройки на сметката Настройки на раздели @@ -722,6 +774,12 @@ Изтриване на изтеглени файлове Сигурни ли сте, че желаете да изтриете изтеглените файлове? + + Изтеглените файлове са премахнати + + Файлът „%1$s“ е премахнат + + Няма изтеглени файлове %1$d избрани @@ -731,6 +789,10 @@ Отваряне + + Премахване + + Извинете. %1$s не можа да зареди страницата. @@ -764,14 +826,12 @@ Изтрита %1$s Добавяне на папка - - Отметката е създадена. Отметката е запазена! - ПРОМЕНЯНЕ + РЕДАКТИРАНЕ - Променяне + Редактиране Избиране @@ -852,9 +912,11 @@ Местоположение - Известие + Известия Постоянно хранилище + + Съдържание под DRM Винаги да пита @@ -873,6 +935,20 @@ Разрешаване на звук и видео + + Разрешаване на звук и видео + + Без звук и видео през мобилни данни + + Звук и видео ще бъдат възпроизвеждани само по Wi-Fi + + Само без звук + + Само без звук + + Без звук и видео + + Без звук и видео Включено @@ -887,6 +963,10 @@ Съберете важните за вас неща.\nГрупирайте търсения, страници и раздели за бърз достъп по-късно. Избиране на раздели + + Избор на списък + + Наименуване на списък Създаване на списък @@ -929,10 +1009,14 @@ Споделяне на препратка + + Изпращане към устройство Всички действия Последно използвани + + Вписване в Sync Вписване в Sync @@ -972,6 +1056,10 @@ Изчистване и отваряне С подкрепата на + + Списъкът е изтрит + + Списъкът е преименуван Разделът е изтрит @@ -982,8 +1070,12 @@ Разделите са затворени Разделите са затворени! + + Отметките са запазени! Преглед + + Добавено към най-посещаваните страници! Поверителният раздел е затворен @@ -992,6 +1084,8 @@ Поверителните раздели са затворени ОТМЕНЯНЕ + + Страницата е премахната Отменяне @@ -1000,8 +1094,14 @@ First parameter is the name of the app, second parameter is the URL or text scanned--> Разрешете %1$s да отвори %2$s + + РАЗРЕШАВАНЕ + + ЗАБРАНЯВАНЕ Наистина ли искате да изтриете %1$s? + + При изтриване на раздела ще бъде изтрит целия списък. Винаги може да създадете нов списък. Изтриване на %1$s? @@ -1014,11 +1114,18 @@ Адресът е копиран + + Това е примерен текст. Той е тук, за да покаже как ще изглежда текста при намаляване и увеличаване на размера чрез тази настройка. Направи текста в уебсайтовете по-голям или по-малък Размер на шрифт + + Автоматичен размер на шрифта + + Размерът на шрифта ще отговаря на настройките на Android. Изключете, за да управлявате размера на шрифта оттук. + Изтриване на данни от разглеждане @@ -1070,19 +1177,44 @@ Историята е изчистена + + Изтриване на данни от разглеждане… + + + + Firefox Preview вече е Firefox Nightly + + + Firefox Nightly се обновява всяка нощ и предлага нови, експериментални възможности. + Поради това, той може да е по-нестабилен. Изтеглете Firefox beta browser, ако предпочитате по-стабилно потребителско усещане. + + Вземете Firefox за Android Beta + + + Firefox Nightly е преместен + + + Това приложение повече няма да получава обновявания по сигурността. Спрете да го използвате и преминете към новия Nightly. + \n\nЗа да прехвърлите вашите отметки, данни за вход и история към друго приложение създайте Firefox Account. Преминете към новият Nightly Firefox Nightly е преместен + + + Това приложение повече няма да получава обновявания по сигурността. Изтеглете новия Nightly и спрете да го използвате. + \n\nЗа да прехвърлите вашите отметки, данни за вход и история към друго приложение създайте Firefox Account. + + Вземете новия Nightly + Здравейте от %s! - - Запознайте се с %s + + Вече имате профил? Вижте какво е новото Получете отговори тук - - Синхронизирайте отметки, пароли и други чрез вашата сметка във Firefox. + + Синхронизирайте Firefox между устройства - Научете повече + Пренесете отметки, история и пароли във Firefox на това устройство. + + Вписани сте като %s в друг Firefox на това устройство. Желаете ли за бъдете вписани с този профил? + + Да, вписване Вписване… - - Вписване във Firefox + + Регистриране + + Без вписване + + Синхронизирането е включено + + Грешка при влизане - Автоматична поверителност - - Настройките за поверителност и сигурност спират проследяващ и злонамерен код, както и компании, които ви преследват. + Постоянна поверителност + + Firefox автоматично предотвратява тайното проследяване от различни компании докато разглеждате в мрежата. Стандартна (подразбиране) - Спира малко проследявания. Страниците зареждат нормално. + Баланс между поверителност и бързодействие. Страниците се зареждат нормално. Строга (препоръчителна) Строга - Спира повече проследявания, реклами и изскачащи прозорци. Страниците зареждат по-бързо, но може да не работят. - - Изберете страна + Спира повече проследявания, така че страниците зарежда по-бързо, но някои функции на страницата може да не работят. + + Изберете място на лентата с инструменти - Изпробвайте работа с една ръка, с лента инструменти отдолу, или я преместете отгоре. + Сложете лентата с инструменти на удобно място. Поставете я долу или я качете горе. Разглеждайте поверително Поверителност + + Ние създадохме %s така, че да имате контрол над това, което споделяте онлайн и с нас. Бележка за поверителността @@ -1143,7 +1287,7 @@ Изберете тема - Запазете батерия и зрението си с избиране на тъмна тема. + Запазете батерия и зрението си с тъмна тема. Автоматичнa @@ -1157,16 +1301,35 @@ Разделите са изпратени! Разделът е изпратен! + + Грешка при изпращане НОВ ОПИТ Сканиране на код + + https://firefox.com/pair]]> + + В готовност за сканиране + + Вписване чрез камерата + + Или чрез електронна поща + + Създайте такъв, за да синхронизирате Firefox между различни устройства.]]> + + Firefox ще спре да се синхронизира с вашия профил, но няма да изтрива данни от разглеждане от устройството. + + %s ще спре да се синхронизира с вашия профил, но няма да изтрива данни от разглеждане от устройството. Изключване Отказ + + Подразбираните папки не могат да бъдат променяни + Настройки на защитата @@ -1184,15 +1347,21 @@ Стандартна (подразбиране) - Спира малко проследявания. Страниците зареждат нормално. + Баланс между поверителност и бързодействие. Страниците се зареждат нормално. + + Какво е спряно от стандартната защита от проследяване Строга - Спира повече проследявания, реклами и изскачащи прозорци. Страниците зареждат по-бързо, но може да не работят. + Спира повече проследявания, така че страниците зарежда по-бързо, но някои функции на страницата може да не работят. + + Какво е спряно от строгата защита от проследяване По избор Изберете какво проследяване и кои скриптове да спрете. + + Какво е спряно от потребителската защита от проследяване Бисквитки @@ -1210,10 +1379,13 @@ Във всички раздели Само в поверителни раздели + + Само в определени раздели Добиване на криптовалути Снемане на цифров отпечатък + Забраняване Разрешено @@ -1261,6 +1433,9 @@ Пренасочващи проследявания + + Изчиства бисквитки за пренасочване към известни проследяващи страници. + Поддръжка @@ -1304,6 +1479,9 @@ Име на пряк път + + Можете лесно да добавите тази страница към началния екран, за да имате бърз достъп до нея, подобно на приложение. + Регистрации и пароли @@ -1316,10 +1494,8 @@ Автоматично попълване Синхронизиране на регистрации - - Включено - - Изключено + + Синхронизиране на регистрации между устройства Повторно свързване @@ -1334,6 +1510,10 @@ Изключения Тук се показват регистрации и пароли, които не са запазени. + + Следните страници няма да запазват регистрации и пароли. + + Изтриване на всички Търсене на регистрация @@ -1355,6 +1535,8 @@ Научете повече + + Желаете ли данните за вход да бъдат запазени от %s? Запазване @@ -1363,10 +1545,18 @@ Паролата е копирана в системния буфер Потребителското име е копирано в системния буфер + + Препратката е копирана Копиране на парола + + Изчистване на паролата Копиране на потребителско име + + Изчистване на потребителското име + + Копиране на сайта Отваряне препратката в четеца @@ -1377,9 +1567,88 @@ Отключете, за да видите запазените регистрации Защитете вашите данни за вход + + Настройте фигура, PIN или парола за отключване на устройството, за да защитите запазените регистрации и пароли, в случай че някой друг има достъп до него. + + По-късно + + Настройване + + Отключете устройството си + + Мащабиране във всички страници + + Разрешава щипване за мащабиране, дори на страници, които не разрешават този жест. + + Име (А-Я) + + Последно използване Меню за сортиране на регистрации + + + Банкови карти + + Запазване и автоматично попълване на карти + + Данните са криптирани + + Синхронизиране на карти между устройства + + Синхронизиране на карти + + Добавяне на карта + + Управление на карти + + Добавяне на карта + + Редактиране на карта + + Номер на карта + + Дата на валидност + + Месец на валидност + + Година на валидност + + Име от картата + + Псевдоним на картата + + Изтриване на картата + + Изтриване на картата + + Запазване + + Запазване + + Отказ + + Запазени карти + + Моля, въведете валиден номер на банкова карта + + Попълнете полето + + Отключете, за да видите запазените карти + + Защитете банковите си карти + + Настройте фигура, PIN или парола за отключване на устройството, за да защитите запазените банкови карти, в случай че някой друг има достъп до него. + + Настройване + + По-късно + + Отключете устройството си + + + Отключете, за да използвате запазената банкова карта + Добавяне на търсеща машина @@ -1414,6 +1683,8 @@ Търсеща машина с име „%s“ вече съществува. + + Въведете низ за търсене Уверете се, че низът за търсене съвпада с примера @@ -1428,6 +1699,8 @@ Добре дошли в един чисто нов %s + + Очаква се напълно преработен четец с подобрена производителност и възможности, които да ви помогнат да направите повече онлайн.\n\nИзчакайте, докато добавяме към %s вашите Обновяване на %s… @@ -1437,10 +1710,57 @@ Пароли + + За да разрешите: + + 1. Отворете Настройки на Android + + Разрешения]]> + + + %1$s в положение ВКЛЮЧЕНО]]> + + + Шифрована връзка + + Незащитена връзка + + Сигурни ли сте, че искате да премахнете всички права за всички страници? + + Сигурни ли сте, че искате да премахнете всички права за страницата? + + Сигурни ли сте, че искате да премахнете това право за страницата? + + Няма изключения + + Предпочитани статии + + Сигурен ли сте, че искате да изтриете отметката? + + Добавяне към предпочитаните + + Проверено от: %1$s Изтриване + + Редактиране + + Сигурни ли сте, че искате да изтриете тези данни за вход? Изтриване + + Настройки за вход + + Текстовото поле за редактиране на адреса на регистрация. + + Текстовото поле за редактиране на потребителското име на регистрация. + + Текстовото поле за редактиране на паролата на регистрация. + + Запазване на промените на регистрацията. + + Отказ от промените Редактиране @@ -1469,28 +1789,38 @@ Няма отворени раздели + + + Пределът за добавяне на предпочитани страници е достигнат + + За да добавите друга предпочитана страница премахнете някоя. Натиснете и задръжте върху нея, след това я премахнете. Добре, разбрах - + + Най-посещавани страници + Наименование + + Име на предпочитана страница Добре Отказ + + Задайте Firefox като стандартно приложение за отваряне на страници, електронна поща и съобщения. + Премахване - - Извлечете максимума от %s - Натиснете за подробности - - Съберете нещата, които са важни за вас - - Групирайте заедно подобни търсения, сайтове и раздели за бърз достъп по-късно. - + + Придвижване нагоре + + + Затваряне + + diff --git a/app/src/main/res/values-br/strings.xml b/app/src/main/res/values-br/strings.xml index 470b8a8cd..89d2e966c 100644 --- a/app/src/main/res/values-br/strings.xml +++ b/app/src/main/res/values-br/strings.xml @@ -91,13 +91,6 @@ Argas - - Cheñchit ar mod ma vez diskouezet an ivinelloù digoret. Kit en arventennoù ha diuzit eta gael ha dindan mod-diskouez an ivinelloù. - - Mont en arventennoù - - Argas - Ivinell nevez @@ -180,6 +173,10 @@ Embann + + + Skramm degemer + Ne cʼhaller ket kennaskañ. Steuñv URL dianav. @@ -541,8 +538,6 @@ Ivinell nevez Kavout er bajenn - - Ivinelloù goubredet Roll Lennadurioù @@ -587,6 +582,15 @@ Goude ur mizvezh + + + Kregiñ gant ar skramm degemer + + Goude peder eurvezh + + Atav + + Morse Serriñ an dornlevr @@ -1562,6 +1566,10 @@ Deiziad termen + + Deiziad termen Miz + + Deiziad termen Bloaz Anv war ar gartenn @@ -1582,6 +1590,25 @@ Biziatait un niverenn kartenn gred talvoudek mar plij. + + Mar plij, leugnit ar maez-mañ + + Dibrennit da welet ho kartennoù enrollet + + Diogelit ho kartennoù kred + + + Arventennit ur patrom prennañ, ur PIN pe ur ger-tremen evit gwareziñ ho kartennoù kred enrollet ma vez ho trevnad gant unan bennak all. + + Arventennañ bremañ + + Diwezhatoc’h + + Dibrennit ho trevnad + + + Dibrennit evit implijout titouroù kartenn gred enrollet + Ouzhpennañ ul lusker klask diff --git a/app/src/main/res/values-ca/strings.xml b/app/src/main/res/values-ca/strings.xml index b298019b5..5fdb858a5 100644 --- a/app/src/main/res/values-ca/strings.xml +++ b/app/src/main/res/values-ca/strings.xml @@ -6,6 +6,7 @@ %s privat %s (nav. privada) + Més opcions @@ -21,10 +22,6 @@ Les pestanyes privades es mostraran aquí. - - Baidu - - JD 1 pestanya oberta. Toqueu per canviar de pestanya. @@ -53,6 +50,16 @@ S’ha seleccionat + + + Desades recentment + + Adreces d’interès desades recentment + + Mostra-ho tot + + Mostra el botó de totes les adreces d’interès desades + El %1$s està creat per @fork-maintainers. @@ -96,13 +103,6 @@ Descarta - - Canvieu la disposició de les pestanyes obertes. Aneu als paràmetres i trieu «graella» a la vista de pestanyes. - - Vés als paràmetres - - Descarta - Pestanya nova @@ -112,6 +112,12 @@ Llocs principals + + + Torneu a la pestanya + + Mostra-ho tot + Pestanyes obertes @@ -182,6 +188,15 @@ Personalitza la vista de lectura + + Afegeix + + Edita + + + + Pantalla d’inici + No s’ha pogut connectar. No es reconeix l’esquema d’URL. @@ -414,6 +429,11 @@ and the third is the device model. --> %1$s en %2$s %3$s + + Targetes de crèdit + + Adreces + Pestanyes rebudes @@ -444,9 +464,6 @@ Més informació - - Desactivada globalment, aneu als Paràmetres per activar-la. - Telemesura @@ -457,6 +474,8 @@ Dades de màrqueting Comparteix dades de funcions que utilitzeu al %1$s amb Leanplum, el nostre proveïdor de màrqueting mòbil. + + Comparteix dades bàsiques d’ús amb Adjust, el nostre proveïdor de màrqueting mòbil Estudis @@ -543,8 +562,6 @@ Pestanya nova Cerca a la pàgina - - Pestanyes sincronitzades Llista de lectura @@ -589,6 +606,15 @@ Al cap d’un mes + + + Comença a la pantalla d’inici + + Passades quatre hores + + Sempre + + Mai Tanca-les manualment @@ -605,12 +631,16 @@ Sessió privada Pestanyes privades + + Pestanyes sincronitzades Afegeix una pestanya Afegeix una pestanya privada Privada + + Sincronitza Pestanyes obertes @@ -621,6 +651,8 @@ Comparteix totes les pestanyes Pestanyes tancades recentment + + Paràmetres del compte Paràmetres de les pestanyes @@ -791,8 +823,6 @@ S’ha suprimit %1$s Afegeix una carpeta - - S’ha creat l’adreça d’interès. S’ha desat l’adreça d’interès @@ -978,6 +1008,8 @@ Totes les accions Usades recentment + + Inicia la sessió per sincronitzar Inicia la sessió al Sync @@ -1171,9 +1203,6 @@ Ja teniu un compte? - - Coneixeu el %s Descobriu les novetats Vegeu les respostes aquí - - Comenceu a sincronitzar les adreces d’interès, les contrasenyes i molt més amb el vostre compte del Firefox. + + Sincronitzeu el Firefox entre dispositius - Més informació + Importeu les adreces d’interès, l’historial i les contrasenyes al Firefox d’aquest dispositiu. @@ -1193,8 +1222,8 @@ Sí, inicia la sessió S’està iniciant la sessió… - - Inicia la sessió al Firefox + + Registre No iniciïs la sessió @@ -1202,26 +1231,23 @@ No s’ha pogut iniciar la sessió - Privadesa automàtica - - Els paràmetres de privadesa i de seguretat bloquen els elements de seguiment, el programari maliciós i les empreses que us fan el seguiment. + Privadesa sempre activa + + El Firefox bloca automàticament les empreses que, en secret, us fan el seguiment mentre navegueu. Estàndard (per defecte) - Es bloquen menys elements de seguiment. Les pàgines es carregaran amb normalitat. + Equilibri entre privadesa i rendiment. Les pàgines es carreguen amb normalitat. Estricta (recomanat) Estricta - Bloca més elements de seguiment, anuncis i finestres emergents. Les pàgines es carreguen més ràpidament, però és possible que algunes característiques no funcionin. - - Posicioneu-vos + Bloca més elements de seguiment i fa que les pàgines es carreguin més ràpidament, però podria causar problemes amb algunes funcions de la pàgina. + + Trieu la ubicació de la barra d’eines - Proveu la navegació amb una sola mà amb la barra d’eines part inferior o moveu-la al capdamunt. + Tingueu la barra d’eines a mà. La podeu mantenir a la part inferior o moure-la a dalt. Navegueu amb privadesa La vostra privadesa + The first parameter is the name of the app (e.g. Firefox Preview) Substitute %s for long browser name. --> Hem dissenyat el %s per donar-vos el control sobre tot allò que compartiu en línia i que compartiu amb nosaltres. Mostra l’avís de privadesa @@ -1249,7 +1275,7 @@ Trieu el tema - Estalvieu bateria i descanseu la vista activant el mode fosc. + Estalvieu bateria i descanseu la vista amb el mode fosc. Automàtic @@ -1305,13 +1331,13 @@ Estàndard (per defecte) - Es bloquen menys elements de seguiment. Les pàgines es carregaran amb normalitat. + Equilibri entre privadesa i rendiment. Les pàgines es carreguen amb normalitat. Què es bloca en la protecció contra el seguiment estàndard Estricta - Bloca més elements de seguiment, anuncis i finestres emergents. Les pàgines es carreguen més ràpidament, però és possible que algunes característiques no funcionin. + Bloca més elements de seguiment i fa que les pàgines es carreguin més ràpidament, però podria causar problemes amb algunes funcions de la pàgina. Què es bloca en la protecció contra el seguiment estricta @@ -1453,10 +1479,8 @@ Emplenament automàtic Sincronitza els inicis de sessió - - Activat - - Desactivat + + Sincronitza els inicis de sessió entre dispositius Torna a connectar @@ -1548,6 +1572,69 @@ Ordena el menú d’inicis de sessió + + + Targetes de crèdit + + + Desa i emplena automàticament les targetes + + Les dades estan xifrades + + Sincronitza les targetes entre dispositius + + Sincronitza les targetes + + Afegeix una targeta de crèdit + + Gestiona les targetes desades + + Afegeix una targeta + + Edita la targeta + + Número de targeta + + Data de caducitat + + Mes de la data de caducitat + + Any de la data de caducitat + + Nom del titular + + Sobrenom de la targeta + + Suprimeix la targeta + + Suprimeix la targeta + + Desa + + Desa + + Cancel·la + + Targetes desades + + Introduïu un número de targeta de crèdit vàlid + + Empleneu aquest camp + + Desbloqueu per veure les targetes desades + + Protegiu les vostres targetes de crèdit + + Configureu un patró de bloqueig del dispositiu, un PIN o una contrasenya perquè cap persona que accedeixi al vostre dispositiu pugui veure les targetes de crèdit que deseu. + + Configura-ho ara + + Més tard + + Desbloqueu el dispositiu + + Desbloqueu per utilitzar la informació emmagatzemada d’una targeta de crèdit + Afegeix un motor de cerca @@ -1708,23 +1795,19 @@ Cancel·la + + Feu que els enllaços dels llocs web, del correu electrònic i dels missatges s’obrin automàticament en el Firefox. + Elimina - - Traieu tot el profit al %s. - Feu clic aquí per a veure més informació - - Recolliu tot allò que us insteressa - - Agrupeu les cerques, els llocs i les pestanyes similars per accedir-hi ràpidament en el futur. - - Ja heu iniciat la sessió com a %s en un altre navegador Firefox d’aquest telèfon. Voleu iniciar la sessió amb aquest compte? - - Podeu afegir fàcilment aquest lloc web a la pantalla d’inici del telèfon per accedir-hi directament i navegar-hi com si fos una aplicació. + + Navega cap amunt + + + Tanca - + diff --git a/app/src/main/res/values-cak/strings.xml b/app/src/main/res/values-cak/strings.xml index d39f31f59..38c877950 100644 --- a/app/src/main/res/values-cak/strings.xml +++ b/app/src/main/res/values-cak/strings.xml @@ -97,13 +97,6 @@ Tewäx - - Tijal kiwachib\'enik jaqon taq ruwi\'. Jät pa Runuk\'ulem k\'a ri\' tacha\' ri kajtz\'ikil pa peraj kitzub\'al taq ruwi\'. - - Jät pa runuk\'ulem - - Tewäx - K’ak’a’ ruwi’ @@ -567,8 +560,6 @@ K\'ak\'a\' ruwi\' Tikanöx pa ruxaq - - Ximon taq ruwi\' Rucholajem sik\'inem @@ -614,6 +605,8 @@ Jun ik\' tik\'o + + Junelïk Titz\'apïx chi q\'ab\'aj @@ -1637,6 +1630,15 @@ Titz\'ib\'äx jun okel rajilab\'al rutarjeta\' kre\'ito\' + + Tanojisaj re k\'ojlem re\' + + Tib\'an runuk\'ulem wakami + + Jub\'a\' chik na + + Man taq\'ät chik ri awokisab\'al + Titz\'aqatisäx kanob\'äl diff --git a/app/src/main/res/values-ckb/strings.xml b/app/src/main/res/values-ckb/strings.xml new file mode 100644 index 000000000..e6804d187 --- /dev/null +++ b/app/src/main/res/values-ckb/strings.xml @@ -0,0 +1,1654 @@ + + + + تایبەت %s + + %s (تایبەت) + + + هەڵبژاردەی زیاتر + + گەڕانی تایبەتی شاراوە کارابکە + + گەڕانی تایبەتی شاراوە ناچالاک بکە + + بگەڕێ یان ناونیشان بنووسە + + بازدەرە کراوەکانت لێرە پیشان دەدرێت. + + بازدەرە تایبەتە شاراوەکان لێرە پیشان دەدرێت + + ١ بازدەر کراوەیە. پەنجەدابگرە بۆ گۆڕینی بازدەرەکان. + + %1$s بازدەر کراوەیە. پەنجەدابگرە بۆ گۆڕینی بازدەرەکان. + + %1$d دیاریکراوە + + کۆمەڵەیەکی نوێ زیادبکە + + ناو + + کۆمەڵە هەڵبژێرە + + لە دۆخی دیاریکردنی چەندیی دەربچۆ + + بازدەرە دیاریکراوەکان هەڵبگرە لە کۆمەڵەکە + + + + %1$s دیاریکرا + + %1$s گێڕاوە لە دیاریکردن + + دەرچووی لە دۆخی دیارتکردنی چەندی + + دۆخی دیاریکردنی چەندانەیی، بازدەرەکان هەڵبژێرە بۆ ختنە کۆکەرەوە + + دیاریکرا + + + %1$s بەرهەم هێنراوە لە لایەن مۆزیلاوە. + + + + تۆ لە دانیشتنێکی تایبەتدایت + + چەند ئەفسانەییەک دەربارەی گەڕانی تایبەتیی + + + دانیشتن بسڕەوە + + + + قەدبڕێک درووستبکە بۆ کردنەوەی بازدەری تایبەتی شاراوە لە شاشەی سەرەکەییەوە. + + قەدبڕ زیادبکە + + نا سوپاس + + + + دەتوانیت وا لە فایەرفۆکس بکەیت کە خۆاکارانە بەستەرەکان لەناو بەرنامەکان بکاتەوە. + + بڕۆ بۆ ڕێکخستن + + پشتگوێخستن + + + داواکاری کامێرا چالاک کرا. بڕۆ بۆ ڕێکخستنەکانی ئاندرۆید، پەنجەبنێ بە دەسەڵاتەکان و ئینجا ڕێگەپێدان هەڵبژێرە. + + بڕۆ بۆ ڕێکخستن + + پشتگوێخستن + + + هەڵبژاردەکان پیشان بدە + + پشتگوێخستن + + + بڕۆ بۆ ڕێکخستن + + پشتگوێخستن + + + + بازدەری نوێ + + بازدەری تایبەتی نوێ + + ماڵپەڕە بەرزەکان + + + + بازدەرەکان بکەرەوە + + دواوە + + پێشەوە + + نوێکردنەوە + + بوەستە + + دڵخواز + + دڵخوازەکان دەستکاریبکە + + پێوەکراوەکان + + زیادکراوەکان + + هیچ پێوەکراوێک نیە + + یارمەتی + + چی نوێ هەیە + + ڕێکخستنەکان + + کتێبخانە + + پیشاندانی ماڵپەڕ وەک ڕوومێز + + زیادی بکە بۆ شاشەی سەرەکی + + دامەزراندن + + بازدەرە هاوکاتپێکراوەکان + + + + هاوکاتپێکردنەوە + + لە ناو پەڕگە بگەڕێ + + بازدەری تایبەت + + هەڵگرتن لە کۆمەڵە + + بڵاوکردنەوە + + بڵاوەپێکردن لەگەڵ... + + کردنەوە لە %1$s + + پشتگیریکراوە لە لایەن %1$s + + پشتگیریکراوە لە لایەن %1$s + + شێوازی دۆخی خوێندنەوە + + شێوازی دۆخی خوێندنەوە دابخە + + کردنەوە لە بەرنامە + + ڕووکار + + شێوازی خوێندنەوە ڕێکبخە + + زیادکردن + + دەستکاریکردن + + + نەتوانرا پەیوەندی بکرێت. شێوەی بەستەرەکە نەناسراوە. + + + + زمانی هەڵبژێردراو + + گەڕان + + وەکوو زمانی ئامێرەکە + + گەڕان بۆ زمان + + + + گەڕانی QR + + بزوێنەری گەڕان + + ڕێکخستنەکانی بزوێنەری گەڕان + + لەم کاتەدا، بگەڕێ لەگەڵ: + + بەستەر بهێنە لە گرتەتەختەوە + + ڕێگەبدە + + ڕێگە مەدە + + ڕێگە دەدەی بە پێشنیاری گەڕان لە دانییشتنی شاراوەی تایبەت؟ + + زیاتر بزانە + + بگەڕێ بۆ %s + + + + ڕاستەوخۆ گەڕان بکە لە توڵی ناونیشانەوە + + + + بازدەرێکی نوێی فایەرفۆکس بکەرەوە + + گەڕان + + بگەڕێ کە وێبدا + + گەڕانی دەنگی + + + + ڕێکخستنەکان + + + + بنەڕەتیی + + گشتی + + دەربارە + + بزوێنەری گەڕانی بنەڕەتی + + گەڕان + + توڵی ناونیشان + + یارمەتی + + + + هەڵسەنگاندن لە گووگڵ پلەی + + پێشنیار بنێرە + + دەربارەی %1$s + + مافەکانت + + وشەی تێپەڕبوونەکان + + کارتی بانکی و ناونیشانەکان + + بیکە وێبگەڕی سەرەکی + + پێشکەوتوو + + تایبەتیی + + تایبەتیی و پاراستن + + ڕێگەپێدانەکانی ماڵپەڕ + + وێبگەڕانی تایبەتی + + کردنەوەی بەستەر لە بازدەری تایبەت + + ڕێگە بە وێنەگرتنی شاشە بدە لە وێبگەڕانی تایبەتی + + ئەگەر ڕێگەدرا، بازدەرە تایبەتەکانیش بینراو دەبن کاتێک چەند بەرنامەیەک کراونەتەوە + + قەدبڕێ وێبگەڕانی تایبەتی زیاد بکە + + دەستپێگەیشتن + + ڕاژەی خوازراو بۆ هەژماری فایەرفۆکس + + ڕاژەی خوازراو بۆ هاوکاتگەری + + هەژمار + + بچۆژوورەوە + + توڵامراز + + ڕووکار + + ماڵەوە + + جوڵاندنەکان + + دەستکاریکردن + + نیشانەکراوەکان، مێژووی کار، وزیاتر لەگەڵ هەژماری فایەرفۆکس + + هەژماری Firefox + + دووبارە پەیوەندی بکەرەوە بۆ هێنانەوەی هاوکاتگەری + + زمان + + هەڵبژاردنەکانی زانیاری + + کۆمەڵی زانیاری + + سەرنجی تایبەتیی + + ئامرازی گەشەپێدەر + + هەڵەدۆزی دوور لەڕێگەی USB + + بزوێنەرەکانی گەڕان پیشان بدە + + پێشنیارەکانی گەڕان پیشان بدە + + + + گەڕانی دەنگی پیشان بدە + + لە دانیشتنی تایبەت پیشانی بدە + + بگەڕێ لە مێژووی کار + + گەڕان لە نیشانەکراوەکان + + بگەڕێ لەناو بازدەرە هاوکاتگەری کراوەکان + + ڕێکخستنی هەژمار + + تەواوکەری خۆکاری URLs + + کردنەوەی بەستەر لە بەرنامەکان + + بەڕێوەبردنی داگرتنی دەرەکی + + پێوەکراوەکان + + ئاگانامەکان + + + + کۆمەڵەیەکی پێوەکراوی دڵخواز + + باشە + + پاشگەزبوونەوە + + ناوی کۆکراوە + + خاوەنی کۆکراوە (ناونیشانی بەکارهێنەر) + + + + + پێوەکراو پشتگیری ناکرێت + + پێوەکراو پێشتر دامەزراوە + + + + هاوکاتگەری پێکردن + + هەڵبژێرە چ هاوکاتگەری پێبکرێت + + مێژوو + + جێنیشانه‌که‌ر + + چوونەژوورەوەکان + + بازدەرەکان بکەرەوە + + بچۆ دەرەوە + + ناوی ئامێر + + ناوی ئامێر نابێت بەتاڵ بێت + + هاوکاتگەری دەکرێت... + + هاوکاتگەری هەڵوەشا. کۆتا هەوڵ: %s + + هاوکاتگەری هەڵوەشا. کۆتا هاوکاتگەری: هەرگیز + + کۆتا هاوکاتگەری: %s + + کۆتا هاوکاتگەری: هەرگیز + + %1$s لە %2$s%3$s + + + کارتی پڕکردنەوەی بانکی + + ناونیشانەکان + + + + بازدەری بەدەستگەیشتوو + + + ئاگانامەکان بۆ بازدەر هاتووە لە ئامێرێکی تری فایەرفۆکسەوە. + + بازدەر گەیشت + + بازدەرەکان گەیشتن + + + بازدەر لە %s + + + + پارێزگاری لە چاودێری + + پارێزگاری لە چاودێری + + ئەو ناوەڕۆک و سکریپتانە بکە کە چاودێریت دەکەن لەسەر هێڵ + + هەڵاوێردی + + پارێزگاری چاودێری ناکارایە بۆ ئەو ماڵپەڕانە + + بیکە کار بۆ هەموو ماڵپەڕەکان + + هەڵاوێردی ڕێگەتپێدەدات کە پارێزگاریکردن لە چاودێری ناکارا بکەیت بۆ چەند ماڵپەڕێکی دیاریکراو. + + زیاتر بزانە + + + پێوانەی دووری + + بەکارهێنان و زانیاری تەکنیکی + + چوستی وێبگەڕ، بەکارهێنانی و زانیاری خوازراوی وێبگەڕەکەت بڵاوەپێدەکات لەگەڵ مۆزیلا بۆ ئەوەی یارمەتیمان بدات %1$s باشتر بکەین + + زانیاری بازاڕیکردن + + ئەو زانیارییانە بڵاودەکاتەوە کە چ تایبەتمەندییەک بەکاردێنیت لە %1$s لەگەڵ Leanplum، کە بریتییە لە فرۆشیاری بازاڕی مۆبایل ئێمە کاری لەگەڵ دەکەین. + + زانیاری سەرەتایی بڵاودەکاتەوە لەگەڵ Adjust، کە بریتییە لە فرۆشیارێکی ئێمە بۆ بازاڕی مۆبایل. + + توێژینەوە + + ڕێگە بدە مۆزیلا توێژینەوە دابمەزرێنێت و کاری پێبکات + + تاقیکردنەوەکان + + + ڕێگەدەدات کە مۆزیلا زانیاری وەدەستبخات دامەزراندن ئەنجام بدات بۆ ئەو تایبەتمەندییە تاقیکارییانەی پێشکەشی دەکەین + + ڕاپۆرت لێدەری تێکشکان + + خزمەتگوزاری شوێنی مۆزیلا + + ڕاپۆرت تەندروستی %s + + + + هاوکاتگەری پێبکە + + کۆدی پێکبەستنەوە سکان بکە لە فایەرفۆکس (ڕوومێز) + + بچۆژوورەوە + + بچۆژوورەوە بۆ بۆ پەیوەندی گرتنەوە + + هەژمار بسڕەوە + + + + firefox.com/pair پیشان دەدرێت]]> + + کامێرا بکەرەوە + + پاشگەزبوونەوە + + + + سەرەوە + + خوارەوە + + + + ڕوون + + تاریک + + دیاریکراوە لە لایەن پارێزەری باتریەوە + + وەکوو ڕووکاری سیستم + + + + بیخزێنە بۆ نوێکردنەوە + + بیخزێنە بۆ شاردنەوەی توڵامراز + + توڵامراز ببە بۆ لاکان بۆ گۆڕین لە نێوان بازدەرەکان + + + + توڵامراز ببە بۆ سەرەوە بۆ کردنەوەی بازدەرەکان + + + + دانیشتنەکان + + وێنەی ڕووپەر(شاشە) + + داگرتنەکان + + نیشانەکراوەکان + + نیشانەکراوەکانی ڕوومێز + + پێرستی نیشانەکراوەکان + + توڵامرازی نیشانەکراوەکان + + نیشانکراوەکانی تر + + مێژوو + + بازدەری نوێ + + لە ناو پەڕە بگەڕێ + + بازدەرە هاوکاتپێکراوەکان + + لیستەی خوێندراوەکان + + گەڕان + + ڕێکخستنەکان + + پێڕستی بڕگەی مێژووی کار + + داخستن + + + کۆتا بازدەری داخراو + + هەمووی مێژووی کار پیشان بدە + + %d بازدەر + + %d بازدەر + + هیچ بازدەرێکی داخراوی نوێ نیە + + + + بازدەرەکان + + پێشبینینی بازدەر + + لیست + + هێڵەکی + + بازدەرەکان دابخە + + دەستیی + + دووای یەک ڕۆژ + + دووای یەک هەفتە + + دووای یەک مانگ + + + داخستنی دەستیی + + داخستن دووای یەک ڕۆژ + + داخستن دووای یەک هەفتە + + داخستن دووای یەک مانگ + + + + بازدەرەکان بکەرەوە + + دانیشتنی تایبەت + + بازدەرە تایبەتەکان + + بازدەرە هاوکاتپێکراوەکان + + بازدەر زیادبکە + + بازدەری تایبەت زیاد بکە + + تایبەت + + هاوکاتگەری + + بازدەرەکان بکەرەوە + + هەڵگرتن لە کۆکەرەوە + + هەڵبژێرە + + هەموو بازدەرەکانی بڵاوەپێبکە + + کۆتا بازدەری داخراو + + ڕێکخستنی هەژمار + + ڕێکخستنەکانی بازدەر + + هەموو بازدەرەکان دابخە + + بازدەری نوێ + + بڕۆ پەڕەی سەرەکی + + دۆخی گۆڕینی بازدەر + + نیشانەکراو + + داخستن + + بازدەری دیاریکراو بڵاوبکەرەوە + + پێڕستی بازدەری دیاریکراو + + بازدەر بسڕەوە لە کۆکەرەوە + + بازدەر دیاریبکە + + بازدەر دابخە + + بازدەری %s دابخە + + پێڕستی بازدەرەکان بکەرەوە + + هەموو بازدەرەکان دابخە + + بازدەرەکان بڵاوبکەرەوە + + بازدەرەکان هەڵبگرە لە کۆکەرەوە + + پێڕستی بازدەر + + بازدەری بڵاوکردنەوە + + سڕینەوە + + پاشەکەوتکردن + + بڵاوکردنەوە + + وێنەی دانیشتنی ئێستا + + هەڵگرتن لە کۆکەرەوە + + کۆکەرەوە بسڕەوە + + ناونانەوەی کۆکەرەوە + + بازدەرەکان بکەرەوە + + ناوی کۆکراوە + + + + دووبارە ناونانەوە + + بیسڕەوە + + سڕینەوە لە مێژووی کار + + %1$s (دۆخی تایبەت) + + پاشەکەوتکردن + + + + مێژووی کار بسڕەوە + + ئایا تۆ دڵنیایت کە دەتەویت مێژووی کار پاکبکەیتەوە/بسڕیتەوە؟ + + مێژوو سڕایەوە + + %1$s سڕایەوە + + پاککردنەوە + + لەبەرگرتنەوە + + بڵاوکردنەوە + + کردنەوە لە بازدەری نوێ + + کردنەوە لە بازدەری تایبەت + + سڕینەوە + + %1$d دیاریکراوە + + %1$d بڕگە سڕایەوە + + ئەمڕۆ + + دوێنێ + + کۆتا 24 کاژێر + + کۆتا 7 ڕۆژ + + کۆتا 30 ڕۆژ + + کۆنتر + + هیچ مێژووییەک نیە + + + + سڕینەوەی داگرتنەکان + + ئایا تۆ دڵنیاییت کە دەتەوێت داگرتنەکان پاکبکەیتەوە؟ + + داگرتنەکان سڕانەوە + + %1$s سڕایەوە + + هیچ پەڕەیەکی داگیراو نیە + + %1$d دیاریکراوە + + کردنەوە + + بیسڕەوە + + + + + ببورە. %1$s ناتوانێت ئەو پەڕەیە باربکات. + + دەتوانیت هەوڵبدەیت بۆ گێڕانەوە یان ئەم بازدەرەی خوارەوە دابخەیت + + ڕاپۆرتی کێشە بنێرە بۆ مۆزیلا + + بازدەر دابخە + + بازدەر بهێنرەوە + + + هەڵبژاردنەکانی دانیشتن + + + دانیشتنی بڵاوکردنەوە + + + + پێڕستی نیشانەکراوەکان + + نیشانەکراوەکان دەستکاریبکە + + بوخچە هەڵبژێرە + + ئایا تۆ دڵنیایت دەتەوێت ئەم بوخچەیە بسریتەوە؟ + + + %s برگە دیاریکراوەکان دەسڕێتەوە. + + %1$s سڕایەوە + + بوخچە زیادبکە + + نیشانکراو پاشەکەوتکرا! + + دەستکاریکردن + + دەستکاریکردن + + هەڵبژێرە + + لەبەرگرتنەوە + + بڵاوکردنەوە + + کردنەوە لە بازدەری نوێ + + کردنەوە لە بازدەری تایبەت + + سڕینەوە + + پاشەکەوتکردن + + %1$d دیاریکراوە + + نیشانەکراوەکان دەستکاریبکە + + بوخچە دەستکاریبکە + + بچۆ ژوورەوە بۆ بینینی نیشانکراوە هاوکاتگەری پێکراوەکان + + بەستەر + + بوخچە + + ناو + + بوخچە زیادبکە + + بوخچە هەڵبژێرە + + پێویستە ناونیشانی هەبێت + + بەستەر نەگونجاوە + + هیچ نیشانکراوێک نیە لێرە + + %1$s سڕایەوە + + نیشانکراوەکان سڕانەوە + + بوخچەی دیاریکراو دەسڕدرێتەوە + + گێڕانەوە + + + + ڕێگەپێدانەکان + + بڕۆ بۆ ڕێکخستنەکان + + شیتی ڕێکخستنی خێرا + + پێشنیارکراو + + بەڕێوەبردنی ڕێگەپێدانەکانی ماڵپەڕ + + ڕێگەپێدانەکان پاکبکەرەوە + + ڕێگەپێدانەکان پاکبکەرەوە + + ڕێگەپێدانەکان پاکبکەرەوە لە هەموو ماڵپەڕەکان + + خۆپێکردن + + کامێرا + + مایکرۆفۆن + + شوێن + + ئاگانامەکان + + بیرگەی هەمیشەیی + + ناوەڕۆکی کۆنتڕۆڵکراوی DRM + + داوای ڕێگەپێدان بکە + + بلۆککراوە + + ڕێگەپێدراوە + + بلۆککراوە لە لایەن ئەندرۆیدەوە + + هەڵاوێردییەکان + + کارا + + ناکارا + + ڕێگەبدە بە دەنگ و ڕەنگ + + ڕێگەبدە بە دەنگ و ڕەنگ + + دەنگ و ڕەنگ بلۆک بکە تەنها لە کاتی بەکارهێنانی ئینتەرنێتی مۆبایل (دەستی) + + دەنگ و ڕەنگ کاردەکەن لە وای-فای + + تەنها دەنگ بلۆک بکە + + تەنها دەنگ بلۆک بکە + + دەنگ و ڕەنگ بلۆک بکە + + دەنگ و ڕەنگ بلۆک بکە + + کارا + + ناکارا + + + + کۆکەرەوەکان + + پێڕستی کۆکەرەوەکان + + + بازدەرەکان دیاریبکە + + کۆکەرەوە هەڵبژێرە + + کۆکەرەوە ناوبنی + + کۆکەرەوەیەکی نوێ زیادبکە + + هەمووی دیاریبکە + + دیاریکردنی هەموو لابدە + + بازدەر هەڵبژیرە بە هەڵگرتن + + %d بازدەر دیاریکراوە + + %d بازدەر دیاریکراوە + + بازدەرەکان پاشەکەوتکرا! + + کۆکەرەوە پاشەکەوتکرا! + + بازدەر پاشەکەوتکرا! + + داخستن + + پاشەکەوتکردن + + پیشاندان + + + کۆکەرەوەی %d + + + + بینێرە و بڵاویبکەرەوە + + بڵاوکردنەوە + + بڵاوکردنەوە + + بەستەر بڵاوبکەرەوە + + بینێرە بۆ ئامێر + + هەموو کردارەکان + + دووا بەکارهێنراو + + بۆ هاوکاتکردن بچۆژوورەوە + + بچۆژوورەوە بۆ هاوکاتگەری + + بینێرە بۆ هەموو ئامێرەکان + + بیبەستەرەوە بۆ هاوکاتگەری + + دەرهێڵ + + پەیوەندی بکە بە ئامێرێکی تر + + بۆ ناردنی بازدەر، پێویستە بەلایەنی کەمەوە بچیتە ژوورەوە لە ئامێرێکی تری فایەرفۆکس. + + تێگەیشتم + + + ناتوانرێت بڵاوبکرێتەوە بۆ ئەم بەرنامەیە + + بینێرە بۆ ئامێر + + هیچ ئامێرێک پەیوەست نیە + + زیاتر بزانە دەربارەی ناردنی بازدەرەکان... + + پەیوەندی بکە بە ئامێرێکی تر... + + + + دانیشتنی گەڕانی تایبەت + + بازدەری تایبەت بسڕەوە + + بازدەری تایبەت دابخە + + کردنەوە + + سڕینەوە و کردنەوە + + پشتگیریکراوە لە لایەن + + کۆکەرەوە سڕایەوە + + کۆکەرەوە ناولێنرایەوە + + بازدەر سڕایەوە + + بازدەرەکان سڕانەوە + + بازدەر داخرا + + بازدەرەکان داخران + + بازدەرەکان داخران! + + نیشانەکراو هەڵگیرا! + + پیشاندان + + زیادکرا بۆ ماڵپەڕە بەرزەکان + + بازدەری تایبەت داخرا + + بازدەرە تایبەتەکان داخران + + بازدەرە تایبەتەکان سڕانەوە + + گێڕانەوە + + ماڵپەڕ سڕایەوە + + گەڕانەوە + + دڵنیابوونەوە + + ڕێگەبدە %1$s کە %2$s بکاتەوە + + ڕێگەپێدان + + ڕێگەنەدان + + ئایا تۆ دڵنیایت کە دەتەوێت %1$s بسڕیتەوە؟ + + + سڕینەوەی ئەم بازدەرە هەموو کۆکەرەوەکە دەسڕێتەوە. دەتوانیت کۆکەرەوەیەکی تر درووست بکەیت لە هەر کاتێکی تردا. + + %1$s دەسڕیتەوە؟ + + سڕینەوە + + پاشگەزبوونەوە + + چوونە دۆخی پراوپڕی شاشە + + بەستەر لەبەرگیرا + + ئەم دەقێکی نمونەییە. لێرە پیشان دەدرێت بۆ ئەوەی بزانی چۆن دەردەچێت کاتێک قەبارەی نووسدینەکە زیاد و کەم دەکەیت. + + وابکە دەقەکان لە ماڵپەڕەکان گەورەتر یان بچووکتر بن + + قەبارەی جۆرەپیت + + + قەبارەۆێدانی خۆکاری دەقەکان + + قەبارەی جۆرەپیت خۆی دەگونجێنێت لەگەڵ ڕێکخستنەکانی ئەندرۆید، ناکارای بکە بۆ ئەوەی خۆت ئەنجامی بدەیت. + + + سڕێنەوەی زانیاری گەڕان + + بازدەرەکان بکەرەوە + + %d بازدەر + + مێژووی گەڕان و زانیاری ماڵپەڕ + + %d ناونیشان + + مێژوو + + %d پەڕە + + شەکرۆکەکان + + تۆ دەچیتە دەرەوە لە زۆربەی ماڵپەڕەکان + + پەڕگە و وێنەی حەشاردراو + + بۆشایی بیرگە زیاتر دەکات + + ڕێگەپێدانەکانی ماڵپەڕ + + داگرتنەکان + + سڕینەوەی زانیاری گەڕان + + سڕێنەوەی زانیاری گەڕان دووای دەرچوون + + خۆکارانەوە زانیارییەکانی گەڕان دەسڕێتەوە کاتێک دەردەچیت لە پێڕستی سەرەکیەوە + + خۆکارانەوە زانیارییەکانی گەڕان دەسڕێتەوە کاتێک دەردەچیت لە پێڕستی سەرەکیەوە + + وازهێنان + + + ئەمە هەموو زانیارییەکانی گەڕانت دەسڕێتەوە + + %s زانیاری گەڕانی دیاریکراو دەسڕێتەوە. + + پاشگەزبوونەوە + + + سڕینەوە + + زانیاری گەڕان سڕایەوە + + سڕینەوەی زانیارییەکانی گەڕان... + + + + Firefox Preview ئێستا بووە بە Firefox Nightly + + فایەرفۆکسی بێتا بەدەست بێنە بۆ ئەندرۆید + + + فایەرفۆکسی شەوانەیی(nightly) لێرە گوازرایەوە + + بچۆ وەشانی نوێی شەوانەیی (Nightly) + + + فایەرفۆکسی شەوانەیی(nightly) لێرە گوازرایەوە + + شەوانەیی (Nightly) نوێ بەدەست بهێنە + + + + بەخێربێی بۆ %s! + + پێشتر هەژمارت هەبووە؟ + + بزانە چی نوێ هەیە + + پرسیارت هەیە دەربارەی نوێکردنەوەی ڕووکاری %s؟ دەتەوێت بزانیت چی گۆڕاوە؟ + + وەڵامەکان لێرە بەدەست بهێنە + + فایەرفۆکس هاوکاتگەری پێبکە لە نێوان ئامێرەکان + + نیشانکراوەکان، مێژووی کار، و وشەی تێپەڕەکان بهێنە بۆ ئەم ئامێرە. + + بەڵێ، بمکە ژوورەوە + + دەچیتە ژوورەوە... + + خۆتۆمارکردن + + بە دەرچووی بمێنەرەوە + + هاوکاتگەری کارایە + + نەتوانرا بچیتە ژوورەوە + + هەموو-کات لەسەر تایبەتیی + + فایەرفۆکس خۆکارانە کۆمپانیاکان ڕادەگرێت لەوەی چاودێریت بکەن لەسەر وێب. + + ئاسایی (بنەڕەتیی) + + + هاوتایی لەنێوان چوستی و تایبەتیی. پەڕەکان ئاسایی باردەکرێن. + + پتەو (پێشنیازکراو) + + پتەو + + چاودێریکەران بلۆک دەکات بۆ پەڕەکان زووتر باردەکرێن. بەڵام لەوانەیە هەندێ کرداری ناو ماڵپەڕەکان بوەستێت. + + شوێنی توڵامراز هەڵبژێرە + + توڵامراز بکەرە شوێنێک زوو دەستت پێیبگات، لە خوارەوە، یان بیخە سەرەوە. + + بگەڕێ بە تایبەتیی (شاراوەیی) + + یەکسەر بازدەرێکی تایبەت بکەرەوە: پەنجە بنێ بە وێنۆچکەی %s. + + بازدەری تایبەت هەموو کات بکەرەوە: ڕێکخستنەکانی گەڕانی تایبەتی نوێبکەرەوە. + + ڕێکخستنەکان بکەرەوە + + تایبەتێتی بکەرەوە + + ئێمە %s داڕشتووە بەشێوەیەک بتوانیت کۆنتڕۆڵی ئەوە بکەیت چی لەسەرهێڵ بڵاوبکەیتەوە یان چی لەگەڵ ئێمە بڵاوبکەیتەوە. + + تێبینییەکانی تایبەتێتی بخوێنەوە + + داخستن + + + دەستبکە بە گەڕان + + + + ڕووکار هەڵبژێرە + + هەندێک وزەی پاتری و چاوت بپارێزە لەڕێگەی دۆخی ڕووکاری تاریکەوە. + + خۆکار + + دەگونجێت بەپێی ڕێکخستنی ئامێرەکەت + + ڕووکاری تاریک + + ڕووکاری ڕوون + + + بازدەرەکان نێردران! + + بازدەر نێردرا! + + نەتوانرا بنێردرێت + + هەوڵ بدەرەوە + + کۆدەکە سکان بکە + + https://firefox.com/pair]]> + + ئامادەیە بۆ سکان + + بچۆ ژوورەوە لەرێگەی کامێراکەتەوە + + دەتوانیت پۆستی ئەلیکترۆنی بەکارببەیت + + + دانەیەک درووست بکە بۆ هاوکاتگەری پێکردن لەنێوان ئامێرەکان.]]> + + دەرچوون + + پاشگەزبوونەوە + + ناتوانرێت بوخچەی بنەڕەتی دەستکاریبکرێت + + + + ڕێکخستنەکانی پارێزگاری + + باشترکردنی پارێزگاری لە چاودێریکردن + + بگەڕێ بێئەوەی چاودێری بکرێیت + + زانیارییەکانت بپارێزە. %s دەتپارێزێت لە زۆرێک لەو پەیگرانەی کە شوێنپێت هەڵ دەگرن لە سەرهێڵ. + + زیاتر بزانە + + ئاسایی (بنەڕەتیی) + + هاوتایی لەنێوان چوستی و تایبەتیی. پەڕەکان ئاسایی باردەکرێن. + + چی بلۆک کراوە لە لایەن پارێزگاریکردن لە چاودێری ئاساییەوە + + پتەو + + چاودێریکەران بلۆک دەکات بۆ پەڕەکان زووتر باردەکرێن. بەڵام لەوانەیە هەندێ کرداری ناو ماڵپەڕەکان بوەستێت. + + چی بلۆک کراوە لە لایەن پارێزگاریکردن لە چاودێری پتەوەوە + + خوازراو + + دیاریبکە کام چاودێریکەر یان نووسە بلۆک بکرێت. + + چی بلۆک کراوە لا لەیەن پارێزگاریکردن لە چاودێری خوازراوەوە + + + شەکرۆکەکان + + چاودێریکەری ناو ماڵپەڕ و تۆڕی کۆمەڵایەتی + + شەکرۆکە لەو ماڵپەڕانەی کە سەردانت نەکردوون + + هەموو شەکرۆکەکانی لایەنی سێهەم (لەوانەیە ببێتە هۆی وەستانی ماڵپەڕەکان) + + هەموو شەکرۆکەکان ( لەوانەیە ببێتە هۆی وەستانی ماڵپەڕەکان) + + چاودێریکردنی ناوەڕۆک + + لە هەموو بازدەرەکان + + تەنها لە بازدەری تایبەت + + تەنها لە بازدەری دیاریکراو (خوازراو) + + شیفرە-کانەکەر + + پەنجەمۆرەکان + بلۆککراوە + + ڕێگەپێدراوە + + چاودێریکردنی تۆڕی کۆمەڵایەتی + + شیفرە-کانەکەر + + پەنجەمۆرەکان + + چاودێریکردنی ناوەڕۆک + + پاراستن کارایە بۆ ئەم ماڵپەڕە + + پاراستن ناکارایە بۆ ئەم ماڵپەڕە + + پاراستنی چاودێری پێشکەوتوو ناکارایە بۆ ئەم ماڵپەڕانە + + بچۆ دواوە + + مافەکانت + + ئەو سەرچاوە کراوانەی ئێمە بەکاریان دێنین + + چی نوێ هەیە لە %s + + %s | کتێبخانەی سەرچاوە کراوە + + + چاودێریکەر بنێرەوە + + + پشتگیری + + تێکشکانەکان + + سەرنجی تایبەتێتی + + مافەکانت بزانە + + زانیاری مۆڵەت + + ئەو سەرچاوانەی بەکاریدێنین + + + 1 بازدەر + + %d بازدەر + + + + لەبەرگرتنەوە + + لکاندن و ڕۆشتن + + لکاندن + + بەستەر لەبەرگیرا بۆ گرتەتەختە + + + زیادی بکە بۆ شاشەی سەرەکی + + پاشگەزبوونەوە + + زیادکردن + + بەردەوام بە بۆ ماڵپەڕەکە + + ناوی قەدبڕ + + + چوونەژوورەوە و وشەی تێپەڕەکان + + چوونەژوورەوە وشەی تێپەڕەکان پاشەکەوت بکە + + داوابکە بۆ پاشەکەوتکردن + + هەرگیز پاشەکەوت مەکە + + پڕکردنەوەی خۆکار + + چوونەژوورەوەکان هاوکاتگەری پێبکە + + چوونەژوورەوەکان هاوکاتگەری پێبکە لە نێوان ئامێرەکان + + پەیوەندی کردنەوە + + بچۆژوورەوە بۆ هاوکاتگەری + + چوونەژوورەوەی پاشەکەوتکراو + + ئەو چوونەژوورەوانەی پاشەکەوتی دەکەیت یان هاوکاتگەری پێدەکەیت لەگەڵ %s لێرە دەردەکەوێت. + + زیاتر بزانە دەربارەی هاوکاتگەری. + + هەڵاوێردییەکان + + + ئەو چوونەژوور و وشەی تێەپەڕانەی پاشەکەوتی ناکەیت لێرە دەردەکەوێت. + + چوونەژوورەوە و وشەی تێپەڕ پاشەکەوت ناکرێت بۆ ئەم ماڵپەڕانە. + + هەموو هەڵاوێردییەکان بسڕەوە + + بگەڕێ لە ناو چوونەژوورەوەکان + + شێوەی ئەلفوبێی + + دووا بەکارهێنراو + + ماڵپەڕ + + ناوی بەکارهێنەر + + وشەی تێپەڕبوون + + PIN لێبدەرەوە + + بیکەرەوە بۆ ئەوەی چوونەژوورەوەکان ببینی + + ئەم پەیوەندییە پارێزراو نیە. ئەو زانیاریانەی دەنووسیت لەوانەیە بڵاوەیپێبکرێت + + زیاتر بزانە + + دەتەوێت ئەم چوونەژوورەوەیە پاشەکەوت بکەیت؟ + + پاشەکەوتکردن + + پاشەکەوتی مەکە + + وشەی تێپەڕبوون لەبەرگیرایەوە + + ناوی بەکارهێنەر لەبەرگیرایەوە + + ماڵپەڕ لەبەرگیرایەوە + + وشەی تێپەڕبوون لەبەربگرەوە + + وشەی تێپەڕبوون پاکبکەرەوە + + ناوی بەکارهێنەر لەبەربگرەوە + + ناوی بەکارهێنەر پاکبکەرەوە + + ماڵپەڕ لەبەربگرەوە + + ماڵپەڕ لە وێبگەڕ بکەرەوە + + وشەی تێپەڕبوون پیشان بدە + + وشەی تێپەڕبوون بشارەوە + + بیکەرەوە بۆ ئەوەی چوونەژوورەوەکان ببینی + + چوونەژوورەوەکان و وشەی تێپەڕبوون بپارێزە + + دوواتر + + ئێستا بیکە + + ئامێرەکەت بکەرەوە + + هێنانە پێش لە هەموو ماڵپەڕەکان + + کارای بکە بۆ ئەوەی ڕێگە بدات نزیککردنەوە و دوورکردنەوە، لەکاتێکا ئەگەر ماڵپەڕەکەش رێگەت پێ نەدات. + + ناو(A-Z) + + کۆتا بەکارهێنراو + + پێڕستی چوونەژوورەوەکان ڕێکخبە + + + + کارتی پڕکردنەوەی بانکی + + هەڵیبگرە و کارتەکان خۆکار پڕبکەرەوە + + زانیارییەکان بە کۆدکراون + + هاوکاتگەری کردنی کارت لە نێوان ئامێرەکان + + هاوکاتگەری کارتەکان + + کارتی پڕکردنەوەی بانکی زیادبکە + + پاشەکەوتکردن + + پاشەکەوتکردن + + پاشگەزبوونەوە + + + بزوێنەری گەڕان زیادبکە + + بزوێنەری گەڕان دەستکاریبکە + + زیادکردن + + پاشەکەوتکردن + + دەستکاریکردن + + سڕینەوە + + + هی تر + + ناو + + زیاتر بزانە + + + وردەکاری بزوێنەری گەڕانی خوزراو + + بەستەری زیاتر بزانە + + + ناوی بزوێنەری گەڕان بنووسە + + گەڕان بە دووای وشەی “%s” پێشتر بوونی هەیە. + + دەقێکی گەڕان بنووسە + + دڵنیابە کە دەقی نووسراو دەگنوجێت لەگەڵ شێوازی نموونەکە + + هەڵە لە پەیوەندیکردن بە “%s” + + %s درووستکرا + + %s پاشەکەوتکرا + + %s سڕایەوە + + + بەخێر بێی بۆ %s نوێ + + نوێکردنەوە %s… + + دەستپێکردنی %s + + تێهەڵکێشکردن تەواو بوو + + وشەی تێپەڕبوونەکان + + + بۆ ڕێگەدا: + + 1. بڕۆ بۆ ڕێکسختنەکانی ئەندرۆید + + ڕێگەپێدانەکان]]> + + %1$s بجوڵێنە بۆ کاراکردن]]> + + + پەیوەندیگرتنی پارێزراو + + پەیوەندیگرتنێکی ناپارێزراو + + تۆ دڵنیایت لە لابردنی هەموو دەسەڵاتەکان لە هەموو ماڵپەڕەکان؟ + + تۆ دڵنیایت لە لابردنی هەموو دەسەڵاتەکان لەم ماڵپەڕە؟ + + تۆ دڵنیایت لە لابردنی ئەم دەسەڵاتە لەم ماڵپەڕە؟ + + هیچ ماڵپەڕێک بەدەر نەبێت + + گرنگترین وتارەکان + + ئایا تۆ دڵنیاییت کە دەتەوێت ئەم نیشانکراوە بسڕیتەوە؟ + + زیادی بکە ماڵپەڕە زۆر سەردانکراوەکان + + سەلمێنراوە لە لایەن: %1$s + + سڕینەوە + + دەستکاریکردن + + + تۆ دڵنیایت کە دەویت ئەم چوونەژوورەوەیە بسڕیتەوە؟ + + سڕینەوە + + هەڵبژاردەکانی چوونەژوورەوە + + گۆڕانکارییەکە پاشەکەوت بکە بۆ چوونەژوورەوە. + + گۆڕانکارییەکان پشتگوێبخە + + دەستکاریکردن + + وشەی تێپڕبوون داواکراوە + + گەڕانی دەنگی + + ئێستا قسە بکە + + + چوونەژوورەوە بەناوە پێستر بوونی هەیە + + + + ئامێریکی تر ببەستەوە + + تکایە دووبارە ڕێپێدان ئەنجام بدەرەوە + + تکایە هاوکاتگەری بازدەر پێبکە. + + هیچ بازدەرێکی کراوەت نیە لە ئامێرەکانی تری فایەرفۆکس. + + لیستەی بازدەرەکان پیشان بدە لە ئامێرەکانی ترەوە. + + بۆ هاوکاتکردن بچۆژوورەوە + + بازدەری کراوە نیە + + + باشە، تێگەیشتم + + زۆترین ماڵپەڕە سەردانکراوەکان پیشان بدە + + ناو + + ناوی زۆرترین ماڵپەڕی سەردانیکراو + + باشە + + پاشگەزبوونەوە + + + سڕینەوە + + + کرتە بکە بۆ زانیاری زیاتر + + + بچۆ سەرەوە + + + داخستن + + diff --git a/app/src/main/res/values-co/strings.xml b/app/src/main/res/values-co/strings.xml index 32445af8a..e7c78f7aa 100644 --- a/app/src/main/res/values-co/strings.xml +++ b/app/src/main/res/values-co/strings.xml @@ -5,6 +5,7 @@ %s privatu %s (nav. privata) + Ozzioni addiziunale @@ -49,6 +50,16 @@ Selezziunatu + + + Arregistrate pocu fà + + Indette arregistrate pocu fà + + Tuttu affissà + + Buttone Affissà tutte l’indette arregistrate + %1$s hè sviluppatu da Mozilla. @@ -96,14 +107,6 @@ Ricusà - - Mudificà l’accunciamentu di l’unghjette aperte. Andate in e preferenze è selezziunate « Quadrittere » sottu « Vista di l’unghjette ». - - - Andà à e preferenze - - Ignurà - Nova unghjetta @@ -114,6 +117,12 @@ Siti principale + + + Rivene in st’unghjetta + + Tuttu affissà + Unghjette aperte @@ -188,6 +197,10 @@ Mudificà + + + Screnu d’accolta + Impussibule di cunnettesi. Schema d’URL scunnisciutu. @@ -553,8 +566,6 @@ Nova unghjetta Circà in a pagina - - Unghjette sincrunizate Lista di lettura @@ -601,6 +612,15 @@ Dopu un mese + + + Principià da u screnu d’accolta + + Dopu quattru ore + + Sempre + + Mai Chjusura manuale @@ -1502,7 +1522,7 @@ Scrivite torna u vostru codice PIN - Ci vole à spalancà per affissà l’identificazioni di cunnessione arregistrate + Spalancate per affissà l’identificazioni di cunnessione arregistrate Sta cunnessione ùn hè micca assicurata. L’identificazioni di cunnessione scritti quì puderianu esse ingannati. @@ -1585,6 +1605,10 @@ Data di scadenza + + Mese di a data di scadenza + + Annu di a data di scadenza Nome di u titulare @@ -1605,6 +1629,24 @@ Ci vole à scrive un numeru accettevule di carta bancaria + + Ci vole à riempie stu campu + + Spalancate per affissà e vostre carte arregistrate + + + Prutege e vostre carte bancarie + + Definite un dissegnu di chjusura, un codice PIN o una parolla d’entrata per prutege e vostre carte arregistrate s’ellu ci era qualchissia chì accidissi à u vostru apparechju. + + Cunfigurà subitu + + Dopu + + Spalancate u vostru apparechju + + Spalancate per impiegà l’infurmazione di e carte bancarie arregistrate + Aghjunghje un mutore di ricerca diff --git a/app/src/main/res/values-cs/strings.xml b/app/src/main/res/values-cs/strings.xml index 33d4a557f..a17a819b6 100644 --- a/app/src/main/res/values-cs/strings.xml +++ b/app/src/main/res/values-cs/strings.xml @@ -5,6 +5,7 @@ Anonymní %s %s (anonymní) + Více možností @@ -49,6 +50,16 @@ Vybráno + + + Naposledy uložené + + Naposledy uložené záložky + + Zobrazit vše + + Tlačítko pro zobrazení všech uložených záložek + Autorem aplikace %1$s je Mozilla. @@ -94,13 +105,6 @@ Ne, děkuji - - Zobrazení otevřených panelů můžete změnit v nastavení aplikace. - - Přejít do nastavení - - Zavřít - Nový panel @@ -110,6 +114,12 @@ Top stránky + + + Návrat zpět + + Zobrazit vše + Otevřít panely @@ -187,6 +197,10 @@ Upravit + + + Domovská obrazovka + Nelze se připojit. Schéma URL nebylo rozpoznáno. @@ -555,8 +569,6 @@ Nový panel Najít na stránce - - Synchronizované panely Seznam ke čtení @@ -601,6 +613,15 @@ Po měsíci + + + Při spuštění zobrazit domovskou obrazovku + + Po pár hodinách od zavření + + Vždy + + Nikdy Zavírat ručně @@ -1589,6 +1610,10 @@ Číslo karty Datum platnosti + + Datum platnosti (měsíc) + + Datum platnosti (rok) Jméno na kartě @@ -1610,6 +1635,24 @@ Zadejte prosím platné číslo platební karty + + Vyplňte prosím toto pole + + Odemknout pro zobrazení uložených karet + + Zabezpečte své platební karty + + Nastavte si gesto, PIN nebo heslo zámku obrazovky, který ochrání vaše uložené platební karty, pokud by se vaše zařízení dostalo do ruky někomu jinému. + + Nastavit + + Později + + Odemkněte zařízení + + + Odemkněte pro použití informací o platební kartě + Přidat vyhledávač diff --git a/app/src/main/res/values-cy/strings.xml b/app/src/main/res/values-cy/strings.xml index 92cad6812..952393240 100644 --- a/app/src/main/res/values-cy/strings.xml +++ b/app/src/main/res/values-cy/strings.xml @@ -4,6 +4,7 @@ %s Preifat %s (Preifat) + Rhagor o opsiynau @@ -48,6 +49,16 @@ Dewiswyd + + + Cadwyd yn ddiweddar + + Nodau tudalen wedi’u cadw’n ddiweddar + + Dangos y cyfan + + Dangos fotwm nodau tudalen wedi’u cadw + Mae %1$s yn cael ei greu gan Mozilla. @@ -93,13 +104,6 @@ Cau - - Newid cynllun tabiau agored. Ewch i’r Gosodiadau a dewis grid o dan golwg tabiau. - - Mynd i’r Gosodiadau - - Cau - Tab newydd @@ -109,6 +113,12 @@ Hoff wefannau + + + Mynd nôl i + + Dangos y cyfan + Tabiau Agored @@ -183,6 +193,10 @@ Golygu + + + Sgrin cartref + Methu cysylltu. Cynllun URL anadnabyddadwy. @@ -545,8 +559,6 @@ Tab newydd Canfod yn y dudalen - - Tabiau wedi’u Cydweddu Rhestr Ddarllen @@ -591,6 +603,15 @@ Ar ôl un mis + + + Dechrau o gartref + + Ar ôl pedair awr + + Bob tro + + Byth Cau â llaw @@ -1569,6 +1590,10 @@ Fodd bynnag, gall fod yn llai sefydlog. Llwythwch ein porwr Beta i gael profiad Rhif y Cerdyn Dyddiad Dod i Ben + + Mis Dod i Ben + + Blwyddyn Dod i Ben Enw ar y Cerdyn @@ -1590,6 +1615,24 @@ Fodd bynnag, gall fod yn llai sefydlog. Llwythwch ein porwr Beta i gael profiad Rhowch rif cerdyn credyd dilys + + Llanwch y maes yma. + + Datgloi i weld y cardiau rydych wedi’u cadw + + Diogelwch eich cerdyn credyd + + Gosodwch batrwm cloi dyfais, PIN, neu gyfrinair i ddiogelu eich mewngofnodion a’ch cyfrineiriau sydd wedi’u cadw rhag i rhywun arall sydd â mynediad i’ch dyfais. + + Gosod nawr + + Yn hwyrach + + Datgloi’ch dyfais + + + Datglowch i ddefnyddio manylion cerdyn credyd wedi’i storio + Ychwanegu peiriant chwilio diff --git a/app/src/main/res/values-da/strings.xml b/app/src/main/res/values-da/strings.xml index 2edd89c05..546eabc46 100644 --- a/app/src/main/res/values-da/strings.xml +++ b/app/src/main/res/values-da/strings.xml @@ -410,6 +410,11 @@ and the third is the device model. --> %1$s på %2$s %3$s + + Betalingskort + + Adresser + Modtagne faneblade @@ -440,9 +445,6 @@ Læs mere - - Slået fra overalt. Gå til Indstillinger for at slå beskyttelse til. - Telemetry @@ -453,6 +455,8 @@ Markedsføringsdata Deler data om de funktioner, du bruger i %1$s, med Leanplum, vores samarbejdspartner inden for markedsføring. + + Deler grundlæggende data for anvendelse med Adjust, vores samarbejdspartner inden for markedsføring. Undersøgelser @@ -789,8 +793,6 @@ %1$s slettet Tilføj mappe - - Bogmærke oprettet. Bogmærke gemt! @@ -1441,10 +1443,8 @@ Autofyld Synkroniser logins - - Til - - Fra + + Synkroniser logins på tværs af enheder Genopret forbindelse @@ -1545,6 +1545,8 @@ Data er krypteret Synkroniser kort på tværs af enheder + + Synkroniser kort Tilføj betalingskort @@ -1575,6 +1577,24 @@ Gemte kort + + Indtast et gyldigt betalingskortnummer + + + Lås op for at se dine gemte betalingskort + + Beskyt dine betalingskort + + Indstil en pinkode, en adgangskode eller et låsemønster på din enhed for at forhindre, at andre mennesker får adgang til dine gemte betalingskort, hvis de har adgang til din enhed. + + Indstil nu + + Senere + + Lås din enhed op + + Lås op for at anvende gemte informationer om betalingskort + Tilføj søgetjeneste @@ -1738,20 +1758,13 @@ Fjern - - Få det meste ud af %s. - Tryk for at se flere detaljer - - Saml de ting, der betyder noget for dig - - Saml relaterede søgninger, websteder og faneblade i grupper. Så kan du hurtigt finde dem igen. - - Du er logget ind som %s i en anden version af Firefox på denne telefon. Vil du logge ind med denne konto? - - Du kan nemt føje dette websted til din telefons startskærm for at have hurtig adgang til det og browse hurtigere med en app-lignende oplevelse. + + Naviger op + + + Luk - + diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml index 6df4e993a..86d1df0a9 100644 --- a/app/src/main/res/values-de/strings.xml +++ b/app/src/main/res/values-de/strings.xml @@ -6,6 +6,7 @@ %s privat %s (privat) + Weitere Optionen @@ -50,6 +51,17 @@ Ausgewählt + + + Kürzlich gespeichert + + Kürzlich gespeicherte Lesezeichen + + Alle anzeigen + + + Schaltfläche: Alle gespeicherten Lesezeichen anzeigen + %1$s wird von Mozilla hergestellt. @@ -96,13 +108,6 @@ Schließen - - Ändern Sie das Layout offener Tabs. Öffnen Sie die Einstellungen und wählen Sie „Raster“ bei der Tab-Ansicht. - - Einstellungen öffnen - - Verwerfen - Neuer Tab @@ -112,6 +117,12 @@ Wichtige Seiten + + + Zurückspringen + + Alle anzeigen + Offene Tabs @@ -188,6 +199,10 @@ Bearbeiten + + + Startbildschirm + Verbindung nicht möglich. Nicht erkennbares URL-Schema. @@ -555,8 +570,6 @@ Neuer Tab In Seite suchen - - Synchronisierte Tabs Leseliste @@ -602,6 +615,15 @@ Nach einem Monat + + + Am Startbildschirm neu beginnen + + Nach vier Stunden + + Immer + + Nie Manuell schließen @@ -1602,6 +1624,10 @@ Kartennummer Ablaufdatum + + Monat des Ablaufdatums + + Jahr des Ablaufdatums Name auf Karte @@ -1623,6 +1649,24 @@ Bitte geben Sie eine gültige Kreditkartennummer ein + + Bitte füllen Sie dieses Feld aus + + Zum Anzeigen Ihrer gespeicherten Karten entsperren + + Sichern Sie Ihre Kreditkarten + + Richten Sie ein Gerätesperrmuster, eine PIN oder ein Passwort ein, um zu verhindern, dass auf Ihre gespeicherten Karten zugegriffen wird, wenn jemand anderes über Ihr Gerät verfügt. + + Jetzt einrichten + + Später + + Entsperren Sie Ihr Gerät + + + Entsperren, um gespeicherte Kreditkartendaten zu verwenden + Suchmaschine hinzufügen diff --git a/app/src/main/res/values-dsb/strings.xml b/app/src/main/res/values-dsb/strings.xml index 5bc928a5b..1b15e5f5a 100644 --- a/app/src/main/res/values-dsb/strings.xml +++ b/app/src/main/res/values-dsb/strings.xml @@ -4,6 +4,7 @@ Priwatny %s %s (priwatny) + Dalšne nastajenja @@ -47,6 +48,16 @@ Wubrany + + + Njedawno skłaźone + + Njedawno skłaźone cytańske znamjenja + + Wšykne pokazaś + + Tłocašk „Wšykne skłaźone cytańske znamjenja pokazaś“ + %1$s se pśez Mozilla zgótujo. @@ -93,13 +104,6 @@ Zachyśiś - - Wubjeŕśo wugótowanje za wócynjone rejtariki. Pśejźćo k nastajenjam a wubjeŕśo kśidno pód rejtarikowym naglědom. - - K nastajenjam - - Zachyśiś - Nowy rejtarik @@ -109,6 +113,12 @@ Nejcesćej woglědane sedła + + + Slědk skócyś + + Wšykne pokazaś + Wócynjone rejtariki @@ -183,6 +193,10 @@ Wobźěłaś + + + Startowa wobrazowka + Zwisk njejo móžny. Njespóznawajobna URL-šema. @@ -545,8 +559,6 @@ Nowy rejtarik Na boku pytaś - - Synchronizěrowane rejtariki Cytańska lisćina @@ -591,6 +603,15 @@ Pó jadnom mjasecu + + + Na startowej wobrazowce zachopiś + + Pó styrich góźinach + + Pśecej + + Nigda Manuelnje zacyniś @@ -1571,6 +1592,10 @@ Kórtowy numer Datum płaśiwosći + + Datum płaśiwosći (mjasec) + + Datum płaśiwosći (lěto) Mě na kórśe @@ -1592,6 +1617,24 @@ Pšosym zapódajśo płaśiwy numer kreditoweje kórty + + Pšosym wupołńśo toś to pólo + + Za zwobraznjowanje wašych skłaźonych kreditowych kórtow wótwóriś + + Kreditowe kórty zawěsćiś + + Nastajśo rědowy zastajeński muster, PIN abo gronidło, aby pśistupoju k swójim skłaźonym kreditowym kórtam zajźował, jolic něchten drugi ma waš rěd. + + Něnto konfigurěrowaś + + Pózdźej + + Wótwóŕśo swój rěd + + + Blokěrowanje wótpóraś, aby se skłaźone informacije kreditoweje kórty wužywali + Pytnicu pśidaś diff --git a/app/src/main/res/values-el/strings.xml b/app/src/main/res/values-el/strings.xml index c7411e2ef..96bebd936 100644 --- a/app/src/main/res/values-el/strings.xml +++ b/app/src/main/res/values-el/strings.xml @@ -5,6 +5,7 @@ Ιδιωτικό %s %s (Ιδιωτικό) + Περισσότερες επιλογές @@ -54,6 +55,17 @@ Επιλέχθηκε + + + Πρόσφατα αποθηκευμένα + + Πρόσφατα αποθηκευμένοι σελιδοδείκτες + + Εμφάνιση όλων + + + Κουμπί εμφάνισης όλων των αποθηκευμένων σελιδοδεικτών + Το %1$s αναπτύσσεται από τη Mozilla. @@ -98,13 +110,6 @@ Απόρριψη - - Αλλάξτε τη διάταξη των ανοικτών καρτελών. Μεταβείτε στις ρυθμίσεις και επιλέξτε "Πλέγμα" στο μενού προβολής καρτελών. - - Μετάβαση στις ρυθμίσεις - - Απόρριψη - Νέα καρτέλα @@ -114,6 +119,12 @@ Κορυφαίες σελίδες + + + Επιστροφή + + Εμφάνιση όλων + Ανοικτές καρτέλες @@ -189,6 +200,10 @@ Επεξεργασία + + + Αρχική οθόνη + Αδυναμία σύνδεσης. Μη αναγνωρίσιμο σχήμα URL. @@ -554,8 +569,6 @@ Νέα καρτέλα Εύρεση στη σελίδα - - Συγχρονισμένες καρτέλες Λίστα ανάγνωσης @@ -602,6 +615,15 @@ Μετά από ένα μήνα + + + Εκκίνηση στην αρχική οθόνη + + Μετά από τέσσερις ώρες + + Πάντα + + Ποτέ Χειροκίνητο κλείσιμο @@ -1506,7 +1528,7 @@ Κωδικός πρόσβασης - Εισάγετε ξανά το PIN σας + Εισαγάγετε ξανά το PIN σας Ξεκλειδώστε για να δείτε τις αποθηκευμένες συνδέσεις σας @@ -1589,6 +1611,10 @@ Αριθμός κάρτας Ημερομηνία λήξης + + Μήνας ημερομηνίας λήξης + + Έτος ημερομηνίας λήξης Όνομα στην κάρτα @@ -1610,6 +1636,24 @@ Παρακαλώ εισαγάγετε έναν έγκυρο αριθμό πιστωτικής κάρτας + + Παρακαλώ συμπληρώστε αυτό το πεδίο + + Ξεκλειδώστε για να δείτε τις αποθηκευμένες κάρτες σας + + Ασφαλίστε τις πιστωτικές κάρτες σας + + Ορίστε ένα μοτίβο κλειδώματος συσκευής, ένα ΡΙΝ ή έναν κωδικό πρόσβασης για την προστασία των αποθηκευμένων πιστωτικών καρτών σας, σε περίπτωση που κάποιος τρίτος αποκτήσει πρόσβαση στη συσκευή σας. + + Ρύθμιση τώρα + + Αργότερα + + + Ξεκλειδώστε τη συσκευή σας + + Ξεκλειδώστε για χρήση των στοιχείων πιστωτικής κάρτας + Προσθήκη μηχανής αναζήτησης diff --git a/app/src/main/res/values-en-rCA/strings.xml b/app/src/main/res/values-en-rCA/strings.xml index 2b61a8116..76ac2be03 100644 --- a/app/src/main/res/values-en-rCA/strings.xml +++ b/app/src/main/res/values-en-rCA/strings.xml @@ -4,6 +4,7 @@ Private %s %s (Private) + More options @@ -48,6 +49,16 @@ Selected + + + Recently saved + + Recently saved bookmarks + + Show all + + Show all saved bookmarks button + %1$s is produced by Mozilla. @@ -93,13 +104,6 @@ Dismiss - - Change the layout of open tabs. Go to settings and select grid under tab view. - - Go to settings - - Dismiss - New tab @@ -109,6 +113,12 @@ Top sites + + + Jump back in + + Show all + Open Tabs @@ -183,6 +193,10 @@ Edit + + + Home screen + Unable to connect. Unrecognizable URL scheme. @@ -542,8 +556,6 @@ New tab Find in page - - Synced tabs Reading List @@ -588,6 +600,15 @@ After one month + + + Start on home + + After four hours + + Always + + Never Close manually @@ -1557,6 +1578,10 @@ Card Number Expiration Date + + Expiration Date Month + + Expiration Date Year Name on Card @@ -1578,6 +1603,23 @@ Please enter a valid credit card number + + Please fill out this field + + Unlock to view your saved cards + + Secure your credit cards + + Set up a device lock pattern, PIN, or password to protect your saved credit cards from being accessed if someone else has your device. + + Set up now + + Later + + Unlock your device + + Unlock to use stored credit card information + Add search engine diff --git a/app/src/main/res/values-en-rGB/strings.xml b/app/src/main/res/values-en-rGB/strings.xml index ae6b39c13..2b78ff49f 100644 --- a/app/src/main/res/values-en-rGB/strings.xml +++ b/app/src/main/res/values-en-rGB/strings.xml @@ -4,6 +4,7 @@ Private %s %s (Private) + More options @@ -47,6 +48,16 @@ Selected + + + Recently saved + + Recently saved bookmarks + + Show all + + Show all saved bookmarks button + %1$s is produced by Mozilla. @@ -92,13 +103,6 @@ Dismiss - - Change the layout of open tabs. Go to settings and select grid under tab view. - - Go to settings - - Dismiss - New tab @@ -108,6 +112,12 @@ Top sites + + + Jump back in + + Show all + Open Tabs @@ -182,6 +192,10 @@ Edit + + + Home screen + Unable to connect. Unrecognisable URL scheme. @@ -542,8 +556,6 @@ New tab Find in page - - Synchronised tabs Reading List @@ -589,6 +601,15 @@ After one month + + + Start on home + + After four hours + + Always + + Never Close manually @@ -1560,6 +1581,10 @@ Card Number Expiration Date + + Expiration Date Month + + Expiration Date Year Name on Card @@ -1581,6 +1606,23 @@ Please enter a valid credit card number + + Please fill out this field + + Unlock to view your saved cards + + Secure your credit cards + + Set up a device lock pattern, PIN, or password to protect your saved credit cards from being accessed if someone else has your device. + + Set up now + + Later + + Unlock your device + + Unlock to use stored credit card information + Add search engine diff --git a/app/src/main/res/values-es-rAR/strings.xml b/app/src/main/res/values-es-rAR/strings.xml index f212f8ea5..45f20cc44 100644 --- a/app/src/main/res/values-es-rAR/strings.xml +++ b/app/src/main/res/values-es-rAR/strings.xml @@ -5,6 +5,7 @@ %s privado %s (Privado) + Más opciones @@ -48,6 +49,16 @@ Seleccionadas + + + Guardados recientemente + + Marcadores guardados recientemente + + Mostrar todos + + Mostrar todos los marcadores guardados + %1$s es producido por Mozilla. @@ -94,13 +105,6 @@ Descartar - - Cambiar el diseño de las pestañas abiertas. Ir a Ajustes y seleccionar cuadrícula bajo la sección de vista de pestañas. - - Ir a Ajustes - - Descartar - Nueva pestaña @@ -110,6 +114,12 @@ Sitios importantes + + + Volver a ver + + Mostrar todas + Abrir pestañas @@ -186,6 +196,10 @@ Editar + + + Pantalla de inicio + No se puede conectar. Esquema de URL irreconocible. @@ -558,8 +572,6 @@ Nueva pestaña Buscar en la página - - Pestañas sincronizadas Lista de lectura @@ -605,6 +617,15 @@ Después de un mes + + + Arrancar en inicio + + Después de cuatro horas + + Siempre + + Nunca Cerrar manualmente @@ -1589,6 +1610,10 @@ Número de tarjeta Fecha de vencimiento + + Mes de fecha de vencimiento + + Año de fecha de vencimiento Nombre en la tarjeta @@ -1610,6 +1635,25 @@ Ingresá un número de tarjeta de crédito válido + + Se debe completar este campo + + Desbloqueá para ver los inicios de sesión guardados + + Asegurá tus tarjetas de crédito + + + Configurá un patrón de bloqueo del dispositivo, PIN o contraseña para proteger el acceso a tus tarjetas de crédito guardadas si alguien más tiene tu dispositivo. + + Configurar ahora + + Más tarde + + Desbloqueá tu dispositivo + + + Desbloquear para usar la información almacenada de la tarjeta de crédito + Agregar buscador diff --git a/app/src/main/res/values-es-rCL/strings.xml b/app/src/main/res/values-es-rCL/strings.xml index e95a4a3cf..3a125a846 100644 --- a/app/src/main/res/values-es-rCL/strings.xml +++ b/app/src/main/res/values-es-rCL/strings.xml @@ -4,6 +4,7 @@ %s en modo privado %s (Private) + Más opciones @@ -47,6 +48,16 @@ Seleccionadas + + + Guardados recientemente + + Marcadores guardados recientemente + + Mostrar todo + + Botón para mostrar todos los marcadores guardados + %1$s es producido por Mozilla. @@ -92,13 +103,6 @@ Ocultar - - Cambia el diseño de las pestañas abiertas. Ve a Ajustes y selecciona cuadrícula bajo la sección de vista de pestañas. - - Ir a ajustes - - Ignorar - Nueva pestaña @@ -108,6 +112,12 @@ Sitios frecuentes + + + Regresar a + + Mostrar todo + Pestañas abiertas @@ -182,6 +192,10 @@ Editar + + + Pantalla de inicio + No se puede conectar. Esquema de URL irreconocible. @@ -544,8 +558,6 @@ Nueva pestaña Buscar en la página - - Pestañas sincronizadas Lista de lectura @@ -590,6 +602,15 @@ Después de un mes + + + Empezar en la pantalla de inicio + + Tras cuatro horas + + Siempre + + Nunca Cerrar manualmente @@ -1567,6 +1588,10 @@ Número de tarjeta Fecha de expiración + + Mes de expiración + + Año de expiración Nombre en la tarjeta @@ -1588,6 +1613,23 @@ Por favor, ingresa un número de tarjeta de crédito válido + + Complete este campo + + Desbloquea para ver tus tarjetas guardadas + + Asegura tus tarjetas de crédito + + Configura un patrón de bloqueo de dispositivo, PIN o contraseña para proteger tus tarjetas de crédito guardadas, y así no sean accedidas si alguien más tiene tu dispositivo. + + Configurar ahora + + Más tarde + + Desbloquea tu dispositivo + + Desbloquea para usar información de la tarjeta de crédito almacenada + Añadir motor de búsqueda diff --git a/app/src/main/res/values-es-rES/strings.xml b/app/src/main/res/values-es-rES/strings.xml index 3932e3c3f..973f80204 100644 --- a/app/src/main/res/values-es-rES/strings.xml +++ b/app/src/main/res/values-es-rES/strings.xml @@ -6,6 +6,7 @@ %s privado %s (Privado) + Más opciones @@ -51,6 +52,17 @@ Seleccionada + + + Guardado recientemente + + Marcadores guardados recientemente + + Mostrar todos + + + Mostrar todos los marcadores guardados + %1$s es producido por Mozilla. @@ -95,13 +107,6 @@ Descartar - - Cambia la disposición de las pestañas abiertas. Ve a ajustes y selecciona cuadrícula en el menú de vista de pestañas. - - Ir a ajustes - - Descartar - Nueva pestaña @@ -111,6 +116,12 @@ Sitios favoritos + + + Volver a esta pestaña + + Mostrar todas + Pestañas abiertas @@ -187,6 +198,10 @@ Editar + + + Pantalla de inicio + No se puede conectar. Esquema de URL irreconocible. @@ -556,8 +571,6 @@ Nueva pestaña Buscar en la página - - Pestañas sincronizadas Lista de lectura @@ -602,6 +615,15 @@ Después de un mes + + + Empezar desde el inicio + + Tras cuatro horas + + Siempre + + Nunca Cerrar manualmente @@ -1606,6 +1628,10 @@ Número de tarjeta Fecha de caducidad + + Mes de caducidad + + Año de caducidad Nombre en la tarjeta @@ -1627,6 +1653,23 @@ Por favor, escriba un número válido de tarjeta de crédito + + Por favor, rellena este campo + + Desbloquear para ver tus tarjetas guardadas + + Asegurar tus tarjetas de crédito + + Configura un patrón de bloqueo, PIN o contraseña para proteger el acceso a tus tarjetas guardadas si alguien más accede a tu dispositivo. + + Configurar ahora + + Más tarde + + Desbloquear tu dispositivo + + Desbloquear para usar la información de la tarjeta de crédito almacenada + Añadir buscador diff --git a/app/src/main/res/values-es-rMX/strings.xml b/app/src/main/res/values-es-rMX/strings.xml index e7e21b488..32521c407 100644 --- a/app/src/main/res/values-es-rMX/strings.xml +++ b/app/src/main/res/values-es-rMX/strings.xml @@ -4,6 +4,7 @@ %s en modo privado %s (Privado) + Más opciones @@ -47,6 +48,16 @@ Seleccionadas + + + Guardado recientemente + + Marcadores recién guardados + + Mostrar todo + + Mostrar todos los marcadores guardados + %1$s es producido por Mozilla. @@ -90,13 +101,6 @@ Descartar - - Cambia el diseño de las pestañas abiertas. Ve a Ajustes y selecciona cuadrícula bajo vista de pestañas. - - Ir a ajustes - - Ignorar - Nueva pestaña @@ -106,6 +110,12 @@ Sitios frecuentes + + + Saltar hacia atrás + + Mostrar todo + Abrir pestañas @@ -182,6 +192,10 @@ Editar + + + Pantalla de inicio + No se puede conectar. Esquema de URL irreconocible. @@ -544,8 +558,6 @@ Nueva pestaña Buscar en la página - - Pestañas sincronizadas Lista de lectura @@ -590,6 +602,15 @@ Después de un mes + + + Comenzar en la página de inicio + + Después de cuatro horas + + Siempre + + Nunca Cerrar manualmente @@ -1566,6 +1587,10 @@ Número de tarjeta Fecha de caducidad + + Mes de la fecha de vencimiento + + Año de la fecha de vencimiento Nombre en la tarjeta @@ -1585,6 +1610,24 @@ Favor de ingresar un número de tarjeta de crédito válido + + Por favor, lleva este campo + + Desbloquear para ver tus tarjetas guardadas + + Asegurar tus tarjetas de crédito + + Configura un patrón de bloqueo de dispositivo, PIN o contraseña para proteger el acceso a tus tarjetas guardadas si alguien más tiene tu dispositivo. + + Configurar ahora + + Más tarde + + Desbloquear tu dispositivo + + + Desbloquear para usar la información almacenada de la tarjeta de crédito + Agregar motor de búsqueda diff --git a/app/src/main/res/values-es/strings.xml b/app/src/main/res/values-es/strings.xml index 3c3cdaae9..8d77d09fa 100644 --- a/app/src/main/res/values-es/strings.xml +++ b/app/src/main/res/values-es/strings.xml @@ -6,6 +6,7 @@ %s privado %s (Privado) + Más opciones @@ -52,6 +53,16 @@ Seleccionado + + + Guardados recientemente + + Marcadores guardados recientemente + + Mostrar todos + + Mostrar todos los marcadores guardados + %1$s es producido por Mozilla. @@ -99,13 +110,6 @@ Descartar - - Cambia el diseño de las pestañas abiertas. Ve a Ajustes y selecciona cuadrícula bajo vista de pestañas. - - Ir a ajustes - - Ignorar - Nueva pestaña @@ -115,6 +119,12 @@ Sitios destacados + + + Volver a ver + + Mostrar todas + Pestañas abiertas @@ -190,6 +200,10 @@ Editar + + + Pantalla de inicio + No se puede conectar. Esquema de URL irreconocible. @@ -545,7 +559,7 @@ Marcadores de escritorio - Menú Marcadores + Menú de marcadores Barra de herramientas de marcadores @@ -556,8 +570,6 @@ Nueva pestaña Buscar en la página - - Pestañas sincronizadas Lista de lectura @@ -580,7 +592,7 @@ %d is a placeholder for the number of tabs selected. --> %d pestaña - No hay pestañas recientemente cerradas + No hay pestañas recientemente cerradas aquí @@ -602,6 +614,15 @@ Después de un mes + + + Empezar en la pantalla de inicio + + Después de cuatro horas + + Siempre + + Nunca Cerrar manualmente @@ -734,7 +755,7 @@ Eliminar - Se seleccionó %1$d + %1$d seleccionados Eliminar %1$d elementos @@ -805,7 +826,7 @@ Seleccionar carpeta - ¿Seguro que quieres eliminar esta carpeta? + ¿Estás seguro de que quieres eliminar esta carpeta? %s eliminará los elementos seleccionados. @@ -835,7 +856,7 @@ Guardar - Se seleccionó %1$d + %1$d seleccionados Editar marcador @@ -1604,7 +1625,11 @@ Número de tarjeta - Fecha de caducidad + Fecha de expiración + + Mes de expiración + + Año de expiración Nombre en la tarjeta @@ -1624,6 +1649,24 @@ Por favor, ingresa un número de tarjeta de crédito válido + + Por favor completa este campo + + Desbloquea para ver tus tarjetas guardadas + + Asegura tus tarjetas de crédito + + Configura un patrón de bloqueo, PIN o contraseña para proteger el acceso a tus tarjetas guardadas si alguien más accede a tu dispositivo. + + Configurar ahora + + Más tarde + + Desbloquea tu dispositivo + + + Desbloquea para usar la información de la tarjeta de crédito almacenada + Agregar motor de búsqueda diff --git a/app/src/main/res/values-fa/strings.xml b/app/src/main/res/values-fa/strings.xml index 0f0419aa4..c957954db 100644 --- a/app/src/main/res/values-fa/strings.xml +++ b/app/src/main/res/values-fa/strings.xml @@ -174,6 +174,8 @@ ظاهر + + سفارشی‌سازی نمای مطالعه افزودن @@ -226,7 +228,7 @@ جست‌وجو - جست در جو اینترنت + جست‌وجو در وب جستجوی صوتی @@ -407,6 +409,11 @@ and the third is the device model. --> %1$s روی %2$s %3$s + + کارت‌های اعتباری + + آدرس‌ها + زبانه‌های دریافت شده @@ -447,6 +454,8 @@ ارزیابی داده به اشتراک‌ گذاری داده‌هایی در خصوص ویژیگی که شما در %1$s با Leanplum تیم فروش موبایل ما. + + داده‌های کاربردی اولیه را با Adjust، فراهم‌کنندهٔ بازریابی سیستم موبایل ما، اشتراک بگذارید مطالعات @@ -613,6 +622,8 @@ به اشتراک‌گذار همه‌ی زبانه‌ها زبانه‌های تازه بسته شده + + تنظیمات حساب تنظیمات سربرگ @@ -967,6 +978,8 @@ همه عمل‌ها به تازگی استفاده شده + + برای همگام‌سازی وارد شوید برای همگام‌سازی وارد شوید @@ -1165,6 +1178,10 @@ در مورد طراحی مجدد %s سؤالی دارید؟ آیا می خواهید بدانید چه چیزی تغییر کرده است؟ پاسخ را از اینجا دریافت کنید + + همگام‌سازی Firefox بین دستگاه‌ها + + نشانک‌ها، تاریخچه و گذرواژه‌های خود را به Firefox در این دستگاه بیاورید. @@ -1181,13 +1198,25 @@ همگام سازی روشن است ورود شکست خورد + + همیشه در حال حفاظت از حریم‌خصوصی + + Firefox به طور خودکار شرکت‌ها را از پیگیری مخفیانهٔ شما در وب دور می‌کند. استاندارد (پیش فرض) + + تعادل بین کارآیی و حریم‌خصوصی. بارگیری صفحات با سرعتی عادی. سختگیرانه (توصیه می‌شود) شدید + + مسدودسازی ردیاب‌های بیشتر، اما برخی امکانات داخل صفحات ممکن است از کار بیافتند. + + محل قرارگیری نوار ابزار خود را انتخاب کنید + + نوار ابزار را در دسترس قرار دهید. آن را پایین نگه دارید، یا به بالا انتقال دهید. مرور ناشناس انتخاب زمینه + + با حالت تاریک، کمی باتری ذخیره کنید و از چشمان خود محافظت کنید. خودکار @@ -1267,10 +1298,14 @@ بیشتر بدانید استاندارد (پیش فرض) + + تعادل بین کارآیی و حریم‌خصوصی. بارگیری صفحات با سرعتی عادی. آنچه توسط حفاظت ردیابی استاندارد مسدود شده است سخت گیرانه + + مسدودسازی ردیاب‌های بیشتر، اما برخی امکانات داخل صفحات ممکن است از کار بیافتند. آنچه توسط حفاظت ردیابی سخت‌گیرانه مسدود شده است @@ -1411,6 +1446,8 @@ تکمیل خودکار همگام‌سازی ورود‌ها + + همگام‌سازی اطلاعات ورودها بین دستگاه‌ها اتصال مجدد @@ -1503,6 +1540,37 @@ مرتب سازی بر روی فهرست ورود + + + کارت‌های اعتباری + + ذخیره و پُرکردن خودکار کارت‌ها + + داده‌ها رمزنگاری شده‌اند + + همگام‌سازی کارت‌ها بین دستگاه‌ها + + همگام‌سازی کارت‌ها + + اضافه کردن کارت اعتباری + + مدیریت کارت‌های ذخیره شده + + اضافه کردن کارت + + ویرایش کارت + + شمارهٔ کارت + + تاریخ انقضا + + نام روی کارت + + نام مستعار کارت + + حذف کارت + + حذف کارت ذخیره @@ -1510,6 +1578,26 @@ انصراف + + کارت‌های ذخیره شده + + + لطفا یک شمارهٔ کارت اعتباری معتبر وارد کنید + + برای مشاهدهٔ کارت‌های اعتباری، قفل را باز کنید + + کارت‌های اعتباری خود را ایمن کنید + + در صورت دسترسی شخص دیگری از دستگاه شما، یک الگوی قفل دستگاه، PIN یا گذرواژه تنظیم کنید تا از اطلاعات کارت‌های اعتباری ذخیره شدهٔ خود محافظت کنید. + + راه‌اندازی + + بعدا + + باز کردن قفل دستگاه + + برای استفاده از اطلاعات کارت اعتباری ذخیره شده، قفل را باز کنید + افزودن موتور جست‌وجو @@ -1668,10 +1756,19 @@ انصراف + + پیوندهای وب سایت‌ها، ایمیل‌ها و پیام‌ها را تنظیم کنید تا به طور خودکار در Firefox باز شوند. + حذف برای جزئیات بیشتر کلیک کنید - + + پیمایش به بالا + + + بستن + + diff --git a/app/src/main/res/values-fi/strings.xml b/app/src/main/res/values-fi/strings.xml index 360d9d33e..bedaca5b5 100644 --- a/app/src/main/res/values-fi/strings.xml +++ b/app/src/main/res/values-fi/strings.xml @@ -5,6 +5,7 @@ Yksityinen %s %s (Yksityinen) + Lisää valintoja @@ -49,6 +50,16 @@ Valittu + + + Äskettäin tallennettu + + Äskettäin tallennetut kirjanmerkit + + Näytä kaikki + + Näytä kaikki tallennetut kirjanmerkit -painike + %1$s on Mozillan tuote. @@ -94,13 +105,6 @@ Hylkää - - Muuta avoimien välilehtien asettelua. Siirry asetuksiin ja valitse ruudukko välilehtinäkymästä. - - Siirry asetuksiin - - Hylkää - Uusi välilehti @@ -110,6 +114,12 @@ Ykkössivustot + + + Palaa takaisin + + Näytä kaikki + Avoimet välilehdet @@ -187,6 +197,10 @@ Muokkaa + + + Aloitusnäkymä + Yhteyden muodostaminen epäonnistui. URL-skeeman tunnistaminen ei onnistu. @@ -554,8 +568,6 @@ Uusi välilehti Etsi sivulta - - Synkronoidut välilehdet Lukulista @@ -601,6 +613,15 @@ Yhden kuukauden jälkeen + + + Käynnistä aloitusnäkymästä + + Neljän tunnin jälkeen + + Aina + + Ei koskaan Sulje manuaalisesti @@ -1586,6 +1607,10 @@ Kortin numero Vanhenemispäivä + + Vanhenemispäivän kuukausi + + Vanhenemispäivän vuosi Nimi kortissa @@ -1607,6 +1632,24 @@ Kirjoita kelvollinen luottokortin numero + + Täytä tämä kenttä + + Avaa lukitus nähdäksesi tallennetut kortit + + Suojaa luottokorttisi + + Aseta laitteen avaukseen tarkoitettu kuvio, PIN-koodi tai salasana suojataksesi tallennetut luottokorttitiedot siltä varalta, että joku saa laitteesi haltuunsa. + + Aseta nyt + + Myöhemmin + + Avaa laitteen lukitus + + + Avaa lukitus käyttääksesi tallennettuja luottokorttitietoja + Lisää hakukone diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml index 45f995d73..d3a55ab76 100644 --- a/app/src/main/res/values-fr/strings.xml +++ b/app/src/main/res/values-fr/strings.xml @@ -6,6 +6,7 @@ %s privé %s (nav. privée) + Plus d’options @@ -50,6 +51,16 @@ Sélectionné + + + Récemment enregistrés + + Marque-pages récemment enregistrés + + Tout afficher + + Bouton Afficher tous les marque-pages enregistrés + %1$s est réalisé par Mozilla. @@ -94,13 +105,6 @@ Ignorer - - Modifiez la disposition des onglets ouverts. Allez dans les paramètres et sélectionnez « Grille » sous « Affichage des onglets ». - - Ouvrir les paramètres - - Ignorer - Nouvel onglet @@ -110,6 +114,12 @@ Sites principaux + + + Revenir dans cet onglet + + Tout afficher + Onglets ouverts @@ -186,6 +196,10 @@ Modifier + + + Écran d’accueil + Impossible de se connecter. Schéma d’URL inconnu. @@ -417,6 +431,11 @@ and the third is the device model. --> %1$s sur %2$s %3$s + + Cartes bancaires + + Adresses + Onglets reçus @@ -550,8 +569,6 @@ Nouvel onglet Rechercher dans la page - - Onglets synchronisés Liste de lecture @@ -596,6 +613,15 @@ Après un mois + + + Démarrer par l’écran d’accueil + + Après quatre heures + + Toujours + + Jamais Fermeture manuelle @@ -1598,6 +1624,10 @@ Cependant, il peut être moins stable. Téléchargez la version bêta de notre n Numéro de carte Date d’expiration + + Mois d’expiration + + Année d’expiration Nom du titulaire @@ -1619,6 +1649,23 @@ Cependant, il peut être moins stable. Téléchargez la version bêta de notre n Veuillez saisir un numéro de carte bancaire valide + + Veuillez compléter ce champ + + Déverrouillez pour afficher vos cartes enregistrées + + Protégez vos cartes bancaires + + Configurez un schéma de verrouillage, un code PIN ou un mot de passe pour protéger vos cartes bancaires enregistrées si jamais quelqu’un accède à votre appareil. + + Configurer maintenant + + Plus tard + + Déverrouillez votre appareil + + Déverrouillez pour utiliser les informations de cartes bancaires enregistrées + Ajouter un moteur de recherche @@ -1786,4 +1833,10 @@ Cependant, il peut être moins stable. Téléchargez la version bêta de notre n Cliquez pour plus de précisions - + + Remonter + + + Fermer + + diff --git a/app/src/main/res/values-fy-rNL/strings.xml b/app/src/main/res/values-fy-rNL/strings.xml index 4d1d621ec..6ffa03cc8 100644 --- a/app/src/main/res/values-fy-rNL/strings.xml +++ b/app/src/main/res/values-fy-rNL/strings.xml @@ -4,6 +4,7 @@ Privee %s %s (Privee) + Mear opsjes @@ -48,6 +49,16 @@ Selektearre + + + Koartlyn bewarre + + Resint bewarre blêdwizers + + Alles toane + + Knop Alle bewarre blêdwizers toane + %1$s is makke troch Mozilla. @@ -95,13 +106,6 @@ Slute - - Wizigje de opmaak fan iepen ljepblêden. Gean nei Ynstellingen en selektearje ûnder Ljepblêdwerjefte ‘Raster’. - - Nei Ynstellingen - - Slute - Nij ljepblêd @@ -111,6 +115,12 @@ Topwebsites + + + Tebekspringe + + Alles toane + Iepen ljepblêden @@ -186,6 +196,10 @@ Bewurkje + + + Startskerm + Net yn steat te ferbinen. Unkenbere URL-skema. @@ -547,8 +561,6 @@ Nij ljepblêd Sykje op side - - Syngronisearre ljepblêden Lêslist @@ -593,6 +605,15 @@ Nei ien moanne + + + Op startskerm begjinne + + Nei fjouwer oer + + Altyd + + Nea Hânmjittich slute @@ -1570,6 +1591,10 @@ Kaartnûmer Ferrindatum + + Ferrindatum – moanne + + Ferrindatum – jier Namme op kaart @@ -1591,6 +1616,25 @@ Fier in jildich creditkaartnûmer yn + + Folje dit fjild yn + + Untskoattelje om jo bewarre kaarten te besjen + + Befeiligje jo creditcards + + Stel in beskoattelingspatroan, pinkoade of wachtwurd foar jo apparaat yn om jo bewarre creditcards te beskermjen tsjin tagong as in oar jo apparaat hat. + + + No ynstelle + + Letter + + Untskoattelje jo apparaat + + + Untskoattelje om bewarre creditkaartynformaasje te brûken + Sykmasine tafoegje diff --git a/app/src/main/res/values-gn/strings.xml b/app/src/main/res/values-gn/strings.xml index 5960304b5..f99359bc7 100644 --- a/app/src/main/res/values-gn/strings.xml +++ b/app/src/main/res/values-gn/strings.xml @@ -5,6 +5,7 @@ Ñemigua %s %s (Ñemigua) + Jeporavorãve @@ -49,6 +50,16 @@ Poravopyre + + + Oñeñongaturamóva + + Techaukaha oñeñongaturamóva + + Techaukapaite + + Ehechauka opaite techaukaha ñongatupyre + %1$s ojapókuri Mozilla. @@ -95,13 +106,6 @@ Mboyke - - Emoambue tendayke ijurujáva oĩha. Eho moĩporãhápe ha eiporavo kora’ieta tendyke rechaha poravorãme. - - Eho ñembohekópe - - Mboyke - Tendayke pyahu @@ -111,6 +115,12 @@ Tenda jehayhuvéva + + + Epo tapykue gotyo + + Techaukapaite + Embojuruja tendayke @@ -187,6 +197,10 @@ Mbosako’i + + + Mba’erechaha ñepyrũgua + Ndaikatúi eike. URL reko ojekuaa’ỹva. @@ -419,6 +433,11 @@ and the third is the device model. --> %1$s %2$s %3$s-pe + + Kuatia’atã ñemurã + + Kundaharape + Tendayke g̃uahẽmbyre @@ -548,8 +567,6 @@ Tendayke pyahu Eheka kuatiaroguépe - - Tendayke mbojuehepyre Moñe’ẽrã rysýi @@ -595,6 +612,15 @@ Peteĩ jasy rire + + + Eñepyrũ yvyetégui + + Irundy aravo rire + + Tapiaite + + Araka’eve Emboty nde pópe @@ -1595,6 +1621,10 @@ Kuatia’atã papy Arange opaha + + Jasýma opahague + + Arýma opahague Kuatia’atã réra @@ -1616,6 +1646,24 @@ Ikatúpiko ehai kuatia’atã ñemurã papapy oikóva + + Ikatúpiko emyenyhẽ ko kora + + Embojuruja ehecha hag̃ua kuatia’atã ñongatupyre + + Emohekorosã nde kuatia’atã ñemurã + + Emboheko peteĩ jekokoha rape, PIN térã ñe’ẽñemi emo’ã hag̃ua nde kuatia’atã ñongatupyre ambue oikeséramo ne mba’e’okápe. + + Emboheko ko’ág̃a + + Upéi + + Embojuruja ne mba’e’oka + + + Embojuruja eipuru hag̃ua kuatia’atã ñemurã marandu mbyatypyre + Embojuaju hekaha @@ -1786,4 +1834,10 @@ Eikutu ápe eikuaave hag̃ua - + + Eikundaha yvate gotyo + + + Mboty + + diff --git a/app/src/main/res/values-hr/strings.xml b/app/src/main/res/values-hr/strings.xml index db9d819ff..41f98c6af 100644 --- a/app/src/main/res/values-hr/strings.xml +++ b/app/src/main/res/values-hr/strings.xml @@ -5,6 +5,7 @@ Privatni %s %s (privatno) + Više opcija @@ -49,6 +50,16 @@ Odabrano + + + Nedavno spremljeno + + Nedavno spremljene zabilješke + + Prikaži sve + + Tipka za prikaz svih spremljenih zabilješki + %1$s proizvodi Mozilla. @@ -92,13 +103,6 @@ Odbaci - - Promijeni raspored otvorenih kartica. Idi u postavke i odaberi mrežu pod prikazom kartica. - - Idi u postavke - - Odbaci - Nova kartica @@ -108,6 +112,12 @@ Omiljene stranice + + + Vrati se natrag + + Prikaži sve + Otvorene kartice @@ -182,6 +192,10 @@ Uredi + + + Početni zaslon + Nije se moguće povezati. Neprepoznatljiva URL shema. @@ -548,8 +562,6 @@ Nova kartica Pronađi na stranici - - Sinkronizirane kartice Popis za čitanje @@ -594,6 +606,15 @@ Nakon jednog mjeseca + + + Počni na početnoj stranici + + Nakon četiri sata + + Uvijek + + Nikad Zatvori ručno @@ -1581,6 +1602,10 @@ Broj kartice Datum valjanosti + + Mjesec datuma valjanosti + + Godina datuma valjanosti Ime na kartici @@ -1602,6 +1627,24 @@ Unesi važeći broj kreditne kartice + + Molimo ispuni ovo polje + + Otključaj za prikaz spremljenih kreditnih kartica + + Osiguraj svoje kreditne kartice + + Postavi uzorak za otključavanje uređaja, PIN ili lozinku da bi tvoje spremljene kreditne kartice bile zaštićene od neovlaštenog pristupa drugih osoba. + + Postavi sada + + Kasnije + + Otključaj svoj uređaj + + + Otključ za korištenje spremljenih podataka o kreditnim karticama + Dodaj tražilicu diff --git a/app/src/main/res/values-hsb/strings.xml b/app/src/main/res/values-hsb/strings.xml index 8d459bf19..c635df12f 100644 --- a/app/src/main/res/values-hsb/strings.xml +++ b/app/src/main/res/values-hsb/strings.xml @@ -4,6 +4,7 @@ Priwatny %s %s (priwatny) + Dalše nastajenja @@ -47,6 +48,16 @@ Wubrany + + + Njedawno składowane + + Njedawno składowane zapołožki + + Wšě pokazać + + Tłóčatko „Wšě składowane zapołožki pokazać“ + %1$s so přez Mozilla zhotowja. @@ -94,13 +105,6 @@ Zaćisnyć - - Wubjerće wuhotowanje za wočinjene rajtarki. Přeńdźće k nastajenjam a wubjerće lěsycu pod rajtarkowym napohladom. - - K nastajenjam - - Zaćisnyć - Nowy rajtark @@ -110,6 +114,12 @@ Najhusćišo wopytane sydła + + + Wróćo skočić + + Wšě pokazać + Wočinjene rajtarki @@ -184,6 +194,10 @@ Wobdźěłać + + + Startowa wobrazowka + Zwisk móžny njeje. Njespóznawajomna URL-šema. @@ -547,8 +561,6 @@ Nowy rajtark Na stronje pytać - - Synchronizowane rajtarki Čitanska lisćina @@ -594,6 +606,15 @@ Po jednym měsacu + + + Na startowej wobrazowce započeć + + Po štyrjoch hodźinach + + Přeco + + Ženje Manuelnje začinić @@ -1573,6 +1594,10 @@ Kartowe čisło Datum płaćiwosće + + Datum płaćiwosće (měsac) + + Datum płaćiwosće (lěto) Mjeno na karće @@ -1594,6 +1619,24 @@ Prošu zapodajće płaćiwe čisło kreditneje karty + + Prošu wupjelńće tute polo + + Za zwobraznjenje wašich składowanych kartow wotewrěć + + Waše kreditne karty zawěsćić + + Nastajće gratowy zawrjenski muster, PIN abo hesło, zo byšće přistupej k swojim składowanym kreditnym kartam zadźěwał, jeli něchtó druhi waš grat ma. + + Nětko konfigurować + + Pozdźišo + + Wotewriće swój grat + + + Blokowanje zběhnyć, zo bychu so składowane informacije kreditneje karty wužiwali + Pytawu přidać diff --git a/app/src/main/res/values-hu/strings.xml b/app/src/main/res/values-hu/strings.xml index 68ca43cf1..47e8e157b 100644 --- a/app/src/main/res/values-hu/strings.xml +++ b/app/src/main/res/values-hu/strings.xml @@ -5,6 +5,7 @@ Privát %s %s (Privát) + További beállítások @@ -48,6 +49,16 @@ Kiválasztva + + + Nemrég mentett + + Legutóbb mentett könyvjelzők + + Összes megjelenítése + + Az összes mentett könyvjelző megjelenítése gomb + A %1$s a Mozilla terméke. @@ -93,13 +104,6 @@ Eltüntetés - - A nyitott lapok elrendezésének módosítása. Ugorjon a beállításokhoz, és válassza ki a rácsot a lapnézet alatt. - - Ugrás a beállításokhoz - - Eltüntetés - Új lap @@ -109,6 +113,12 @@ Kedvenc oldalak + + + Ugrás vissza + + Összes megjelenítése + Nyitott lapok @@ -185,6 +195,10 @@ Szerkesztés + + + Kezdőképernyő + Nem tud csatlakozni. Felismerhetetlen URL-séma. @@ -550,8 +564,6 @@ Új lap Keresés az oldalon - - Szinkronizált lapok Olvasási lista @@ -596,6 +608,15 @@ Egy hónap után + + + Kezdés a kezdőképernyőn + + Négy óra után + + Mindig + + Soha Bezárás kézzel @@ -1581,6 +1602,10 @@ Kártyaszám Lejárati dátum + + Lejárati dátum hónapja + + Lejárati dátum éve Kártyán szereplő név @@ -1602,6 +1627,24 @@ Adjon meg egy érvényes bankkártyaszámot + + Töltse ki ezt a mezőt + + Feloldás a mentett kártyák megtekintéshez + + Biztosítsa bankkártyáit + + Állítsa be az eszköz lezárási mintáját, PIN-kódját vagy jelszavát, hogy megvédje a mentett bankkártyáit, ha valaki hozzáfér az eszközéhez. + + Beállítás most + + Később + + Eszköz feloldása + + + Oldja fel, hogy a tárolt bankkártya-információkat használja + Keresőszolgáltatás hozzáadása diff --git a/app/src/main/res/values-hy-rAM/strings.xml b/app/src/main/res/values-hy-rAM/strings.xml index d9582c8ca..ad2c14bf1 100644 --- a/app/src/main/res/values-hy-rAM/strings.xml +++ b/app/src/main/res/values-hy-rAM/strings.xml @@ -4,6 +4,7 @@ Մասնավոր %s %s (մասնավոր) + Լր. ընտրանքներ @@ -48,6 +49,16 @@ Ընտրված + + + Վերջերս պահպանված + + Վերջերս պահպանված էջանիշները + + Ցուցադրել բոլորը + + Ցուցադրել բոլոր պահպանված էջանիշների կոճակը + %1$s-ը մշակված է Mozilla-ի կողմից: @@ -57,7 +68,7 @@ - %1$s-ին մաքրում է որոնման և զննարկման պատմությունը, երբ փակում եք ներդիրը կամ դուրս եք գալիս հավելվածից: Չնայած դա ձեզ անանուն չի դարձնում կայքերի կամ ձեր համացանցի ծառայություններ մատուցողի համար, այն ավելի հեշտ է դարձնում ձեր առցանց ակտիվության գաղտնիությունը այն դեպքում, եթե մեկ ուրիշը ևս օգտագործում է տվյալ սարքը: + %1$s-ը մաքրում է որոնման և զննարկման պատմությունը, երբ փակում եք ներդիրը կամ դուրս եք գալիս հավելվածից: Չնայած դա ձեզ անանուն չի դարձնում կայքերի կամ ձեր համացանցի ծառայություններ մատուցողի համար, այն ավելի հեշտ է դարձնում ձեր առցանց ակտիվության գաղտնիությունը այն դեպքում, եթե մեկ ուրիշը ևս օգտագործում է տվյալ սարքը: Տարածված առասպելներ գաղտնի դիտարկման վերաբերյալ Ջնջել աշխատաշրջանը @@ -92,13 +103,6 @@ Բաց թողնել - - Փոխեք բացված ներդիրների դասավորությունը: Գնացեք կարգավորումներ և ընտրեք Ցանց՝ ներդիրի տեսքի ներքո: - - Անցնել Կարգավորումներին - - Բաց թողնել - Նոր ներդիր @@ -109,6 +113,12 @@ Լավագույն կայքեր + + + Վերադառնալ + + Ցուցադրել բոլորը + Բաց ներդիրներ @@ -184,6 +194,10 @@ Խմբագրել + + + Հիմնական էկրան + Հնարավոր չէ կապակցվել: Անճանաչելի URL ուրվակազմ: @@ -545,8 +559,6 @@ Նոր ներդիր Գտնել էջում - - Համաժամեցված ներդիրներ Ընթերցացուցակ @@ -591,6 +603,15 @@ Մեկ ամիս անց + + + Սկսել տնից + + Չորս ժամ անց + + Միշտ + + Երբեք Ձեռքով փակեք @@ -928,7 +949,7 @@ Հավաքածուի ցանկ - Հավաքեք ձեզ համար կարևոր բաները:\nԽմբավորեք համանման որոնումները, կայքերը և ներդիրները՝ ավելի ուշ արագ մատչելու համար: + Հավաքեք ձեզ համար կարևոր բաները:\nԽմբավորեք համանման որոնումները, կայքերը և ներդիրները՝ հետո ավելի արագ մատչելու համար: Ընտրեք ներդիրները @@ -1529,7 +1550,7 @@ Ստեղծեք սարքի կողպեքի նմուշ, PIN կամ գաղտնաբառ՝ ձեր պահպանված մուտքանունները և գաղտնաբառերը մուտք գործելուց պաշտպանելու համար, եթե ձեր սարքը ուրիշի ձեռքն ընկնի: - Ավելի ուշ + Հետո Տեղակայել հիմա @@ -1570,6 +1591,10 @@ Քարտի համարը Քարտի ժամկետը + + Ժամկետի ամսաթվի ամիսը + + Ժամկետի ամսաթվի տարին Քարտի վրա ձեր անունը @@ -1591,6 +1616,23 @@ Մուտքագրեք բանկային վավեր քարտի համար + + Լրացրեք այս դաշտը + + Ապակողպեք՝ դիտելու համար պահպանված քարտերը + + Անվտանգ դարձրեք ձեր բանկային քարտերը + + Տեղակայեք սարքի կողպման նախշ, PIN կամ գաղտնաբառ՝ պաշտպանելու պահված բանկային քարտերը այն դեպքում, եթե որևէ մեկը ևս մուտք ունի Ձեր սարքին: + + Տեղակայել հիմա + + Ավելի ուշ + + Ապակողպեք ձեր սարքը + + Ապակողպեք՝ օգտագործելու համար բանկային քարտերի պահված տեղեկությունները + Ավելացնել որոնիչ diff --git a/app/src/main/res/values-ia/strings.xml b/app/src/main/res/values-ia/strings.xml index 7d3f87146..2003600d5 100644 --- a/app/src/main/res/values-ia/strings.xml +++ b/app/src/main/res/values-ia/strings.xml @@ -6,6 +6,7 @@ %s anonyme %s (nav. anonyme) + @@ -36,7 +37,7 @@ Exir del modo multiselection - Salvar schedas eligite al collection + Salvar le schedas seligite in un collection Selecte %1$s @@ -48,6 +49,16 @@ Seligite + + + Salvate recentemente + + Marcapaginas recentemente salvate + + Monstrar toto + + Monstrar tote le button marcapaginas salvate + %1$s es producite per Mozilla. @@ -94,13 +105,6 @@ Dimitter - - Cambio le disposition de schedas aperte. Vade a parametros e selige grillia sub le scheda vider. - - Vade a parametros - - Dimitter - Nove scheda @@ -109,6 +113,12 @@ Sitos popular + + + Revenir in + + Monstrar toto + Schedas aperte @@ -185,6 +195,10 @@ Rediger + + + Pagina initial + Connexion impossibile. Schema de URL non recognoscibile @@ -417,6 +431,11 @@ and the third is the device model. --> %1$s sur %2$s %3$s + + Cartas de credito + + Adresses + Schedas recipite @@ -451,9 +470,6 @@ Saper plus - - Disactivate globalmente, vade a parametros pro activar lo. - Telemetria @@ -468,6 +484,8 @@ Comparti datos re le functionalitates que tu usa in %1$s con Leanplum, nostre venditor de mercato mobile. + + Comparti le datos de uso basic con Adjust, nostre fornitor de marketing mobile Studios @@ -562,8 +580,6 @@ Nove scheda Trovar in le pagina - - Schedas synchronisate Lista de lectura @@ -610,6 +626,15 @@ Depost un mense + + + Initiar al pagina initial + + Post quatro horas + + Sempre + + Nunquam Clauder manualmente @@ -667,11 +692,11 @@ Clauder - Compartir schedas eligite + Compartir le schedas seligite - Menu del schedas eligite + Menu de schedas seligite Remover le scheda ex le collection @@ -822,8 +847,6 @@ Delite %1$s Adder plica - - Marcapagina create. Marcapagina salvate! @@ -977,7 +1000,7 @@ - %d schedas eligite + %d schedas seligite %d scheda seligite @@ -1500,10 +1523,8 @@ Autoplenar Synchronisar credentiales - - Active - - Inactive + + Synchronisar credentiales inter le apparatos Reconnecter @@ -1605,6 +1626,8 @@ Synchronisar cartas inter apparatos + + Synchronisar cartas Adde un carta de credito @@ -1617,6 +1640,10 @@ Numero del carta Data de expiration + + Mense de expiration + + Anno de expiration Nomine sur le carta @@ -1635,6 +1662,27 @@ Cartas salvate + + Insere un numero valide de carta de credito + + + Completa iste campo + + Disbloca pro vider tu cartas salvate + + Protege tu carta de credito + + Implementa un patrono de blocada apparato, PIN o contrasigno pro proteger tu cartas de credito de esser accedite, si alcuno altere ha tu apparato. + + Implementar ora + + Plus tarde + + Disbloca tu apparato + + + Disbloca pro usar le informationes de carta de credito immagazinate + Adder motor de recerca @@ -1799,19 +1847,13 @@ Remover - - Obtene le maximo de %s. - Clicca pro altere detalios - - Collige le objectos que te interessa - - Gruppa insimul recercas simile, sitos e schedas pro acceder rapidemente plus tarde. - - Tu es authenticate como %s sur un altere navigator Firefox sur iste telephono. Vole tu acceder con iste conto? - - Tu pote facilemente adder iste sito web al pagina initial de tu telephono pro acceder instantaneemente e navigar plus velocemente, como in un app. + + Navigar + + + Clauder + diff --git a/app/src/main/res/values-in/strings.xml b/app/src/main/res/values-in/strings.xml index 19121aa02..9ddf989bd 100644 --- a/app/src/main/res/values-in/strings.xml +++ b/app/src/main/res/values-in/strings.xml @@ -21,10 +21,6 @@ Tab privat Anda akan muncul di sini. - - Baidu - - JD 1 tab terbuka. Ketuk untuk beralih tab. @@ -99,13 +95,6 @@ Tutup - - Ubah tata letak tab terbuka. Buka pengaturan dan pilih kisi di bawah tampilan tab. - - Buka pengaturan - - Tutup - Tab baru @@ -185,6 +174,17 @@ Tampilan + + Ubahsuai tampilan pembaca + + Tambahkan + + Ubah + + + + Layar beranda + Tidak dapat terhubung. Skema URL yang tidak dapat dikenali. @@ -223,6 +223,11 @@ Pelajari lebih lanjut + + Cari %s + + Cari langsung dari bilah alamat + Buka tab Firefox baru @@ -414,6 +419,11 @@ and the third is the device model. --> %1$s dalam %2$s %3$s + + Kartu kredit + + Alamat + Tab yang diterima @@ -445,9 +455,6 @@ Pelajari lebih lanjut - - Dimatikan secara global, buka Pengaturan untuk menyalakannya. - Telemetri @@ -459,6 +466,8 @@ Data pemasaran Bagikan data mengenai fitur yang Anda gunakan pada %1$s dengan Leanplum, vendor pemasaran seluler kami. + + Bagikan data penggunaan dasar dengan Adjust, vendor pemasaran seluler kami Kajian @@ -546,8 +555,6 @@ Tab baru Temukan di laman - - Tab yang disinkronkan Daftar Baca @@ -592,6 +599,15 @@ Setelah satu bulan + + + Mulai dari Beranda + + Setelah empat jam + + Selalu + + Tidak Pernah Tutup secara manual @@ -608,12 +624,16 @@ Sesi pribadi Tab privat + + Tab tersinkron Tambah tab Tambah tab pribadi Pribadi + + Sinkron Tab Terbuka @@ -624,6 +644,8 @@ Bagikan semua tab Tab yang baru saja ditutup + + Setelan akun Setelan tab @@ -795,12 +817,12 @@ %1$s terhapus Tambah folder - - Markah dibuat. Markah berhasil disimpan! EDIT + + Ubah Pilih @@ -981,6 +1003,8 @@ Semua tindakan Baru saja digunakan + + Masuk untuk menyinkronkan Masuk ke Sync @@ -1177,9 +1201,6 @@ Sudah memiliki akun? - - Ketahui tentang %s Lihat apa yang baru Dapatkan jawabannya di sini - - Mulai sinkronkan markah, kata sandi, dan lainnya dengan akun Firefox Anda. + + Sinkronkan Firefox antar perangkat - Pelajari lebih lanjut + Bawa markah, riwayat, dan kata sandi ke Firefox di perangkat ini. @@ -1199,8 +1220,8 @@ Ya, masukkan saya Masuk… - - Masuk ke Firefox + + Daftar Tetap keluar @@ -1208,26 +1229,23 @@ Gagal masuk - Privasi otomatis - - Pengaturan privasi dan keamanan memblokir pelacak, malware, dan perusahaan yang mengikuti Anda. + Privasi selalu aktif + + Firefox secara otomatis menghentikan perusahaan yang mengikuti Anda di web secara rahasia. Standar (baku) - Memblokir lebih sedikit pelacak. Laman akan dimuat secara normal. + Seimbang untuk privasi dan kinerja. Halaman dimuat secara normal. Ketat (disarankan) Ketat - Memblokir lebih banyak pelacak, iklan, dan sembulan. Halaman dimuat lebih cepat, namun beberapa fungsi mungkin tidak berfungsi. - - Pilih posisi + Blokir lebih banyak pelacak sehingga laman dimuat lebih cepat, tetapi beberapa fungsionalitas pada laman mungkin rusak. + + Pilih penempatan bilah alat Anda - Coba menjelajah dengan satu tangan dengan bilah alat di bawah atau pindahkan ke atas. + Letakkan bilah alat agar mudah dijangkau. Tetap di bawah, atau pindahkan ke atas. Menjelajah dengan privat Privasi Anda + The first parameter is the name of the app (e.g. Firefox Preview) Substitute %s for long browser name. --> Kami merancang %s agar Anda dapat mengendalikan apa saja yang Anda bagikan secara daring dan apa yang Anda bagikan kepada kami. Pelajari pemberitahuan privasi kami @@ -1255,7 +1273,7 @@ Pilih tema Anda - Hemat baterai dan penglihatan Anda dengan mengaktifkan mode gelap. + Hemat baterai dan penglihatan Anda dengan mode gelap. Otomatis @@ -1311,13 +1329,13 @@ Standar (baku) - Memblokir lebih sedikit pelacak. Laman akan dimuat secara normal. + Seimbang untuk privasi dan kinerja. Halaman dimuat secara normal. Apa yang diblokir oleh perlindungan pelacakan standar Ketat - Memblokir lebih banyak pelacak, iklan, dan sembulan. Halaman dimuat lebih cepat, namun beberapa fungsi mungkin tidak berfungsi. + Blokir lebih banyak pelacak sehingga laman dimuat lebih cepat, tetapi beberapa fungsionalitas pada laman mungkin rusak. Apa yang diblokir oleh perlindungan pelacakan ketat @@ -1458,10 +1476,8 @@ Isi Otomatis Sinkronkan info masuk - - Aktif - - Nonaktif + + Sinkronkan log masuk antar perangkat Hubungkan kembali @@ -1552,6 +1568,69 @@ Sortir menu info masuk + + + Kartu kredit + + Simpan dan isi otomatis kartu + + Data terenkripsi + + Sinkronisasi kartu antar perangkat + + Sinkronkan kartu + + Tambahkan kartu kredit + + Kelola kartu tersimpan + + Tambah kartu + + Ubah kartu + + Nomor Kartu + + Tanggal Kedaluwarsa + + Bulan Tanggal Kedaluwarsa + + Tanggal Tahun Kedaluwarsa + + Nama pada Kartu + + Nama Alias Kartu + + Hapus kartu + + Hapus kartu + + Simpan + + Simpan + + Batal + + Kartu tersimpan + + Masukkan nomor kartu kredit yang sah + + Silahkan isi kolom ini + + Buka kunci untuk melihat kartu yang Anda simpan + + Amankan kartu kredit Anda + + Atur pola, PIN, atau kata sandi kunci perangkat untuk melindungi kartu kredit Anda yang tersimpan agar tidak diakses jika orang lain memiliki perangkat Anda. + + Atur sekarang + + Nanti + + Buka perangkat Anda + + + Buka kunci untuk menggunakan informasi kartu kredit tersimpan + Tambah mesin pencari @@ -1711,23 +1790,19 @@ Batal + + Setel tautan dari situs web, surel, dan pesan untuk secara otomatis dibuka di Firefox. + Hapus - - Dapatkan hasil maksimal dari %s. - Klik untuk lebih jelasnya - - Kumpulkan hal-hal yang penting bagi Anda - - Kelompokkan pencarian, situs, dan tab yang serupa agar dapat diakses cepat nanti. - - Anda masuk sebagai %s di peramban Firefox lainnya pada ponsel ini. Apakah Anda ingin masuk dengan akun tersebut? - - Anda dapat dengan mudah menambahkan situs web ini ke layar Beranda ponsel Anda untuk mendapatkan akses instan dan penjelajahan lebih cepat seperti menggunakan aplikasi. + + Arahkan ke atas + + + Tutup - + diff --git a/app/src/main/res/values-it/strings.xml b/app/src/main/res/values-it/strings.xml index d805839a4..2f3130b70 100644 --- a/app/src/main/res/values-it/strings.xml +++ b/app/src/main/res/values-it/strings.xml @@ -6,6 +6,7 @@ %s anonimo %s (nav. anonima) + Altre opzioni @@ -50,6 +51,16 @@ Selezionata + + + Aggiunti di recente + + Segnalibri aggiunti di recente + + Visualizza tutti + + Pulsante per visualizzare tutti i segnalibri salvati + %1$s è sviluppato da Mozilla. @@ -93,13 +104,6 @@ Chiudi - - Cambia la disposizione delle schede aperte. Vai alle impostazioni e seleziona Griglia sotto Visualizzazione schede. - - Vai alle impostazioni - - Annulla - Nuova scheda @@ -109,6 +113,12 @@ Siti principali + + + Torna a questa scheda + + Visualizza tutte + Schede aperte @@ -186,6 +196,10 @@ Modifica + + + Schermata principale + Connessione non riuscita. Schema URL non riconoscibile. @@ -558,8 +572,6 @@ Nuova scheda Trova nella pagina - - Schede sincronizzate Elenco lettura @@ -605,6 +617,15 @@ Dopo un mese + + + Inizia dalla schermata principale + + Dopo quattro ore + + Sempre + + Mai Chiudi manualmente @@ -1607,6 +1628,10 @@ Numero carta Data di scadenza + + Mese della data di scadenza + + Anno della data di scadenza Nome sulla carta @@ -1629,6 +1654,24 @@ Inserire un numero di carta di credito valido + + Compilare questo campo + + Sblocca per visualizzare le carte di credito salvate + + Proteggi le tue carte di credito + + Imposta una sequenza di blocco, PIN o password per impedire a chi si impossessa del dispositivo di visualizzare le carte di credito salvate. + + Imposta adesso + + Più tardi + + Sblocca il dispositivo + + + Sblocca per utilizzare le informazioni delle carte di credito salvate + Aggiungi motore di ricerca diff --git a/app/src/main/res/values-iw/strings.xml b/app/src/main/res/values-iw/strings.xml index 078bd7a0d..4a0b203c7 100644 --- a/app/src/main/res/values-iw/strings.xml +++ b/app/src/main/res/values-iw/strings.xml @@ -4,6 +4,7 @@ %s במצב פרטיות ‏%s (פרטי) + אפשרויות נוספות @@ -49,6 +50,16 @@ נבחר + + + נשמרו לאחרונה + + סימניות שנשמרו לאחרונה + + הצגת הכול + + כפתור להצגת כול הסימניות השמורות + ‏%1$s נוצר על־ידי Mozilla. @@ -95,13 +106,6 @@ סגירה - - ניתן לשנות את הפריסה של הלשוניות הפתוחות. יש לעבור להגדרות ולבחור ברשת תחת תצוגת לשוניות. - - מעבר להגדרות - - התעלמות - לשונית חדשה @@ -111,6 +115,9 @@ אתרים מובילים + + הצגת הכול + לשוניות פתוחות @@ -185,6 +192,10 @@ עריכה + + + מסך הבית + לא ניתן להתחבר. מבנה הכתובת אינו ברור. @@ -547,8 +558,6 @@ לשונית חדשה חיפוש בדף - - לשוניות מסונכרנות רשימת קריאה @@ -594,6 +603,15 @@ אחרי חודש אחד + + + להתחיל ממסך הבית + + לאחר 4 שעות + + תמיד + + לעולם לא סגירה באופן ידני @@ -1530,7 +1548,7 @@ שמירה מאובטחת של הכניסות והססמאות שלך - ניתן להגדיר תבנית נעילת מכשיר, קוד או ססמה כדי להגן על פרטי הגישה והססמאות שלך מפני גורמים בלתי מהימנים שמחזיקים במכשיר שלך. + ניתן להגדיר תבנית נעילת מכשיר, קוד או ססמה כדי להגן על פרטי הגישה והססמאות השמורות שלך מפני גורמים בלתי מהימנים שמחזיקים במכשיר שלך. מאוחר יותר @@ -1574,6 +1592,10 @@ מספר כרטיס תאריך תפוגה + + החודש של תאריך התפוגה + + השנה של תאריך התפוגה שם שעל הכרטיס @@ -1595,6 +1617,24 @@ נא להכניס מספר כרטיס אשראי תקין + + נא למלא שדה זה + + יש לבטל את הנעילה כדי להציג את הכרטיסים השמורים שלך + + אבטחת כרטיסי האשראי שלך + + ניתן להגדיר תבנית נעילת מכשיר, קוד או ססמה כדי להגן על כרטיסי האשראי השמורים שלך מפני גורמים בלתי מהימנים שמחזיקים במכשיר שלך. + + להגדיר כעת + + מאוחר יותר + + שחרור נעילת המכשיר שלך + + + יש לבטל את הנעילה כדי להשתמש בפרטי כרטיס האשראי השמור + הוספת מנוע חיפוש diff --git a/app/src/main/res/values-ja/strings.xml b/app/src/main/res/values-ja/strings.xml index 54415a6d1..e75c0ff13 100644 --- a/app/src/main/res/values-ja/strings.xml +++ b/app/src/main/res/values-ja/strings.xml @@ -96,13 +96,6 @@ 閉じる - - 開いたタブのレイアウトを変更します。設定画面を開き、タブビューの下のグリッドを選択してください。 - - 設定を開く - - 閉じる - 新しいタブ @@ -188,6 +181,10 @@ 編集 + + + ホーム画面 + 接続できません。認識できない URL スキームです。 @@ -555,8 +552,6 @@ 新しいタブ ページ内検索 - - 同期したタブ リーディングリスト @@ -601,6 +596,15 @@ 1 か月後 + + + ホーム画面で開始 + + 4 時間後 + + 常に使用する + + 使用しない 手動で閉じる @@ -1590,6 +1594,10 @@ カード番号 有効期限 + + 有効期限月 + + 有効期限年 カード名義 @@ -1611,6 +1619,25 @@ 有効なクレジットカード番号を入力してください + + このフィールドは入力必須です + + 保存されたカード情報を表示するにはロック解除してください + + クレジットカード情報の保護 + + + 端末のロックパターンや PIN、パスワードを設定して、保存されたクレジットカード情報とパスワードを他人の不正なアクセスから保護しましょう。 + + 今すぐ設定 + + 後で + + 端末のロック解除 + + + ロックを解除して保存したクレジットカード情報を使用します + 検索エンジンの追加 diff --git a/app/src/main/res/values-ka/strings.xml b/app/src/main/res/values-ka/strings.xml index 7c4bdfc12..8847d1e4b 100644 --- a/app/src/main/res/values-ka/strings.xml +++ b/app/src/main/res/values-ka/strings.xml @@ -4,6 +4,7 @@ პირადი %s %s (პირადი) + დამატებითი პარამეტრები @@ -47,6 +48,16 @@ მონიშნულია + + + ბოლოს შენახული + + ბოლოს ჩანიშნული + + ყველას ჩვენება + + ყველა ჩანიშნულის გამოსაჩენი ღილაკი + %1$s შემქმნელი Mozilla. @@ -90,13 +101,6 @@ გამოტოვება - - შეცვალეთ გახსნილი ჩანართების განლაგება. გადადით პარამეტრებში და აირჩიეთ ბადისებრი, ჩანართის ხედში. - - პარამეტრებში გადასვლა - - გამოტოვება - ახალი ჩანართი @@ -106,6 +110,12 @@ რჩეული საიტები + + + წინაზე გადასვლა + + ყველას ჩვენება + გახსნილი ჩანართები @@ -180,6 +190,10 @@ ჩასწორება + + + მთავარი ეკრანი + ვერ დაუკავშირდა. გაურკვეველი URL-სქემა. @@ -544,8 +558,6 @@ ახალი ჩანართი პოვნა გვერდზე - - დასინქრონებული ჩანართები წასაკითხთა სია @@ -591,6 +603,15 @@ ერთი თვის შემდეგ + + + მთავარით დაწყება + + 4 საათის შემდეგ + + ყოველთვის + + არასდროს ხელით დახურვა @@ -1572,6 +1593,10 @@ ბარათის ნომერი ვადის გასვლის თარიღი + + ვადის გასვლის თვე + + ვადის გასვლის წელიწადი მფლობელის სახელი @@ -1593,6 +1618,23 @@ გთხოვთ, შეიყვანოთ საკრედიტო ბარათის მართებული ნომერი + + გთხოვთ, შეავსოთ ეს ველი + + გახსენით შენახული ბარათების სანახავად + + დაიცავით საკრედიტო ბარათები + + დააყენეთ მოწყობილობის ჩასაკეტად მოსახაზი, PIN-კოდი ან პაროლი, თქვენი ბარათების მონაცემებთან, უცხო პირების წვდომის აღსაკვეთათ. + + დაყენება ახლავე + + მოგვიანებით + + გახსენით მოწყობილობა + + გახსენით, შენახული ბარათის გამოსაყენებლად + საძიებო სისტემის დამატება diff --git a/app/src/main/res/values-kab/strings.xml b/app/src/main/res/values-kab/strings.xml index df083a661..3af28118a 100644 --- a/app/src/main/res/values-kab/strings.xml +++ b/app/src/main/res/values-kab/strings.xml @@ -4,6 +4,7 @@ Uslig %s %s (Uslig) + Ugar n yiγewwaṛen @@ -51,6 +52,16 @@ Iţufren + + + Yettwasekles melmi kan + + Ticraḍ n yisebtar yettwaskelsen melmi kan + + Sken kullec + + Taqeffalt teskanay-d meṛṛa ticraḍ n yisebtar yettwaskelsen + %1$s d afares n Mozilla. @@ -96,13 +107,6 @@ Tiktiwin tigejdanin yuzzlen ur nṣeḥḥi ara Zgel - - Senfel taneɣruft n waccaren yeldin. Ddu ɣer yiɣewwaren syen fren iẓiki deg n yiccer. - - Ddu ɣer yiɣewwaren - - Zgel - Iccer amaynut @@ -112,6 +116,12 @@ Tiktiwin tigejdanin yuzzlen ur nṣeḥḥi ara Ismal ufrinen + + + Uɣal ɣer deffir + + Sken kullec + Ldi icarren @@ -187,6 +197,10 @@ Tiktiwin tigejdanin yuzzlen ur nṣeḥḥi ara Ẓreg + + + Agilal agejdan + Ur izmir ara ad yeqqen. Azenziɣ n tensa URL ur yettwassen ara. @@ -554,8 +568,6 @@ Tiktiwin tigejdanin yuzzlen ur nṣeḥḥi ara Iccer amaynut Af deg usebter - - Iccaren yemtawin Tabdart n tɣuṛi @@ -600,6 +612,15 @@ Tiktiwin tigejdanin yuzzlen ur nṣeḥḥi ara Seld yiwen n waggur + + + Bdu seg ugilal agejdan + + Seld rebεa n yisragen + + Yal tikkelt + + Urǧin Mdel s ufus @@ -1586,6 +1607,10 @@ Tiktiwin tigejdanin yuzzlen ur nṣeḥḥi ara Uṭṭun n tkarḍa Azemz n taggara + + Azemz n taggara n wayyur + + Azemz n taggar n useggas Isem ɣef tkarḍa @@ -1606,6 +1631,23 @@ Tiktiwin tigejdanin yuzzlen ur nṣeḥḥi ara Ma ulac aɣilif sekcem uṭṭun ameɣtu n tkarḍa n usmad + + Ttxil-k·m ččar urti-a + + Kkes asekkeṛ i wakken ad twaliḍ tikerḍiwin-ik·im yettwaskelsen + + Seɣles tikerḍiwin-ik·im n usmad + + Sbadu taneɣruft n usekkeṛ n yibenk, tangalt PIN neq awal uffir i ummesten n tkerḍiwin-ik·im n usmad yettwaskelsen ticki yella win ikecmen ɣer yibenk-inek·inem. + + Sbadu tura + + Ticki + + Serreḥ i ibenk-inek·inem + + Kkes asekkeṛ i wakken ad tesqedceḍ talɣut n tkarḍa n usmad + Rnu amsedday n unadi diff --git a/app/src/main/res/values-kk/strings.xml b/app/src/main/res/values-kk/strings.xml index 4574961a0..5cdbee3ea 100644 --- a/app/src/main/res/values-kk/strings.xml +++ b/app/src/main/res/values-kk/strings.xml @@ -4,6 +4,7 @@ Жекелік %s %s (Жекелік) + Көбірек опциялар @@ -47,6 +48,17 @@ Таңдалған + + + Жуырда сақталған + + + Жуырда сақталған бетбелгілер + + Барлығын көрсету + + Барлық сақталған бетбелгілерді көрсету батырмасы + %1$s жасаған Mozilla. @@ -91,13 +103,6 @@ Тайдыру - - Ашық беттер жаймасын өзгерту. Баптауларға өтіп, беттер көрінісі астындағы торды таңдаңыз. - - Баптауларға өту - - Тайдыру - Жаңа бет @@ -106,6 +111,12 @@ Үздік сайттар + + + Кері оралу + + Барлығын көрсету + Ашық беттер @@ -179,6 +190,10 @@ Түзету + + + Бастапқы экран + Байланысу мүмкін емес. URL схемасы белгісіз. @@ -538,8 +553,6 @@ Жаңа бет Беттен табу - - Синхрондалған беттер Оқу тізімі @@ -584,6 +597,15 @@ Бір айдан кейін + + + Бастапқы экраннан бастау + + Төрт сағаттан кейін + + Әрқашан + + Ешқашан Қолмен жабу @@ -1564,6 +1586,10 @@ Карта нөмірі Мерзімнің біту күні + + Жарамдылық мерзімінің айы + + Жарамдылық мерзімінің жылы Картадағы аты @@ -1585,6 +1611,24 @@ Несиелік картаның жарамды нөмірін енгізіңіз + + Бұл өрісті толтырыңыз + + Сақталған карталарыңызды көру үшін бұғаттауын ашыңыз + + Несиелік карталарыңызды қорғаңыз + + Бөтен адам сіздің құрылғыңызда болса, одан сақталған несиелік карталарды қорғау үшін құрылғының бұғаттау үлгісін, PIN-кодын немесе парольді орнатыңыз. + + Қазір баптау + + Кейінірек + + Құрылғының бұғаттауын ашыңыз + + + Сақталған несиелік карта ақпаратын қолдану үшін бұғаттауын ашыңыз + Іздеу жүйесін қосу diff --git a/app/src/main/res/values-kmr/strings.xml b/app/src/main/res/values-kmr/strings.xml index 5cc849d06..57238d939 100644 --- a/app/src/main/res/values-kmr/strings.xml +++ b/app/src/main/res/values-kmr/strings.xml @@ -94,13 +94,6 @@ Bigire - - Tu dikarî raxistina hilpekînên vekirî biguherînî. Here sazkariyan û ji bin "xuyabûna hilpekînan" grîdê hilbijêre. - - Here sazkariyan - - Bigire - @@ -416,6 +409,11 @@ and the third is the device model. --> %1$s - %2$s %3$s + + Kartên krediyê + + Navnîşan + Hilpekînên hatine stendin @@ -447,9 +445,6 @@ Zêdetir bizane - - Bi temamî hat girtin, ji bo vekirinê here Sazkariyan. - Telemetrî @@ -460,6 +455,8 @@ Daneyên bazarkirinê Daneyên têkildarî taybetiyên %1$sê ku tu bi kar tînî bi Leanpluma em xizmeta bazara mobîl jê dikirin re parve dike. + + Daneyên bikaranînê yên bingehîn bi hevkara me ya kar Adjustê tên parvekirin Lêkolîn @@ -547,8 +544,6 @@ Hilpekîna nû Di rûpelê de bibîne - - Hilpekînên senkronîzekirî Lîsteya xwendinê @@ -798,8 +793,6 @@ %1$s hate jêbirin Peldankê tevlî bike - - Favorî hat afirandin. Favorî hat hilanîn! @@ -1456,10 +1449,8 @@ Bixweber dagire Hesaban senkronîze bike - - Vekirî - - Girtî + + Hesaban di navbera amûran de sync bike Dîsa girê bide @@ -1560,6 +1551,8 @@ Kartan di navbera amûran de senkronîze bike + + Karda syncê Kredîkartekê lê zêde bike @@ -1589,6 +1582,23 @@ Kartên tomarkirî + + Tika ye hejmereke derbasdar ya karta krediyê binivîse + + Ji bo kartên xwe yên qeydkirî bibînî kilîdê rake + + Kartên xwe yên krediyê bixe ewlehiyê + + Nîgareke kilîdê, PIN yan jî şîfreyekê diyar bike ji bo ku gava amûra te bikeve destê kesên din kartên te yên krediyê bên parastin. + + Niha saz bike + + Paşê + + Kilîda amûra xwe veke + + Kilîdê rake ku dikaribî agahiyên kartên krediyê yên tomarkirî bi kar bînî + Motora lêgerînê tevlî bike @@ -1752,19 +1762,13 @@ Rake - - Ji %s’ê fêdeya herî zêde bibînin. - Ji bo agahiyên zêdetir, bitikîne - - Tiştên ku ji te re girîng in berhev bike - - Lêgerîn, malper û hilpekînên wekhev, bike kom da ku paşê tu karibî xwe zû bigihînî wan. - - Tu li ser vê telefonê di gerokeke din a Firefoxê de wekî %s têketî yê. Tu dixwazî bi vî hesabî têkevî? - - Tu dikarî vê malperê bi hêsanî li ekrana Malê ya telefona xwe zêde bikî û dikarî vê malperê bilez û wekî ku bernamokek be bi kar bînî. + + Jorê + + + Bigire + diff --git a/app/src/main/res/values-ko/strings.xml b/app/src/main/res/values-ko/strings.xml index 27b190017..82de41f89 100644 --- a/app/src/main/res/values-ko/strings.xml +++ b/app/src/main/res/values-ko/strings.xml @@ -6,6 +6,7 @@ 사생활 보호 %s %s (사생활 보호) + 옵션 더보기 @@ -53,6 +54,16 @@ 선택됨 + + + 최근 저장됨 + + 최근 저장된 북마크 + + 모두 표시 + + 저장된 북마크 모두 표시 버튼 + %1$s는 Mozilla에서 제작했습니다. @@ -100,13 +111,6 @@ 닫기 - - 열린 탭의 레이아웃을 변경하세요. 설정으로 이동하여 탭 보기에서 그리드를 선택하세요. - - 설정으로 이동 - - 닫기 - 새 탭 @@ -116,6 +120,12 @@ 상위 사이트 + + + 최근 탭으로 이동 + + 모두 표시 + 탭 열기 @@ -193,6 +203,10 @@ 편집 + + + 홈 화면 + 연결할 수 없음. 인식할 수 없는 URL 구성표. @@ -560,8 +574,6 @@ 새 탭 페이지에서 찾기 - - 동기화된 탭 읽기 목록 @@ -607,6 +619,15 @@ 한 달 후 + + + 홈에서 시작 + + 4시간 후 + + 항상 + + 안 함 수동으로 닫기 @@ -1574,7 +1595,7 @@ 로그인과 비밀번호 보안 - 다른 사람이 기기를 가지고 있는 경우, 저장된 로그인과 비밀번호에 접근하지 못하도록 기기 잠금 패턴, PIN 또는 비밀번호를 설정하세요. + 다른 사람이 내 기기를 가지고 있는 경우, 저장된 로그인과 비밀번호에 접근하지 못하도록 기기 잠금 패턴, PIN 또는 비밀번호를 설정하세요. 나중에 @@ -1619,6 +1640,10 @@ 유효 기간 + + 유효 기간 월 + + 유효 기간 년 카드상의 이름 @@ -1640,6 +1665,24 @@ 유효한 신용 카드 번호를 입력해 주세요 + + 이 항목을 입력하세요. + + 저장된 카드를 보려면 잠금 해제 + + 신용 카드 보안 + + 다른 사람이 내 기기를 가지고 있는 경우, 저장된 신용 카드에 접근하지 못하도록 기기 잠금 패턴, PIN 또는 비밀번호를 설정하세요. + + 지금 설정 + + 나중에 + + 기기 잠금 해제 + + + 저장된 신용 카드 정보를 사용하려면 잠금 해제 + 검색 엔진 추가 diff --git a/app/src/main/res/values-lt/strings.xml b/app/src/main/res/values-lt/strings.xml index 4a0db67f6..0450c77be 100644 --- a/app/src/main/res/values-lt/strings.xml +++ b/app/src/main/res/values-lt/strings.xml @@ -412,6 +412,11 @@ and the third is the device model. --> „%1$s“, esanti „%2$s%3$s“ + + Mokėjimo kortelės + + Adresai + Gautos kortelės @@ -1457,10 +1462,8 @@ Užpildyti automatiškai Sinchronizuoti prisijungimus - - Taip - - Ne + + Sinchronizuoti prisijungimus tarp įrenginių Prisijungti iš naujo @@ -1565,6 +1568,8 @@ Sinchronizuoti korteles tarp įrenginių + + Sinchronizuoti korteles Pridėti mokėjimo kortelę @@ -1596,6 +1601,23 @@ Įrašytos kortelės + + Įveskite teisingą mokėjimo kortelės numerį + + Atrakinkite, norėdami peržiūrėti įrašytas korteles + + Apsaugokite savo mokėjimo korteles + + Naudokite įrenginio užraktą, PIN, arba slaptažodį, kad apsaugotumėte savo mokėjimo korteles tada, kai jūsų įrenginį turi kažkas kitas. + + Apsaugoti dabar + + Vėliau + + Atrakinkite savo įrenginį + + Atrakinkite, norėdami naudoti įrašytą mokėjimo kortelės informaciją + Pridėti ieškyklę @@ -1767,4 +1789,10 @@ Spustelėkite čia, jeigu norite daugiau informacijos - + + Pereiti aukštyn + + + Užverti + + diff --git a/app/src/main/res/values-nb-rNO/strings.xml b/app/src/main/res/values-nb-rNO/strings.xml index 2eba8af50..40665e7ba 100644 --- a/app/src/main/res/values-nb-rNO/strings.xml +++ b/app/src/main/res/values-nb-rNO/strings.xml @@ -4,6 +4,7 @@ Privat %s %s (privat) + Flere innstillinger @@ -48,6 +49,16 @@ Valgt + + + Nylig lagret + + Nylig lagrede bokmerker + + Vis alle + + Vis alle lagrede bokmerker-knapp + %1$s er produsert av Mozilla. @@ -95,13 +106,6 @@ Ignorer - - Endre utseende av åpne faner. Gå til innstillinger og velg rutenett under fanevisning. - - Gå til innstillinger - - Avvis - Ny fane @@ -111,6 +115,12 @@ Mest besøkte nettsteder + + + Hopp inn igjen + + Vis alle + Åpne faner @@ -186,6 +196,10 @@ Rediger + + + Startskjerm + Kan ikke koble til. Ugjenkjennelig URL-skjema. @@ -553,8 +567,6 @@ Ny fane Søk på siden - - Synkroniserte faner Leseliste @@ -599,6 +611,15 @@ Etter en måned + + + Start på starskjerm + + Etter fire timer + + Alltid + + Aldri Lukk manuelt @@ -1593,6 +1614,10 @@ Kortnummer Utløpsdato + + Utløpsdato måned + + Utløpsdato år Navn på kort @@ -1613,6 +1638,24 @@ Oppgi et gyldig betalingskortnummer + + Fyll ut dette feltet + + Lås opp for å se dine lagrede betalingskort + + Sikre dine betalingskort + + Konfigurer en PIN-kode, et passord eller et låsemønster for å beskytte de lagrede betalingskortene dine om noen andre skulle få tak i enheten din. + + Konfigurer nå + + Senere + + Lås opp enheten din + + + Lås opp for å bruke lagret betalingskortinformasjon + Legg til søkemotor diff --git a/app/src/main/res/values-night/colors.xml b/app/src/main/res/values-night/colors.xml index c4cc6a4ae..a2e2e7920 100644 --- a/app/src/main/res/values-night/colors.xml +++ b/app/src/main/res/values-night/colors.xml @@ -51,9 +51,11 @@ @color/search_suggestion_indicator_icon_color_dark_theme @color/search_suggestion_indicator_icon_bookmark_color_dark_theme @color/accent_high_contrast_dark_theme + @color/accent_high_contrast_dark_theme @color/preference_section_header_dark_theme @color/accent_high_contrast_dark_theme @color/accent_high_contrast_dark_theme + @color/recently_used_share_menu_dark_theme @color/mozac_widget_favicon_background_dark_theme @color/mozac_widget_favicon_border_dark_theme @@ -78,10 +80,10 @@ @color/top_site_title_text_dark_theme - #3A3944 - #5B5B66 - @color/photonViolet50 - @color/dark_grey_90 + @color/photonDarkGrey40 + @color/photonDarkGrey05 + @color/foundation_light_theme + @color/photonDarkGrey90 @color/synced_tabs_separator_dark_theme diff --git a/app/src/main/res/values-nl/strings.xml b/app/src/main/res/values-nl/strings.xml index 87b3f33ef..c22472c53 100644 --- a/app/src/main/res/values-nl/strings.xml +++ b/app/src/main/res/values-nl/strings.xml @@ -5,6 +5,7 @@ Privé %s %s (Privé) + Meer opties @@ -51,6 +52,16 @@ Geselecteerd + + + Onlangs opgeslagen + + Recent opgeslagen bladwijzers + + Alles tonen + + Knop Alle opgeslagen bladwijzers tonen + %1$s is gemaakt door Mozilla. @@ -98,13 +109,6 @@ Sluiten - - Wijzig de opmaak van open tabbladen. Ga naar instellingen en selecteer onder Tabbladweergave ‘Raster’. - - Naar Instellingen - - Sluiten - Nieuw tabblad @@ -114,6 +118,12 @@ Topwebsites + + + Terugspringen + + Alles tonen + Open tabbladen @@ -190,6 +200,10 @@ Bewerken + + + Startscherm + Kan niet verbinden. Onherkenbaar URL-schema. @@ -551,8 +565,6 @@ Nieuw tabblad Zoeken op pagina - - Gesynchroniseerde tabbladen Leeslijst @@ -600,6 +612,15 @@ Na een maand + + + Op startscherm beginnen + + Na vier uur + + Altijd + + Nooit Handmatig sluiten @@ -1579,6 +1600,10 @@ Kaartnummer Vervaldatum + + Vervaldatum – maand + + Vervaldatum – jaar Naam op kaart @@ -1600,6 +1625,24 @@ Voer een geldig creditcardnummer in + + Vul dit veld in + + Ontgrendel om uw opgeslagen kaarten te bekijken + + Beveilig uw creditcards + + Stel een vergrendelingspatroon, pincode of wachtwoord voor uw apparaat in om uw opgeslagen creditcards te beschermen tegen toegang als iemand anders uw apparaat heeft. + + Nu instellen + + Later + + Ontgrendel uw apparaat + + + Ontgrendelen om opgeslagen creditcardgegevens te gebruiken + Zoekmachine toevoegen diff --git a/app/src/main/res/values-nn-rNO/strings.xml b/app/src/main/res/values-nn-rNO/strings.xml index be6fc13ca..282a3fa2a 100644 --- a/app/src/main/res/values-nn-rNO/strings.xml +++ b/app/src/main/res/values-nn-rNO/strings.xml @@ -5,6 +5,7 @@ Privat %s %s (privat) + Fleire innstillingar @@ -52,6 +53,16 @@ Vald + + + Nyleg lagra + + Nylig lagra bokmerke + + Vis alle + + Vis alle lagra bokmerke-knapp + %1$s er produsert av Mozilla. @@ -96,13 +107,6 @@ Ignorer - - Endre utsjånad av opne faner. Gå til innstillingar og vel rutenett under fanevising. - - Gå til Innstillingar - - Avvis - Ny fane @@ -112,6 +116,12 @@ Mest besøkte nettstadar + + + Hopp inn igjen + + Vis alle + Opne faner @@ -186,6 +196,10 @@ Rediger + + + Startskjerm + Klarte ikkje å kople til. Ukjenneleg URL-skjema. @@ -551,8 +565,6 @@ Ny fane Finn på sida - - Synkroniserte faner Leseliste @@ -598,6 +610,15 @@ Etter ein månad + + + Start på starskjerm + + Etter fire timar + + Alltid + + Aldri Lat att manuelt @@ -1586,6 +1607,10 @@ Kortnummer Går ut-dato + + Går ut-dato, månad + + Går ut-dato, år Namn på kort @@ -1607,6 +1632,24 @@ Skriv inn eit gyldig betalingskortnummer + + Fyll ut dette feltet + + Lås opp for å sjå lagra betalingskort + + Sikre betalingskorta dine + + Konfigurer eit låsemønster for eininga, PIN, eller passord, for å beskytte dei lagra betalingskorta dine om nokon andre skulle få tak i eininga di. + + Konfigurer no + + Seinare + + Lås opp eininga di + + + Lås opp for å bruke lagra betalingskortinformasjon + Legg til søkjemotor diff --git a/app/src/main/res/values-oc/strings.xml b/app/src/main/res/values-oc/strings.xml index 3b881459b..6699ba92d 100644 --- a/app/src/main/res/values-oc/strings.xml +++ b/app/src/main/res/values-oc/strings.xml @@ -1614,6 +1614,23 @@ Picatz un numèro de carta de crèdit valid + + Desblocatz per veire las cartas enregistradas + + + Securizatz vòstras cartas de crèdit + + Configuratz un esquèma de verrolhatge, un còdi PIN o un senhal per protegir vòstres identificants de cartas de crèdit enregistrats se per cas qualqu’un accedisca a vòstre periferic. + + Configurar ara + + Mai tard + + Desverrolhatz lo periferic + + + Desverrolhatz per utilizar las informacions de cartas de crèdit enregistradas + Apondre un motor de recèrca @@ -1783,6 +1800,9 @@ Clicatz per aver de detalhs + + Remontar + Tampar diff --git a/app/src/main/res/values-pa-rIN/strings.xml b/app/src/main/res/values-pa-rIN/strings.xml index 1fd1bcb57..d9af5dbb9 100644 --- a/app/src/main/res/values-pa-rIN/strings.xml +++ b/app/src/main/res/values-pa-rIN/strings.xml @@ -98,13 +98,6 @@ ਖ਼ਾਰਜ ਕਰੋ - - ਖੁੱਲ੍ਹੀਆਂ ਟੈਬਾਂ ਦੇ ਖਾਤੇ ਨੂੰ ਬਦਲੋ। ਸੈਟਿੰਗਾਂ ਉੱਤੇ ਜਾਓ ਅਤੇ ਟੈਬ ਵੇਖਣ ਲਈ ਗਿੱਡ ਚੁਣੋ। - - ਸੈਟਿੰਗਾਂ ਉੱਤੇ ਜਾਓ - - ਖ਼ਾਰਜ ਕਰੋ - ਨਵੀਂ ਟੈਬ @@ -560,8 +553,6 @@ ਨਵੀਂ ਟੈਬ ਸਫ਼ੇ ‘ਚ ਲੱਭੋ - - ਸਿੰਕ ਕੀਤੀਆਂ ਟੈਬਾਂ ਪੜ੍ਹਨ ਸੂਚੀ @@ -1612,6 +1603,21 @@ ਵਾਜਬ ਕਰੈਡਿਟ ਕਾਰਡ ਨੰਬਰ ਦਿਓ ਜੀ + + ਆਪਣੇ ਸੰਭਾਲੇ ਹੋਏ ਕਾਰਡ ਵੇਖਣ ਲਈ ਅਣ-ਲਾਕ ਕਰੋ + + ਆਪਣੇ ਕਰੈਡਿਟ ਕਾਰਡ ਸੁਰੱਖਿਅਤ ਕਰੋ + + ਆਪਣੀ ਡਿਵਾਇਸ ਲਈ ਲਾਕ ਪੈਟਰਨ, ਪਿੰਨ, ਜਾਂ ਪਾਸਵਰਡ ਸੈੱਟ ਕਰੋ ਤਾਂ ਜੋ ਕਿਸੇ ਹੋਰ ਹੱਥ ਤੁਹਾਡਾ ਡਿਵਾਇਸ ਹੋਣ ਉੱਤੇ ਤੁਹਾਡੇ ਸੰਭਾਲੇ ਪਾਸਵਰਡ ਸੁਰੱਖਿਅਤ ਰਹਿਣ। + + ਹੁਣੇ ਸੈਟ ਅੱਪ ਕਰੋ + + ਬਾਦ \'ਚ + + ਆਪਣਾ ਡਿਵਾਇਸ ਅਣ-ਲਾਕ ਕਰੋ + + ਸੰਭਾਲੀ ਕਰੈਡਿਟ ਕਾਰਡ ਜਾਣਕਾਰੀ ਵਰਤਣ ਲਈ ਅਣ-ਲਾਕ ਕਰੋ + ਖੋਜ ਇੰਜਣ ਜੋੜੋ diff --git a/app/src/main/res/values-pl/strings.xml b/app/src/main/res/values-pl/strings.xml index 8ba0a1f4f..917cec130 100644 --- a/app/src/main/res/values-pl/strings.xml +++ b/app/src/main/res/values-pl/strings.xml @@ -5,6 +5,7 @@ %s (tryb prywatny) %s (tryb prywatny) + Więcej opcji @@ -49,6 +50,16 @@ Zaznaczone + + + Ostatnio zachowane + + Ostatnio dodane zakładki + + Wyświetl wszystkie + + Przycisk wyświetlenia wszystkich dodanych zakładek + %1$s jest tworzony przez Mozillę. @@ -94,13 +105,6 @@ Zamknij - - Zmień układ otwartych kart. Otwórz ustawienia i wybierz siatkę w sekcji wyglądu kart. - - Otwórz ustawienia - - Zamknij - Nowa karta @@ -110,6 +114,12 @@ Popularne + + + Wskocz z powrotem + + Wyświetl wszystkie + Otwarte karty @@ -186,6 +196,10 @@ Edytuj + + + Strona startowa + Nie można się połączyć. Nieznany protokół adresu URL. @@ -550,8 +564,6 @@ Nowa karta Znajdź na stronie - - Karty z innych urządzeń Do przeczytania @@ -587,9 +599,9 @@ Siatka - Zamykanie kart + Zamykaj karty - Ręczne + Ręcznie Po jednym dniu @@ -597,6 +609,15 @@ Po miesiącu + + + Zaczynaj na stronie startowej + + Po czterech godzinach + + Zawsze + + Nigdy Zamykane ręcznie @@ -1578,6 +1599,10 @@ Numer karty Data ważności + + Miesiąc daty ważności + + Rok daty ważności Imię i nazwisko @@ -1598,6 +1623,24 @@ Wprowadź prawidłowy numer karty płatniczej + + Wypełnij to pole + + Odblokuj, aby wyświetlić zachowane karty + + Zabezpiecz karty płatnicze + + Skonfiguruj wzór blokady, kod PIN lub hasło, aby ochronić zachowane karty płatnicze w przypadku, gdy ktoś inny uzyska dostęp do urządzenia. + + Skonfiguruj teraz + + Później + + Odblokuj urządzenie + + + Odblokuj, aby użyć przechowywanych informacji o kartach płatniczych + Dodaj wyszukiwarkę diff --git a/app/src/main/res/values-pt-rBR/strings.xml b/app/src/main/res/values-pt-rBR/strings.xml index 28e7c2abe..318ede103 100644 --- a/app/src/main/res/values-pt-rBR/strings.xml +++ b/app/src/main/res/values-pt-rBR/strings.xml @@ -4,6 +4,7 @@ %s privativo %s (privativo) + Mais opções @@ -47,6 +48,16 @@ Selecionada + + + Salvos recentemente + + Favoritos salvos recentemente + + Mostrar todos + + Botão de mostrar todos os favoritos salvos + O %1$s é produzido pela Mozilla. @@ -93,13 +104,6 @@ Descartar - - Altere o layout de abas abertas. Vá em configurações e selecione grade na visão de abas. - - Ir para configurações - - Descartar - Nova aba @@ -109,6 +113,12 @@ Sites preferidos + + + Retornar + + Mostrar tudo + Abas abertas @@ -184,6 +194,10 @@ Editar + + + Tela inicial + Não foi possível conectar. Esquema de URL não reconhecível. @@ -546,8 +560,6 @@ Nova aba Procurar na página - - Abas sincronizadas Lista de leitura @@ -592,6 +604,15 @@ Após um mês sem uso + + + Iniciar na tela inicial + + Após quatro horas + + Sempre + + Nunca Fechar manualmente @@ -1530,7 +1551,7 @@ Proteja suas contas e senhas - Configure um desenho de bloqueio, código PIN ou senha para proteger o acesso a suas contas e senhas salvas, caso outras pessoas usem seu dispositivo. + Configure um método de bloqueio do dispositivo (desenho, código PIN ou senha) para proteger o acesso a suas contas e senhas salvas, caso outras pessoas usem seu dispositivo. Mais tarde @@ -1573,6 +1594,10 @@ Número do cartão Data de validade + + Mês da data de validade + + Ano da data de validade Nome no cartão @@ -1594,6 +1619,24 @@ Digite um número de cartão de crédito válido + + Preencha este campo + + Desbloqueie para ver seus cartões salvos + + Proteja seus cartões de crédito + + Configure um método de bloqueio do dispositivo (desenho, código PIN ou senha) para proteger o acesso a seus cartões de crédito salvos, caso outras pessoas usem seu dispositivo. + + Configurar agora + + Mais tarde + + Desbloqueie seu dispositivo + + + Desbloqueie para usar informações armazenadas de cartões de crédito + Adicionar mecanismo de pesquisa diff --git a/app/src/main/res/values-pt-rPT/strings.xml b/app/src/main/res/values-pt-rPT/strings.xml index 30c521ed1..e94c9d9a8 100644 --- a/app/src/main/res/values-pt-rPT/strings.xml +++ b/app/src/main/res/values-pt-rPT/strings.xml @@ -94,13 +94,6 @@ Dispensar - - Altere a disposição dos separadores abertos. Aceda às configurações e selecione grelha sob vista de separadores. - - Ir para as definições - - Ignorar - Novo separador @@ -184,6 +177,10 @@ Editar + + + Ecrã inicial + Não foi possível ligar. Esquema do endereço não reconhecido. @@ -413,6 +410,11 @@ and the third is the device model. --> %1$s no %2$s %3$s + + Cartões de crédito + + Moradas + Separadores recebidos @@ -543,8 +545,6 @@ Novo separador Localizar na página - - Separadores sincronizados Lista de leitura @@ -590,6 +590,15 @@ Depois de um mês + + + Começar no ecrã inicial + + Depois de quatro horas + + Sempre + + Nunca Fechar manualmente @@ -1455,10 +1464,8 @@ Preenchimento automático Sincronização de credenciais - - Ativada - - Desativada + + Sincronizar credenciais entre dispositivos Voltar a ligar @@ -1559,6 +1566,8 @@ Os dados são encriptados Sincronizar cartões entre dispositivos + + Sincronizar cartões Adicionar cartão de crédito @@ -1572,6 +1581,10 @@ Número do cartão Data de expiração + + Mês da data de expiração + + Ano da data de expiração Nome no cartão @@ -1590,6 +1603,25 @@ Cartões guardados + + Por favor, introduza um número de cartão de crédito válido + + Por favor preencha este campo + + Desbloquear para ver os cartões guardados + + Proteja os seus cartões de crédito + + Configure um padrão, PIN ou palavra-passe de bloqueio do dispositivo para impedir que os seus cartões de crédito guardados sejam acedidos por outra pessoa que tenha acesso ao seu dispositivo. + + Configurar agora + + Mais tarde + + Desbloquear o seu dispositivo + + Desbloquear para utilizar as informações de cartão de crédito armazenadas + Adicionar motor de pesquisa @@ -1758,4 +1790,10 @@ Clique para mais detalhes - + + Navegar para cima + + + Fechar + + diff --git a/app/src/main/res/values-rm/strings.xml b/app/src/main/res/values-rm/strings.xml index f4fa3590a..4ef2d5291 100644 --- a/app/src/main/res/values-rm/strings.xml +++ b/app/src/main/res/values-rm/strings.xml @@ -1594,6 +1594,22 @@ Endatescha per plaschair in numer da carta da credit valid + + Debloccar per vesair tias cartas memorisadas + + Protegia tias cartas da credit + + Endrizza in muster per bloccar l\'apparat, in PIN u pled-clav per evitar ch\'ina autra persuna possia acceder a tias cartas da credit memorisadas sch\'ella ha tes apparat. + + Ussa endrizzar + + Pli tard + + Debloccar tes apparat + + + Debloccar per utilisar las datas da cartas da credit memorisadas + Agiuntar ina maschina da tschertgar diff --git a/app/src/main/res/values-ro/strings.xml b/app/src/main/res/values-ro/strings.xml index 38af6b4ac..5ed50ab50 100644 --- a/app/src/main/res/values-ro/strings.xml +++ b/app/src/main/res/values-ro/strings.xml @@ -68,14 +68,6 @@ Nu, mulțumesc - - - Accesează Firefox mai repede. Adaugă un widget pe ecranul de start. - - Adaugă widget - - Nu acum - Filă nouă @@ -124,8 +116,6 @@ Caută în pagină Filă privată - - Filă nouă Salvează în colecție @@ -187,7 +177,6 @@ Află mai multe - Căutare @@ -306,6 +295,9 @@ Notificări + + Numele colecției + Sincronizează acum @@ -371,9 +363,6 @@ Află mai multe - - Dezactivat la nivel global, intră în Setări pentru activare. - Telemetrie @@ -451,8 +440,8 @@ Istoric - - File sincronizate + + Caută în pagină Listă de lectură @@ -526,7 +515,7 @@ Deschide filele - Șterge + Șterge %1$s (mod privat) @@ -572,13 +561,11 @@ Fără istoric - - - Nu există descărcări aici %1$d selectate + Ne cerem scuze. %1$s nu poate încărca pagina. @@ -612,8 +599,6 @@ %1$s șters Adaugă dosarul - - Marcaj creat. Marcaj salvat! @@ -713,15 +698,15 @@ Activată Dezactivată - + Permite audio și video Blochează audio și video numai pe date celulare Audio și video se vor reda pe Wi-Fi - + Blochează numai audio - + Blochează audio și video Activat @@ -972,9 +957,6 @@ Bine ai venit pe %s! Ai deja un cont? - - Descoperă %s Vezi ce e nou Obține răspunsuri aici - - Începe să sincronizezi marcaje, parole și multe altele din contul Firefox. - - Află mai multe - - Ești autentificat(ă) ca %s de pe un alt browser Firefox de pe acest telefon. Vrei să te autentifici cu acest cont? Da, conectează-mă Autentificare… - - Intră în contul Firefox Rămâi deconectat Sync este activat Eroare de autentificare - - Confidențialitate automată - - Setările de confidențialitate și securitate blochează elementele de urmărire, softurile rău-intenționate și firmele care te urmăresc. Standard (implicit) - - Blochează mai puține elemente de urmărire. Paginile se vor încărca normal. Strictă (recomandat) Strictă - - Blochează mai multe elemente de urmărire, reclame și ferestre pop-up. Paginile se încarcă mai repede, dar se poate ca unele funcționalități să nu meargă. - - Ia o poziție - - Încearcă navigarea cu o singură mână folosind bara de unelte de jos sau mut-o în partea de sus. Navighează privat Confidențialitatea ta - - Am proiectat %s să îți dea control asupra a ceea ce partajezi - online și ce partajezi cu noi. Citește notificarea noastră privind confidențialitatea @@ -1051,8 +1004,6 @@ Alege o temă - - Economisește consumul bateriei și protejează-ți ochii prin activarea modului întunecat. Automat @@ -1105,14 +1056,10 @@ Află mai multe Standard (implicit) - - Blochează mai puține elemente de urmărire. Paginile se vor încărca normal. Ce blochează protecția standard împotriva urmăririi Strictă - - Blochează mai multe elemente de urmărire, reclame și ferestre pop-up. Paginile se încarcă mai repede, dar se poate ca unele funcționalități să nu meargă. Ce blochează protecția strictă împotriva urmăririi @@ -1233,9 +1180,6 @@ Denumire comandă rapidă - - Poți adăuga cu ușurință acest site web în ecranul de pornire al telefonului pentru acces instant și o navigare mai rapidă, ca și cum ai fi într-o aplicație. - Date de autentificare și parole @@ -1248,10 +1192,6 @@ Completare automată Sincronizează datele de autentificare - - Activat - - Dezactivat Reconectare @@ -1462,7 +1402,7 @@ Există un set de date de autentificare cu acest nume de utilizator - + Conectează alt dispozitiv. Te rugăm să te autentifici din nou. @@ -1481,11 +1421,13 @@ A fost atinsă limita de site-uri de top - - Pentru a adăuga un site de top nou, trebuie să elimini unul existent. Ține degetul pe denumirea site-ului pentru selectare și apoi atinge „Elimină”. Ok, am înțeles + + Nume + Elimină - + + diff --git a/app/src/main/res/values-ru/strings.xml b/app/src/main/res/values-ru/strings.xml index 924d20dbe..f81814fdb 100644 --- a/app/src/main/res/values-ru/strings.xml +++ b/app/src/main/res/values-ru/strings.xml @@ -6,6 +6,7 @@ Приватный %s %s (Приватно) + Другие настройки @@ -38,8 +39,6 @@ Выберите коллекцию Выйти из режима множественного выбора - - Закрыть экран вкладок Сохранить выбранные вкладки в коллекцию @@ -53,8 +52,18 @@ Выбрано + + + Недавно добавленные + + Недавно добавленные закладки + + Показать все + + Показать все добавленные закладки + - %1$s разработан @fork-maintainers. + %1$s разработан Mozilla. @@ -101,13 +110,6 @@ Пропустить - - Измените отображение открытых вкладок. Перейдите в настройки и выберите «Сеткой» в секции «Просмотр вкладок». - - Перейти в настройки - - Закрыть - Новая вкладка @@ -117,6 +119,12 @@ Топ сайтов + + + Перейти обратно в + + Показать все + Открытые вкладки @@ -195,6 +203,10 @@ Изменить + + + Домашний экран + Ошибка подключения. Не удалось распознать схему URL. @@ -319,10 +331,6 @@ Домой Жесты - - Панель вкладок - - Плавающая кнопка действия (ПКД) Персонализация @@ -361,13 +369,9 @@ Поиск облачных вкладок Настройки Аккаунта + Автозаполнение URL - - Настройка источника пользовательских дополнений - - Поиск дополнений - Открывать ссылки в приложениях @@ -537,13 +541,13 @@ - Потянуть, чтобы обновить + Потяните, чтобы обновить - Прокрутить страницу, чтобы скрыть панель инструментов + Прокрутите страницу, чтобы скрыть панель инструментов - Провести в сторону по панели инструментов, чтобы переключить вкладки + Проведите в сторону по панели инструментов, чтобы переключить вкладки - Провести вверх по панели инструментов, чтобы открыть вкладки + Проведите вверх по панели инструментов, чтобы открыть вкладки @@ -568,8 +572,6 @@ Новая вкладка Найти на странице - - Облачные вкладки Список для чтения @@ -615,6 +617,15 @@ Через месяц + + + Запускать на домашнем экране + + Через четыре часа + + Всегда + + Никогда Закрывать вручную @@ -1262,23 +1273,6 @@ Строгая - Блокирует больше трекеров, рекламы и всплывающих окон. Страницы будут грузиться быстрее, но часть функций может не работать. - - Выберите макет панели вкладок - - Выберите, либо старый стиль экрана вкладок Firefox (Fennec), либо панель вкладок нового стиля (Fenix). - - Старый стиль Fennec (по умолчанию) - - Щелчок по счётчику вкладок на панели инструментов покажет вам экран вкладок с макетом, похожим на предыдущую (Fennec) версию Firefox. - - Новый стиль Fenix - - Щелчок по счётчику вкладок на панели инструментов покажет вам новый макет панели вкладок из Fenix версии Firefox. - - Сделайте выбор Блокирует больше трекеров, так что страницы загружаются быстрее, но некоторые страницы могут работать некорректно. Выберите размещение панели инструментов @@ -1546,10 +1540,6 @@ Имя пользователя Пароль - - Убрать HTTP/HTTPS/WWW из URL-адресов - - Удалять HTTP/HTTPS/WWW из URL-адресов на панели инструментов и в области вкладок Введите ваш PIN-код ещё раз @@ -1634,6 +1624,10 @@ Номер карты Срок действия + + Месяц срока действия + + Год срока действия Имя держателя @@ -1654,6 +1648,23 @@ Пожалуйста, введите корректный номер карты + + Пожалуйста, заполните это поле + + Разблокируйте, чтобы просмотреть сохранённые карты + + Защитите свои банковские карты + + Настройте графический ключ, PIN-код или пароль для блокировки устройства, чтобы защитить сохранённые банковские карты, если кто-либо ещё получит доступ к вашему устройству. + + Настроить сейчас + + Позже + + Разблокируйте своё устройство + + Разблокируйте, чтобы использовать сохранённые данные банковской карты + Добавление поисковой системы @@ -1803,35 +1814,6 @@ Показывать самые посещаемые сайты - - Установить пользовательскую учетную запись дополнений - - Установить собственную коллекцию дополнений - - - Настроить поведение системы - - Приостанавливать вкладки, чтобы их не убили ради памяти - - Если эта функция включена, то при нехватке памяти в системе вкладки будут приостановлены, а состояние страницы будет потеряно. - - - Включить компактные вкладки - - Включить верхнюю панель вкладок - - Включить полноэкранный экран вкладок - - Обратный порядок вкладок в панели вкладок - - Включите, чтобы помещать новые вкладки в начало списка вкладок, отключите, чтобы помещать новые вкладки в конец списка вкладок - - Включить ПКД для новой вкладки - - Поместить ПКД вверху - - Разрешить размещать кнопку для новой вкладки вверху, отключите, чтобы разместить её внизу - Имя diff --git a/app/src/main/res/values-sat/strings.xml b/app/src/main/res/values-sat/strings.xml index 2463204b4..bc41119ea 100644 --- a/app/src/main/res/values-sat/strings.xml +++ b/app/src/main/res/values-sat/strings.xml @@ -4,6 +4,7 @@ ᱯᱨᱟᱭᱣᱮᱴ %s %s (ᱯᱨᱟᱭᱣᱮᱴ) + ᱰᱷᱮᱨ ᱮᱴᱟᱜᱟᱜ @@ -44,6 +45,15 @@ ᱵᱟᱪᱷᱟᱣᱮᱱᱟ + + + ᱱᱤᱛᱜᱮ ᱥᱟᱺᱪᱟᱣ ᱟᱠᱟᱱᱟ + + + ᱱᱮᱛᱚᱜ ᱜᱮ ᱥᱟᱺᱪᱟᱣ ᱟᱠᱟᱱ ᱵᱩᱠᱢᱟᱨᱠ ᱠᱚ + + ᱡᱷᱚᱛᱚ ᱫᱮᱠᱷᱟᱣ ᱢᱮ + %1$s ᱛᱮᱭᱟᱨ ᱦᱩᱭ ᱠᱟᱱᱟ ᱢᱳᱡᱤᱞᱟ ᱫᱟᱨᱟᱭᱛᱮ ᱾ @@ -91,13 +101,6 @@ ᱵᱟᱹᱰ - - ᱠᱷᱩᱞᱟᱹ ᱴᱮᱵ ᱞᱮᱭᱟᱩᱴ ᱠᱚ ᱵᱚᱫᱚᱞ ᱢᱮ ᱾ ᱥᱟᱡᱟᱣ ᱴᱷᱮᱱ ᱪᱟᱞᱟᱣ ᱠᱟᱛᱮᱫᱽ ᱴᱮᱵᱽ ᱣᱤᱣ ᱞᱟᱛᱟᱨ ᱨᱮ ᱜᱨᱤᱰ ᱵᱟᱪᱷᱟᱣ ᱢᱮ ᱾ - - ᱥᱟᱡᱟᱣ ᱛᱮ ᱪᱟᱞᱟᱜᱽ ᱢᱮ - - ᱵᱚᱸᱫᱽ - ᱱᱟᱶᱟ ᱴᱮᱵᱽ @@ -529,8 +532,6 @@ ᱮᱴᱟᱜᱟ ᱵᱩᱠᱢᱟᱨᱠ ᱠᱚ ᱱᱟᱜᱟᱢ - - ᱥᱭᱸᱠᱼᱰ ᱴᱮᱵᱽ ᱠᱚ ᱯᱟᱲᱦᱟᱣ ᱞᱤᱥᱴᱤ diff --git a/app/src/main/res/values-sk/strings.xml b/app/src/main/res/values-sk/strings.xml index a8da36f25..97d9edcdc 100644 --- a/app/src/main/res/values-sk/strings.xml +++ b/app/src/main/res/values-sk/strings.xml @@ -1599,6 +1599,21 @@ Prosím, zadajte platné číslo platobnej karty + + Odomknutím zobrazíte svoje uložené kreditné karty + + Zabezpečte svoje kreditné karty + + Nastavte si vzor, kód alebo heslo, ktorým ochránite svoje uložené kreditné karty v prípade, že vaše zariadenie bude používať niekto iný. + + Nastaviť teraz + + Neskôr + + Odomknite svoje zariadenie + + Odomknutím použijete uložené informácie o kreditnej karte + Pridať vyhľadávací modul diff --git a/app/src/main/res/values-sl/strings.xml b/app/src/main/res/values-sl/strings.xml index f3ff182a1..88f22dfda 100644 --- a/app/src/main/res/values-sl/strings.xml +++ b/app/src/main/res/values-sl/strings.xml @@ -4,6 +4,7 @@ Zasebni %s %s (zasebno) + Več možnosti @@ -49,6 +50,14 @@ Izbrano + + + Nedavno shranjeno + + Nedavno shranjeni zaznamki + + Prikaži vse + %1$s izdeluje Mozilla. @@ -94,13 +103,6 @@ Zapri - - Spremenite postavitev odprtih zavihkov. Pojdite v nastavitve in v pogledu zavihkov izberite mrežo. - - Pojdi v nastavitve - - Skrij - Nov zavihek @@ -110,6 +112,9 @@ Glavne strani + + Prikaži vse + Odprti zavihki @@ -184,6 +189,10 @@ Uredi + + + Domači zaslon + Povezava ni mogoča. Neprepoznavna URL shema. @@ -552,8 +561,6 @@ Nov zavihek Najdi na strani - - Sinhronizirani zavihki Bralni seznam @@ -598,6 +605,15 @@ Po enem mesecu + + + Začni na domačem zaslonu + + po štirih urah + + vedno + + nikoli Zapri ročno @@ -1465,6 +1481,8 @@ Samodejno izpolnjevanje Sinhronizacija prijav + + Sinhroniziraj prijave med napravami Ponovno poveži @@ -1567,6 +1585,8 @@ Podatki so šifrirani Sinhroniziraj kartice med napravami + + Sinhroniziraj kartice Dodaj kreditno kartico @@ -1580,6 +1600,10 @@ Številka kartice Datum poteka + + Mesec izteka veljavnosti + + Leto izteka veljavnosti Ime na kartici @@ -1601,6 +1625,21 @@ Vnesite veljavno številko kreditne kartice + + Izpolnite to polje + + Odklenite za ogled shranjenih kartic + + Zavarujte svoje kreditne kartice + + Nastavite vzorec za zaklepanje naprave, PIN ali geslo za zaščito pred dostopom do kreditnih kartic, če vašo napravo uporablja še kdo. + + Nastavi zdaj + + Pozneje + + Odklenite svojo napravo + Dodaj iskalnik diff --git a/app/src/main/res/values-sq/strings.xml b/app/src/main/res/values-sq/strings.xml index fa1e32869..46f3f7cf7 100644 --- a/app/src/main/res/values-sq/strings.xml +++ b/app/src/main/res/values-sq/strings.xml @@ -91,13 +91,6 @@ Hidhe tej - - Ndryshoni skemën e skedave të hapura. Shkoni te rregullimet dhe përzgjidhni rrjetë nën pamjen skeda. - - Shko te rregullimet - - Hidhe tej - Skedë e re @@ -182,6 +175,10 @@ Përpunoni + + + Skena e kreut + S’arrihet të lidhet. Skemë URL jo e pranuar. @@ -412,6 +409,11 @@ and the third is the device model. --> %1$s në %2$s %3$s + + Karta krediti + + Adresa + Skeda të marra @@ -538,8 +540,6 @@ Skedë e re Gjej në faqe - - Skeda të njëkohësuara Listë Leximesh @@ -584,6 +584,15 @@ Pas një muaji + + + Fillo me kreun + + Pas katër orësh + + Përherë + + Kurrë Mbylleni dorazi @@ -1563,6 +1572,10 @@ Numër Karte Datë Skadimi + + Muaj Date Skadimi + + Vit Date Skadimi Emër në Kartë @@ -1583,6 +1596,23 @@ Ju lutemi, jepni një numër të vlefshëm karte krediti + + Ju lutemi, plotësojeni këtë fushë + + Që të shihni kartat tuaja të ruajtura, shkyçeni + + Siguroni kartat tuaja të kreditit + + Ujdisni një rregullsi, PIN ose fjalëkalim kyçjeje pajisjeje për të mbrojtur nga hyrja në to kartat tuaja kreditit të ruajturar, nëse pajisjen tuaj e ka dikush tjetër. + + Ujdiseni tani + + Më vonë + + Shkyçni pajisjen tuaj + + Që të përdorni të dhëna karte krediti të depozituara, shkyçeni + Shtoni motor kërkimesh @@ -1752,4 +1782,10 @@ Klikoni për më tepër hollësi - + + Lëvizni për sipër + + + Mbylle + + diff --git a/app/src/main/res/values-sr/strings.xml b/app/src/main/res/values-sr/strings.xml index 1dec857e9..f3e477272 100644 --- a/app/src/main/res/values-sr/strings.xml +++ b/app/src/main/res/values-sr/strings.xml @@ -5,6 +5,7 @@ Приватни %s %s (Приватни режим) + Више опција @@ -20,10 +21,6 @@ Ваши приватни језичци биће приказани овде. - - Baidu - - JD 1 отворен језичак. Додирните за пребацивање језичака. @@ -52,6 +49,16 @@ Изабрано + + + Недавно сачувано + + Недавно сачувани обележивачи + + Прикажи све + + Прикажи дугме свих сачуваних обележивача + %1$s производи @fork-maintainers. @@ -95,13 +102,6 @@ Одбаци - - Промените приказ отворених језичака. Идите у подешавања и одаберите мрежу под приказом језичака. - - Иди у подешавања - - Одбаци - Нови језичак @@ -111,6 +111,12 @@ Популарне странице + + + Скочи назад + + Прикажи све + Отворени језичци @@ -181,6 +187,15 @@ Прилагоди приказ за читање + + Додај + + Уреди + + + + Почетни екран + Није могуће повезивање. Непозната URL шема. @@ -411,6 +426,11 @@ and the third is the device model. --> %1$s на %2$s %3$s + + Кредитне картице + + Адресе + Примљени језичци @@ -441,9 +461,6 @@ Сазнајте више - - Искључено је глобално, за укључивање идите на Подешавања. - Телеметрија @@ -454,6 +471,8 @@ Маркетиншки подаци Дели податке о функцијама које користите у апликацији %1$s са Leanplum-ом, нашим провајдером мобилног маркетинга. + + Подели податке о основном коришћењу са фирмом Adjust, нашим сарадником за маркетинг Студије @@ -542,8 +561,6 @@ Нови језичак Пронађи на страници - - Синхронизовани језичци Списак за читање @@ -588,6 +605,15 @@ После једног месеца + + + Покрени се на почетном екрану + + После четири сата + + Увек + + Никада Затвори ручно @@ -604,12 +630,16 @@ Приватна сесија Приватни језичци + + Синхронизовани језичци Додај језичак Додај приватни језичак Приватно + + Синхронизација Отворени језичци @@ -620,6 +650,8 @@ Дели све језичке Недавно затворени језичци + + Подешавања налога Подешавања језичака @@ -789,8 +821,6 @@ %1$s избрисано Додај фасциклу - - Забелешка је направљена. Забелешка је сачувана! @@ -975,6 +1005,8 @@ Све радње Недавно затворено + + Синхронизација Пријави се на Sync @@ -1167,9 +1199,6 @@ Добро дошли у апликацију %s! Већ имате налог? - - Упознајте се са апликацијом %s Погледајте шта је ново @@ -1178,10 +1207,10 @@ Имате питање о новом дизајну апликације %s? Желите ли да знате шта је промењено? Овде потражите одговоре - - Почните са синхронизовањем забелешки, лозинки и других делова са вашим Firefox налогом. + + Синхронизујте Firefox на више уређаја - Сазнајте више + Пребаците обележиваче, историју и лозинке у Firefox на овом уређају. @@ -1190,8 +1219,8 @@ Да, пријави ме Пријава у току - - Пријава у Firefox + + Пријави се Остави ме пријављеног @@ -1200,26 +1229,23 @@ Неуспех при пријављивању - Аутоматска приватност - - Подешавања приватности и безбедности блокирају трагаче, злонамерни софтвер и компаније које вас прате. + Увек укључена приватност + + Firefox самостално спречава тајно праћење на вебу. Стандардно (подразумевано) - Блокира мање пратилаца. Странице ће се нормално учитавати. + Уравнотежена приватност и перформансе. Странице се учитавају уобичајено. Строго (препоручено) Строго - Блокира више пратилаца, огласа и скочних прозора. Странице се учитавају брже, али неке функције можда неће радити. - - Одлучите се + Блокира више пратилаца те се странице учитавају брже али неке могућности на страници можда неће радити. + + Изаберите положај алатнице - Пробајте прегледати једном руком с доњом алатном траком или је померите према горе. + Постави алатницу на дохват руке. Било на дну или на врху. Прегледајте приватно Ваша приватност + The first parameter is the name of the app (e.g. Firefox Preview) Substitute %s for long browser name. --> Дизајнирали смо %s тако да имате пуну контролу над оним што делите на мрежи и са нама. Прочитајте наше обавештење о приватности @@ -1247,7 +1273,7 @@ Изаберите вашу тему - Штедите батерију и сачувајте вид укључивањем тамног режима. + Сачувајте нешто батерије и ваш вид са тамном темом. Самостално @@ -1305,13 +1331,13 @@ Стандардно (подразумевано) - Блокира мање пратилаца. Странице ће се нормално учитавати. + Уравнотежена приватност и перформансе. Странице се учитавају уобичајено. Шта се блокира стандардном заштитом од праћења Строго - Блокира више пратилаца, огласа и скочних прозора. Странице се учитавају брже, али неке функције можда неће радити. + Блокира више пратилаца те се странице учитавају брже али неке могућности на страници можда неће радити. Шта се блокира строгом заштитом од праћења @@ -1454,10 +1480,8 @@ Самостално попуњавање Синхронизуј пријаве - - Укључено - - Искључено + + Усклади пријаве на свим уређајима Поново повежи @@ -1559,9 +1583,61 @@ Подаци су шифровани Синхронизуј картице на уређајима + + Синхронизуј картице Додај кредитну картицу + + Управљај сачуваним картицама + + Додај картицу + + Уреди картицу + + Број картице + + Датум истека + + Месец истека + + Година истека + + Име на картици + + Надимак картице + + Обриши картицу + + Обриши картицу + + Сачувај + + Сачувај + + Откажи + + Сачуване картице + + Унесите исправан број кредитне картице + + Попуните ово поље + + Откључај за приказ сачуваних картица + + Обезбедите ваше кредитне картице + + Поставите шаблон закључавања уређаја, ПИН или лозинку да бисте заштитили ваше сачуване кредитне картице од неовлашћеног приступа. + + Подеси сада + + Касније + + Откључајте ваш уређај + + + Откључај за употребу сачуваних кредитних картица + Додај претраживач @@ -1721,23 +1797,19 @@ Откажи + + Подешава самостално отварање адреса са страница, мејлова и порука унутар Firefox-a. + Уклони - - Искористите %s у потпуности. - Кликните за више детаља - - Сакупљајте ствари које су вам важне - - Групишите сличне претраге, странице и језичке за брз приступ касније. - - Пријављени сте као %s у другом Firefox прегледачу, на овом телефону. Желите ли да се пријавите са тим налогом? - - Ову страницу можете лако додати на почетни екран вашег телефона за тренутни приступ и брже прегледање. + + Иди нагоре + + + Затвори - + diff --git a/app/src/main/res/values-su/strings.xml b/app/src/main/res/values-su/strings.xml index 117a4f63d..323ba7947 100644 --- a/app/src/main/res/values-su/strings.xml +++ b/app/src/main/res/values-su/strings.xml @@ -90,13 +90,6 @@ Tutup - - Ngarobah perenah tab anu maruka. Buka setélan tur pilih grid handapeun témbongan tab. - - Buka setélan - - Tutup - Tab anyar @@ -182,6 +175,10 @@ Ropéa + + + Layar tepas + Teu bisa nyambung. Skéma URL teu dipikawanoh. @@ -416,6 +413,11 @@ and the third is the device model. --> %1$s dina %2$s %3$s + + Kartu kiridit + + Alamat + Tab nu katampa @@ -447,9 +449,6 @@ Lenyepan - - Dipareuman sacara global, buka Setélan pikeun ngahurungkeun. - Telemétri @@ -460,6 +459,8 @@ Data pamasaran Bagikeun data ngeunaan fitur naon baé anu dipaké di %1$s ka Leanplum, péndor pamasaran ider kami. + + Bagikeun data pamakéan dasar ka Adjust, péndor pamasaran ider kami Studi @@ -547,8 +548,6 @@ Tab anyar Téangan dina kaca - - Tab singkron Daptar Bacaeun @@ -594,6 +593,15 @@ Sanggeus sabulan + + + Mimitian di tepas + + Sanggeus opat jam + + Matuh + + Ulah Tutup manual @@ -800,8 +808,6 @@ Mupus %1$s Tambah map - - Markah dijieun. Markah diteundeun! @@ -1466,10 +1472,8 @@ Eusi otomatis Singkronkeun login - - Hurung - - Pareum + + Singkronkeun login di sakabéh parabot Sambungkeun deui @@ -1570,6 +1574,8 @@ Data diénkrip Singkronkeun kartu di sakabeh parabot + + Singkronkeun kartu Tambah kartu kiridit @@ -1583,6 +1589,10 @@ Nomer Kartu Tanggal Kadaluarsa + + Bulan Kadaluwarsa + + Taun Kadaluwarsa Ngaran dina Kartu @@ -1600,6 +1610,25 @@ Kartu disimpen + + Mangga lebetkeun nomer kartu kiridit anu sah + + Mangga eusian kolom ieu + + Buka konci pikeun nempo kartu anu diteundeun + + Amankeun kartu kiridit anjeun + + Jieun pola konci paranti, PIN, atawa kecap sandi pikeun ngajaga kartu kiridit anu diteundeun bisi paranti anjeun dipaké batur. + + Setél ayeuna + + Engké deui + + Buka konci paranti anjeun + + Buka konci pikeun nganggo inpormasi kartu kiridit anu disimpen + Tambah mesin pamaluruh @@ -1767,20 +1796,13 @@ Piceun - - Maksimalkeun %s. - Pencét sangkan leuwih écés - - Kumpulkeun hal anu penting pikeun anjeun - - Ngagabungkeun pamaluruhan, loka sareng tab anu sami pikeun aksés gancang engké. - - Anjeun asup salaku %s dina séjén panyungsi Firefox di ieu telepon. Anjeun rék asup maké ieu akun? - - Anjeun bisa kalawan gampang nambahkeun ieu raramatloka kana layar Tepas ponsél pikeun aksés instan sarta maluruh leuwih gancang kawas muka aplikasi. + + Pindah ka luhur + + + Tutup - + diff --git a/app/src/main/res/values-sv-rSE/strings.xml b/app/src/main/res/values-sv-rSE/strings.xml index f18b8ba38..7b79187f4 100644 --- a/app/src/main/res/values-sv-rSE/strings.xml +++ b/app/src/main/res/values-sv-rSE/strings.xml @@ -5,6 +5,7 @@ Privat %s %s (Privat) + Fler alternativ @@ -48,6 +49,16 @@ Markerad + + + Nyligen sparade + + Nyligen sparade bokmärken + + Visa alla + + Visa knappen alla sparade bokmärken + %1$s produceras av Mozilla. @@ -95,13 +106,6 @@ Ignorera - - Ändra layouten för öppna flikar. Gå till inställningar och välj rutnät under flikvy. - - Gå till Inställningar - - Ignorera - Ny flik @@ -111,6 +115,12 @@ Mest besökta + + + Hoppa tillbaka + + Visa alla + Öppna flikar @@ -188,6 +198,10 @@ Redigera + + + Startsidan + Kan inte ansluta. Oigenkännligt URL-schema. @@ -555,8 +569,6 @@ Ny flik Hitta på sidan - - Synkade flikar Läslista @@ -602,6 +614,15 @@ Efter en månad + + + Börja på startsidan + + Efter fyra timmar + + Alltid + + Aldrig Stäng manuellt @@ -1587,6 +1608,10 @@ Kortnummer Utgångsdatum + + Utgångsdatum månad + + Utgångsdatum år Namn på kort @@ -1608,6 +1633,24 @@ Ange ett giltigt kreditkortsnummer + + Fyll i det här fältet + + Lås upp för att se dina sparade kreditkort + + Säkra dina kreditkort + + Konfigurera enhetens låsmönster, PIN eller lösenord för att skydda dina sparade kreditkort från åtkomst om någon annan har din enhet. + + Konfigurera nu + + Senare + + Lås upp din enhet + + + Lås upp för att använda lagrad kreditkortsinformation + Lägg till sökmotor diff --git a/app/src/main/res/values-szl/strings.xml b/app/src/main/res/values-szl/strings.xml index 2b53bb194..158e06588 100644 --- a/app/src/main/res/values-szl/strings.xml +++ b/app/src/main/res/values-szl/strings.xml @@ -347,4 +347,105 @@ Ôtwiyrej linki w aplikacyjach + + Zewnyntrzny menedżer pobiyranio + + Rozszyrzynia + + Powiadōmiynia + + + + Włosno kolekcyjo rozszyrzyń + + OK + + Pociep + + Miano kolekcyje + + Posiedziciel kolekcyje (ID ôd używocza) + + + + Kolekcyjo rozszyrzyń je zmiyniōno. Wyłōnczynie aplikacyji, coby przidać zmiany… + + + + Rozszyrzynie niy ma ôbsugowane + + Rozszyrzynie je już zainstalowane + + + + Synchrōnizuj teroz + + Ôbier, co synchrōnizować + + Historyjo + + Zokłodki + + Dane logowanio + + Ôtwarte karty + + Wyloguj + + Miano masziny + + Miano masziny niy śmiy być prōżne. + + Synchrōnizacyjo… + + Synchronizacyjo sie niy podarziła. Ôstatnio udano: %s + + Synchronizacyjo sie niy podarziła. Ôstatnio udano: żodno + + Ôstatnio synchrōnizacyjo: %s + + Ôstatnio synchrōnizacyjo: żodno + + %1$s na %2$s %3$s + + Kredytowe karty + + Adresy + + + + Przijynte karty + + Powiadōmiynia ô kartach przijyntych z inkszych maszin z aplikacyjōm Firefox. + + Karta je przijynto + + Karty sōm przijynte + + Karty ze %s + + + + Ôchrōna ôd śledzynio + + Ôchrōna ôd śledzynio + + Szperuj zawartość i skrypty, co cie śledzōm w necu + + Wyjōntki + + Na tych strōnach ôchrōna ôd śledzynio je wyłōnczōno + + Załōncz do wszyskich strōn + + Z wyjōntkami możesz zastawić ôchrōna ôd śledzynio na ôbranych strōnach. + + Przewiydz sie wiyncyj + + + Telemetryjo + + diff --git a/app/src/main/res/values-tg/strings.xml b/app/src/main/res/values-tg/strings.xml index a245a087f..380a40cae 100644 --- a/app/src/main/res/values-tg/strings.xml +++ b/app/src/main/res/values-tg/strings.xml @@ -94,13 +94,6 @@ Нодида гузарондан - - Тарҳбандиро барои варақаҳои кушодашуда иваз намоед. Ба танзимот гузаред ва дар зери намоиши варақаҳо панҷараро интихоб намоед. - - Гузариш ба танзимот - - Нодида гузарондан - Варақаи нав @@ -184,6 +177,10 @@ Таҳрир кардан + + + Экрани асосӣ + Пайваст нашуд. Нақшаи URL шинохтанашаванда аст. @@ -543,8 +540,6 @@ Варақаи нав Ҷустуҷӯ дар саҳифа - - Варақаҳои ҳамоҳангшуда Рӯйхати хониш @@ -590,6 +585,15 @@ Пас аз як моҳ + + + Оғоз дар экрани асосӣ + + Пас аз чор соат + + Ҳамеша + + Ҳеҷ гоҳ Ба таври дастӣ пӯшидан @@ -1572,6 +1576,10 @@ Рақами корт Санаи анҷоми муҳлат + + Моҳи санаи анҷоми муҳлат + + Соли санаи анҷоми муҳлат Ном дар корт @@ -1594,6 +1602,23 @@ Лутфан, рақами корти кредитии дурустро ворид намоед + + Лутфан, ин майдонро пур кунед + + Барои дидани кортҳои нигоҳдошташуда, қулфро кушоед + + Кортҳои кредитии худро муҳофизат кунед + + Барои муҳофизат кардани кортҳои кредитии нигоҳдошташудаи худ аз дастрасии озод, агар касе дигар аз дастгоҳи шумо истифода барад, шаклвораи қулфи экран, рамзи PIN ё ниҳонвожаеро барои дастгоҳи худ танзим намоед. + + Ҳозир насб кунед + + Дертар + + Қулфи дастгоҳи худро кушоед + + Барои истифодаи маълумоти кортҳои кредитии нигоҳдошташуда, қулфро кушоед + Илова кардани низоми ҷустуҷӯӣ diff --git a/app/src/main/res/values-th/strings.xml b/app/src/main/res/values-th/strings.xml index 2ee95d0d1..07cdb2268 100644 --- a/app/src/main/res/values-th/strings.xml +++ b/app/src/main/res/values-th/strings.xml @@ -4,6 +4,7 @@ %s ส่วนตัว %s (ส่วนตัว) + ตัวเลือกเพิ่มเติม @@ -47,6 +48,12 @@ เลือกแล้ว + + + บันทึกไว้ล่าสุด + + แสดงหมด + %1$s ผลิตขึ้นโดย Mozilla @@ -91,13 +98,6 @@ ยกเลิก - - เปลี่ยนเค้าโครงของแท็บที่เปิดอยู่ ไปยังการตั้งค่าแล้วเลือกเส้นตารางภายใต้มุมมองแท็บ - - ไปยังการตั้งค่า - - ปิด - แท็บใหม่ @@ -107,6 +107,12 @@ ไซต์เด่น + + + กลับเข้าไป + + แสดงหมด + แท็บที่เปิดอยู่ @@ -182,6 +188,10 @@ แก้ไข + + + หน้าแรก + ไม่สามารถเชื่อมต่อได้เนื่องจากเป็นรูปแบบ URL ที่ไม่รู้จัก @@ -412,6 +422,11 @@ and the third is the device model. --> %1$s บน %2$s %3$s + + บัตรเครดิต + + ที่อยู่ + แท็บที่ได้รับ @@ -443,9 +458,6 @@ เรียนรู้เพิ่มเติม - - ปิดใช้งานสำหรับทุกไซต์แล้ว ให้ไปที่การตั้งค่าเพื่อเปิด - การวัดและส่งข้อมูลทางไกล @@ -456,6 +468,8 @@ ข้อมูลการตลาด แบ่งปันข้อมูลเกี่ยวกับคุณลักษณะที่คุณใช้ใน %1$s กับ Leanplum ผู้ให้บริการการตลาดมือถือของเรา + + แบ่งปันข้อมูลการใช้งานพื้นฐานกับ Adjust ผู้จำหน่ายการตลาดมือถือของเรา การศึกษา @@ -540,8 +554,6 @@ แท็บใหม่ ค้นหาในหน้า - - แท็บที่ซิงค์ รายการอ่าน @@ -586,6 +598,15 @@ หลังจากผ่านไปหนึ่งเดือน + + + เริ่มที่หน้าแรก + + หลังจาก 4 ชั่วโมง + + ทุกครั้ง + + ไม่เลย ปิดด้วยตนเอง @@ -794,8 +815,6 @@ ลบ %1$s แล้ว เพิ่มโฟลเดอร์ - - สร้างที่คั่นหน้าแล้ว บันทึกที่คั่นหน้าแล้ว! @@ -1448,10 +1467,8 @@ การเติมอัตโนมัติ ซิงค์การเข้าสู่ระบบ - - เปิด - - ปิด + + ซิงค์การเข้าสู่ระบบระหว่างอุปกรณ์ เชื่อมต่อใหม่ @@ -1552,6 +1569,8 @@ ข้อมูลถูกเข้ารหัส ซิงค์บัตรระหว่างอุปกรณ์ + + ซิงค์บัตร เพิ่มบัตรเครดิต @@ -1565,6 +1584,10 @@ หมายเลขบัตร วันหมดอายุ + + เดือนหมดอายุ + + ปีหมดอายุ ชื่อบนบัตร @@ -1583,6 +1606,25 @@ บัตรที่บันทึกไว้ + + โปรดป้อนหมายเลขบัตรเครดิตที่ถูกต้อง + + โปรดกรอกช่องนี้ + + ปลดล็อกเพื่อดูบัตรเครดิตที่บันทึกไว้ของคุณ + + รักษาความปลอดภัยให้กับบัตรเครดิตของคุณ + + ตั้งค่ารูปแบบการล็อกอุปกรณ์, PIN, หรือรหัสผ่านเพื่อปกป้องไม่ให้ใครเข้าถึงบัตรเครดิตที่บันทึกไว้ของคุณหากคนอื่นมีอุปกรณ์ของคุณ + + ตั้งค่าตอนนี้ + + ภายหลัง + + ปลดล็อกอุปกรณ์ของคุณ + + ปลดล็อกเพื่อใช้ข้อมูลบัตรเครดิตที่เก็บไว้ + เพิ่มเครื่องมือค้นหา @@ -1748,20 +1790,13 @@ ลบ - - รับประโยชน์สูงสุดจาก %s - คลิกเพื่อดูรายละเอียดเพิ่มเติม - - รวบรวมสิ่งที่สำคัญสำหรับคุณ - - จัดกลุ่มการค้นหา ไซต์ และแท็บที่คล้ายกันเพื่อการเข้าถึงอย่างรวดเร็วในภายหลัง - - คุณลงชื่อเข้าในชื่อ %s บนเบราว์เซอร์ Firefox อื่นบนโทรศัพท์นี้ คุณต้องการลงชื่อเข้าด้วยบัญชีนี้หรือไม่? - - คุณสามารถเพิ่มเว็บไซต์นี้ลงในหน้าจอหลักของโทรศัพท์ของคุณเพื่อเข้าถึงและเรียกดูได้เร็วขึ้นด้วยประสบการณ์ที่เหมือนแอป + + นำทางขึ้นไปด้านบน + + + ปิด - + diff --git a/app/src/main/res/values-tr/strings.xml b/app/src/main/res/values-tr/strings.xml index 46a0a1cfc..068e45729 100644 --- a/app/src/main/res/values-tr/strings.xml +++ b/app/src/main/res/values-tr/strings.xml @@ -5,6 +5,7 @@ Gizli %s %s (Gizli) + Daha fazla seçenek @@ -48,6 +49,16 @@ Seçildi + + + Son kaydedilenler + + Son kaydedilen yer imleri + + Tümünü göster + + Tüm kayıtlı yer imleri düğmesini göster + %1$s bir Mozilla ürünüdür. @@ -93,13 +104,6 @@ Kapat - - Açık sekmelerin görünümünü değiştirebilirsiniz. Ayarlara gidip “sekme görünümü” altından “ızgara”yı seçin. - - Ayarlara git - - Kapat - Yeni sekme @@ -109,6 +113,12 @@ Sık kullanılanlar + + + Açık sekmeler + + Tümünü göster + Açık sekmeler @@ -178,12 +188,16 @@ Görünüm - Okuyucu görünümünü özelleştir + Okuyucuyu özelleştir Ekle Düzenle + + + Ana ekran + Bağlanılamıyor. Tanınmayan URL şeması. @@ -547,8 +561,6 @@ Yeni sekme Sayfada bul - - Eşitlenmiş sekmeler Okuma listesi @@ -593,6 +605,15 @@ Bir ay sonra + + + Ana ekrandan başla + + Dört saat sonra + + Her zaman + + Asla Elle kapat @@ -1570,6 +1591,10 @@ Kart numarası Son kullanma tarihi + + Son kullanma tarihi - Ay + + Son kullanma tarihi - Yıl Kart üzerindeki ad @@ -1591,6 +1616,24 @@ Lütfen geçerli bir kredi kartı numarası girin + + Lütfen bu alanı doldurun + + Kayıtlı kartlarınızı görmek için kilidi açın + + Kredi kartlarını güvence altına al + + Cihazınız başka birinin eline geçerse kayıtlı kartlarınıza erişilmesini önlemek için cihaz kilidi deseni, PIN veya parola ayarlayın. + + Hemen ayarla + + Daha sonra + + + Cihazınızın kilidini açın + + Depolanan kredi kartı bilgilerini kullanmak için kilidi açın + Arama motoru ekle diff --git a/app/src/main/res/values-tt/strings.xml b/app/src/main/res/values-tt/strings.xml index 790303dce..cc3146b64 100644 --- a/app/src/main/res/values-tt/strings.xml +++ b/app/src/main/res/values-tt/strings.xml @@ -4,6 +4,7 @@ Хосусый %s %s (Хосусый) + Күбрәк опцияләр @@ -81,11 +82,6 @@ Яшерү - - Көйләүләргә күчү - - Яшерү - Яңа таб @@ -170,6 +166,10 @@ Үзгәртү + + Тоташып булмады. Танылмаган URL схемасы. + Сайланган тел @@ -202,6 +202,9 @@ %s ярдәмендә эзләү + + Адрес юлыннан турыдан-туры эзләү + Яңа Firefox табын ачу @@ -288,6 +291,8 @@ Кыстыргычларны, тарихны һәм башкаларны Firefox Хисабыгыз белән синхронлау Firefox хисап язмасы + + Синхронлауны дәвам итү өчен яңадан тоташыгыз Тел @@ -371,6 +376,10 @@ Җиһаз исеме буш була алмый. Синхронлау... + + Синхронлау барып чыкмады. Соңгы синхронлау: %s + + Синхронлау барып чыкмады. Соңгы синхронлау: һичкайчан Соңгы синхронлау: %s @@ -383,18 +392,27 @@ Башка җиһаздагы таблар + + Башка Firefox җиһазларыннан алынган таблар өчен искәртүләр. Таб кабул ителде Таблар кабул ителде + + %s җиһазыннан таб + Күзәтелүдән саклау Күзәтелүдән саклау + + Интернетта Сезне күзәтүче эчтәлек һәм скриптларны блоклау Чыгармалар + + Күзәтелүдән саклау бу сайтлар өчен cүнгән Барлык сайтлар өчен дә кабызу @@ -402,10 +420,20 @@ Телеметрия + + Куллану турында һәм техник мәгълүматлар Маркетинг мәгълүматлары Тикшеренүләр + + Mozilla-га тикшеренүләр урнаштырырга һәм үткәрергә рөхсәт итү + + Тәҗрибәләр + + Mozilla-га эксперименталь мөмкинлекләр өчен мәгълүмат урнаштырырга һәм җыярга рөхсәт итү + + Ватылулар хәбәрчесе Mozilla урнашу хезмәте @@ -414,6 +442,8 @@ Синхронлауны кабызу + + Эш өстәле компьютерындагы Firefox-та ялгау кодын сканерлау Керү @@ -422,6 +452,9 @@ Хисап язмасын бетерү + + + Firefox.com/pair адресында күрсәтелгән QR кодны сканерлагыз]]> Камераны ачу @@ -440,9 +473,22 @@ Караңгы төсле + + Батареяны саклау режимын исәпкә алу Җиһаз темасына иярү + + + Яңарту өчен тартыгыз + + + Кораллар панелен яшерү өчен әйләндерегез + + Табларны алыштыру өчен кораллар панелен кырыйга сөйрәгез + + Табларны ачу өчен кораллар панелен өскә таба сөйрәгез + Сессияләр @@ -466,14 +512,14 @@ Яңа таб Биттән табу - - Синхронланган таблар Уку исемлеге Эзләү Көйләүләр + + Тарих элементы менюсы Ябу @@ -494,6 +540,8 @@ Таблар + + Таб күренеше Исемлек @@ -559,6 +607,8 @@ Яңа таб Баш биткә кайту + + Таб режимын алыштыру Кыстыргыч @@ -593,6 +643,8 @@ Саклау Уртаклашу + + Агымдагы сессия рәсеме Җыентыкка саклау @@ -638,6 +690,9 @@ %1$d сайланды + + %1$d элементны бетерү Бүген @@ -677,6 +732,8 @@ Гафу. %1$s бу сәхифәне йөкли алмый. + + Mozilla-га ватылу турында хәбәр җибәрү Табны ябу @@ -697,12 +754,12 @@ Папка сайлау Папка бетерүне раслыйсызмы? + + %s сайланган элементларны бетерәчәк. %1$s бетерелде Папка өстәү - - Кыстыргыч ясалды. Кыстыргыч cакланды! @@ -790,6 +847,8 @@ Искәртү Даими саклагыч + + DRM белән идарә ителгән эчтәлек Рөхсәт итүне сорау @@ -808,6 +867,10 @@ Аудио һәм видеоны рөхсәт итү Аудио һәм видеоны рөхсәт итү + + Аудио һәм видеоны мобиль интернетны кулланганда гына блоклау + + Аудио һәм видео Wi-Fi аша уйнатылачак Аудионы гына тыю @@ -884,11 +947,19 @@ Синхронлауга керү Барлык җиһазларга җибәрү + + Синхронлауга яңадан тоташу + + Офлайн Башка җиһазны тоташтыру + + Табны җибәрү өчен, кимендә тагын бер башка җиһаздан Firefox-ка керегез. Аңладым + + Бу кушымта белән бүлешеп булмый Җиһазга җибәрү @@ -945,12 +1016,17 @@ Кире алу Раслау + + %1$s кушымтасына %2$s сылтамасын ачарга рөхсәт бирү РӨXCӘT ИТҮ КИРЕ КАГУ %1$s җыентыгын бетерүне раслыйсызмы? + + Бу табны бетерү бөтен җыентыкны бетерәчәк. Сез һәрвакыт яңа җыентыклар булдыра аласыз. %1$s җыентыгын бетерергәме? @@ -962,9 +1038,14 @@ Тулы экран режимына күчү URL копияләнде + + Вебсайтларда текстны зурайту я кечерәйтү Шрифт үлчәме + + Автоматик шрифт үлчәме + Гизү мәгълүматларын бетерү @@ -983,6 +1064,10 @@ %d бит Кукилар + + Сез күпчелек сайтлардан чыгачаксыз + + Кәшләнгән рәсемнәр һәм файллар Саклагычта урын бушата @@ -992,9 +1077,15 @@ Йөкләүләр Гизү мәгълүматларын бетерү + + Чыкканда гизү мәгълүматларын бетерү Чыгу + + Бу сезнең барлык гизү мәгълүматларыгызны да бетерәчәк. + + %s сайланган гизү мәгълүматларын бетерәчәк. Баш тарту @@ -1005,6 +1096,9 @@ Гизү мәгълүматларын бетерү… + + + Firefox Preview хәзер Firefox Nightly дип атала Android Beta өчен Firefox алу @@ -1039,16 +1133,29 @@ Керү... Теркәлү + + Кермичә генә тору Синхронлау кабызылган Кереп булмады + + Даими хосусыйлык Стандарт (килешенгәнчә) Катгый (киңәш ителә) Катгый + + Кораллар панеленең урнашуын сайлау + + Хосусый режимда гизү + + Бер тапкыр гына хосусый таб ачу өчен %s тамгачыгына басыгыз. + + Хосусый табларны һәрвакыт ачу өчен хосусый гизү көйләүләрен яңартыгыз. Көйләүләрне ачу @@ -1058,11 +1165,18 @@ Ябу + + Гизүне башлау + Теманы сайлау + + Караңгы режим ярдәмендә батареяны һәм күзләрегезне саклагыз. Автоматик + + Җиһаз көйләүләренә яраклаша Караңгы тема @@ -1078,11 +1192,22 @@ КАБАТЛАУ Кодны сканерлау + + https://firefox.com/pair адресына үтегез]]> + + Сканерлауга әзер + + Камерагыз ярдәмендә керегез + + Моның урынына эл. почта кулланыгыз Өзү Баш тарту + + Стандарт папкаларны үзгәртә алмыйм + Саклау көйләүләре @@ -1092,13 +1217,25 @@ Күбрәк белү Стандарт (килешенгәнчә) + + Стандарт күзәтелүдән саклау чаралары нәрсәләрне блоклый Катгый Үзгә + + Кайсы төр трекерларны һәм скриптларны блокларга икәнен сайлагыз. + + Үзгә күзәтелүдән саклау чаралары нәрсәләрне блоклый Кукилар + + Сайт-ара һәм социаль челтәр күзәтүчеләре + + Каралмаган сайтлардан булган кукилар + + Күзәтүче эчтәлек Барлык табларда @@ -1108,11 +1245,27 @@ Үзгә табларда гына Криптомайнерләр + + Бармак эзләрен җыючылар (идентификаторлар) Тыелган Рөхсәт ителгән + + Социаль челтәр күзәтүчеләре + + Сайт-ара күзәтүче сookie файллары Криптомайнерләр + + Бармак эзләрен җыючылар (идентификаторлар) + + Күзәтүче эчтәлек + + Бу сайт өчен саклау КАБЫНГАН + + Бу сайт өчен саклау СҮНГӘН + + Күзәтелүдән көчәйтелгән саклау бу вебсайтлар өчен сүндерелгән Кире кайту @@ -1126,8 +1279,13 @@ The first parameter is the app name --> %s | OSS китапханәләр + + Юнәлтүләрне күзәтеп торучылар + Техник ярдәм + + Өзеклеклер Хосусыйлык аңлатмасы @@ -1137,6 +1295,11 @@ Без кулланган китапханәләр + + Хата төзәтү менюсы: кабызу өчен %1$d чиртү калды + Хата төзәтү менюсы кабынган + 1 таб @@ -1177,10 +1340,8 @@ Автотутыру Логиннарны синхронлау - - Кабынган - - Сүнгән + + Логиннарны җиһазлар арасында синхронлау Яңадан тоташу @@ -1195,6 +1356,8 @@ Сакланмаган логиннар һәм серсүзләр монда күрсәтеләчәк. Бу сайтлар өчен логиннар һәм серсүзләр сакланмаячак. + + Барлык чыгармаларны бетерү Логиннардан эзләү @@ -1211,8 +1374,12 @@ PIN-кодыгызны яңадан кертегез Сакланган логиннарыгызны карау өчен йозакны ачыгыз + + Бу бәйләнеш шифрланмаган. Монда кертелгән логиннар башкалар кулына эләгергә мөмкин. Күбрәк белү + + %s бу логинны сакласынмы? Саклау @@ -1242,34 +1409,53 @@ Серсүзне яшерү Сакланган логиннарыгызны карау өчен йозакны ачыгыз + + Логиннарыгыз һәм серсүзләрегезне башкалардан саклагыз Cоңрак + + Хәзер урнаштыру Җиһазыгызның йозагын ачыгыз + + Барлык вебсайтларны да масштаблау Исем (А-Я) Соңгы кулланылган + + Логиннар менюсын тәртипкә китерү + Кредит карталары + + Карталарны саклау һәм автотөгәлләү Мәгълүматлар шифрланган Карталарны җиһазлар арасында синхронлау + + Карталарны синхронлау Кредит картасын өстәү Сакланган карталар белән идарә итү Картаны өстәү + + Картаны үзгәртү Карта номеры Вакыты чыгу датасы Картадагы исем + + Карта исеме + + Картаны бетерү Картаны бетерү @@ -1282,6 +1468,9 @@ Сакланган карталар + + Зинһар, дөрес бер карта номерын кертегез + Эзләү системасын өстәү @@ -1301,18 +1490,26 @@ Исем Эзләнәчәк сүз я сүзтезмә + + Сорауны “%s” юлы белән алыштырыгыз. Мисал өчен:\nhttps://www.google.com/search?q=%s Күбрәк белү + + Үзгә эзләү системасының нечкәлекләре Күбрәк белү сылтамасы Эзләү системасының исемен кертегез + + “%s” исемле эзләү системасы инде бар. Эзләнәсе сүзтезмәне кертегез Эзләнәсе сүзтезмәнең Мисал форматына туры килүен тикшерегез + + “%s” адресына тоташу хатасы %s ясалды @@ -1320,6 +1517,8 @@ %s бетерелде + + Өр яңа %s-ка рәхим итегез %s яңартыла… @@ -1329,6 +1528,13 @@ Серсүзләр + + Рөхсәт итү өчен: + + 1. Android көйләүләренә керегез + + Рөхсәтләр’гә басыгыз]]> + Хәвефсез бәйләнеш @@ -1339,6 +1545,8 @@ Бу сайт өчен бирелгән барлык рөхсәтләрне дә чистартуны раслыйсызмы? Әлеге сайт өчен бирелгән бу рөхсәтне кире алуны раслыйсызмы? + + Сайт өчен чыгармалар юк Төп мәкаләләр @@ -1358,6 +1566,12 @@ Бетерү Логин көйләүләре + + Логинның веб-адресы өчен үзгәртелә торган текст кыры. + + Логинның кулланучы исеме өчен үзгәртелә торган текст кыры. + + Логинның серсүзе өчен үзгәртелә торган текст кыры. Логин үзгәрешләрен саклау. @@ -1372,17 +1586,33 @@ Хәзер сөйләгез + + Мондый исемле кулланучы бар инде + Башка бер җиһазны тоташтыру. + + Зинһар, сайтка яңадан керегез. + + Зинһар, таблар синхронлауны кабызыгыз. + + Башка җиһазларыгыздагы Firefox-ларда ачык таблар юк. + + Башка җиһазларыгызда ачылган таблар исемлеген карау. Синхронлауга керү Ачык таблар юк + + + Төп сайтлар саны чиккә җитте Яхшы, аңладым - + + Иң күп каралган сайтларны күрсәтү + Исем Төп сайт исеме @@ -1394,4 +1624,7 @@ Бетерү + + Күбрәк белү өчен басыгыз + diff --git a/app/src/main/res/values-tzm/strings.xml b/app/src/main/res/values-tzm/strings.xml new file mode 100644 index 000000000..e223d2be2 --- /dev/null +++ b/app/src/main/res/values-tzm/strings.xml @@ -0,0 +1,296 @@ + + + + Uslig %s + + %s (Uslig) + + Isem + + + Rnu asanf + + Uhu, tanemmirt + + + Ddu ɣer tisɣal + + + Ddu ɣer tisɣal + + + Ddu ɣer tisɣal + + + + Iccer amaynu + + Iccer uslig amaynu + + + Sbedd + + Tiwisi + + Amaynu + + Tisɣal + + Tasedlist + + Rzu g tasna + + Iccer uslig + + Bḍu + + Bḍu d… + + Ṛẓem g %1$s + + Ṛẓem g tsensi + + Rnu + + + Rzu + + Ḍfeṛ tutlay n wallal + + Tutlayt n urezzu + + + Anesmassu n urezzu + + Tisɣal n unesmassu n urezzu + + Tikkelt-a, rzu s: + + Rzu %s + + + + Ṛẓem iccer amaynu n Firefox + + Rzu + + Rzu g web + + + + Tisɣal + + Ɣef + + Arezzu + + Tiwisi + + Ɣef %1$s + + Amiḍan + + Kcem + + Asgum + + Amiḍan Firefox + + Tutlayt + + Tisɣal n umiḍan + + + Tineɣmisin + + + WAXXA + + + Inekcam + + Ffeɣ + + Isem n wallal + + %1$s g %2$s %3$s + + + Tansiwin + + + Kcem + + Kkes amiḍan + + + + Anafaw + + Adeɣmum + + + Af g tesna + + Rzu + + Tisɣal + + + Mḍel + + + Uslig + + Tisɣal n umiḍan + + Mḍel + + Kkes + + Bḍu + + Kkes + + + Sfeḍ + + Bḍu + + Kkes + + + Kkes %1$d iferdas + + Ass-a + + Assennaṭ + + 24 n tesragin timeggura + + 7 n wussan imeggura + + 30 n wussan imeggura + + Iqbuṛen + + + Ṛẓem + + Kkes + + + + Rnu asdaw + + Bḍu + + Kkes + + URL + + ASDAW + + ISEM + + + Rnu asdaw + + + Ddu ɣer tisɣal + + Tineɣmisin + + + Mḍel + + + Bḍu + + Bḍu + + + Bḍu asɣen + + Azen ɣer wallal + + Azen ɣer wallal + + + Ṛẓem + + Kkes %1$s? + + Kkes + + + %d n tansiwin + + %d n tasniwin + + Ffeɣ + + + Kkes + + + + Ansuf ɣer %s! + + Ṛẓem tisɣal + + + Mḍel + + + Rnu + + + Isem (A-Ẓ) + + + Rnu takaṛḍa + + Uṭṭun n tkaṛḍa + + Isem g tkaṛḍa + + Kkes takaṛḍa + + Kkes takaṛḍa + + + Rnu + + Kkes + + + Isem + + + 1. Ddu ɣer tisɣal n Android + + + Kkes + + Kkes + + + Isem + + + WAXXA + + + Kkes + + diff --git a/app/src/main/res/values-uk/strings.xml b/app/src/main/res/values-uk/strings.xml index 4121d9621..d794f71d6 100644 --- a/app/src/main/res/values-uk/strings.xml +++ b/app/src/main/res/values-uk/strings.xml @@ -4,6 +4,7 @@ Приватний перегляд %s %s (Приватний перегляд) + Додатково @@ -47,6 +48,16 @@ Вибрано + + + Недавно збережені + + Недавно збережені закладки + + Показати всі + + Показати всі збережені закладки + %1$s розроблено Mozilla. @@ -93,13 +104,6 @@ Відхилити - - Змініть вигляд відкритих вкладок. Перейдіть до налаштувань і виберіть подання вкладок сіткою. - - Перейти до налаштувань - - Відхилити - Нова вкладка @@ -109,6 +113,12 @@ Популярні сайти + + + Назад до + + Показати всі + Відкриті вкладки @@ -186,6 +196,10 @@ Редагувати + + + Домашній екран + Неможливо з’єднатися. Невідома схема URL-адреси. @@ -354,7 +368,7 @@ Автозавершення URL-адрес - Відкривати посилання в програмах + Відкривати посилання у програмах Зовнішній менеджер завантажень @@ -554,8 +568,6 @@ Нова вкладка Знайти на сторінці - - Синхронізовані вкладки Список читання @@ -600,6 +612,15 @@ Через місяць + + + Відкривати домівку після запуску + + Через чотири години + + Завжди + + Ніколи Закрити власноруч @@ -1585,6 +1606,10 @@ Номер картки Термін дії + + Місяць закінчення терміну дії + + Рік закінчення терміну дії Ім’я на картці @@ -1606,6 +1631,24 @@ Введіть дійсний номер кредитної картки + + Будь ласка, заповніть це поле + + Розблокуйте для перегляду збережених карток + + Захистіть свої банківські картки + + Встановіть графічний ключ, ПІН, чи пароль, щоб захистити збережені банківські картки від інших, хто може отримати доступ до вашого пристрою. + + Встановити + + Пізніше + + Розблокуйте свій пристрій + + + Розблокуйте, щоб використовувати збережену інформацію про кредитну картку + Додати засіб пошуку diff --git a/app/src/main/res/values-ur/strings.xml b/app/src/main/res/values-ur/strings.xml index d43fd38a6..e8d1525f1 100644 --- a/app/src/main/res/values-ur/strings.xml +++ b/app/src/main/res/values-ur/strings.xml @@ -4,6 +4,7 @@ نجی %s %s (نجی) + مزید اختیارات @@ -20,10 +21,6 @@ آپ کے نجی ٹیبز یہاں دکھائے جائیں گے۔ - - بیدو - - JD 1 کھلا ٹیب۔ ٹیبز بدلنے کے لئے دبائیں۔ @@ -54,6 +51,12 @@ منتخب شدہ + + + حال ہی میں محفوظ شدہ + + تمام دکھائیں + %1$s ء@fork-maintainers کے ذریعہ تیار کیا گیا ہے۔ @@ -89,11 +92,6 @@ برخاست کریں - - سیٹنگز پر جائیں - - برخاست کریں - نیا ٹیب @@ -103,6 +101,9 @@ سر فہرست سائٹین + + تمام دکھائیں + ٹیب کھولیں @@ -172,6 +173,15 @@ ظاہرى شکل + + اضافہ کریں + + تدوین کریں + + + + ابتدائی اسکرین + رابطہ قائم کرنے میں ناکام رہا۔ ناقابل شناخت URL اسکیم۔ @@ -212,6 +222,9 @@ %s تلاش کریں + + ایڈریس بار سے براہ راست تلاش کریں + ایک نیا Firefox ٹیب کھولیں @@ -398,6 +411,11 @@ and the third is the device model. --> %3$s %2$s پر %1$s + + کریڈٹ کارڈز + + پتے + موصول شدہ ٹیب @@ -428,9 +446,6 @@ مزید سیکھیں - - سبھی کے لیے بند ہو گیا، اسے شروع کرنے کے لیے سیٹنگس میں جائیں۔ - ٹیلیمیٹری @@ -524,8 +539,6 @@ نیا ٹیب صفحے میں تلاش کریں - - سینک ہو چکے ٹیبز پڑھنے کی فہرست @@ -572,6 +585,12 @@ ایک مہینے کے بعد + + چار گھنٹے بعد + + ہمیشہ + + کبھی نہیں دستی طور پر بند کریں @@ -595,6 +614,8 @@ نجی ٹیب شامل کریں نجی + + سنک ٹیب کھولیں @@ -605,6 +626,8 @@ تمام ٹیبز شیئر کریں حالیہ بند کیے گئے ٹیبز + + اکاؤنٹ کی سیٹنگز ٹیب کی سیٹنگز @@ -773,8 +796,6 @@ %1$s حذف ہو گیا فولڈر بناؤ - - بُکمارک بنایا گیا۔ بکمارک محفوظ! @@ -1142,46 +1163,28 @@ %s میں خوش آمدید! کیا پہلے سے ہی ایک اکاؤنٹ ہے؟ - - %s سے واقف ہوں دیکھیں نیا کیا ہے یہاں جوابات حاصل کریں - - مزید سیکھیں ہاں ، مجھے سائن ان کریں سائن ان ہو رہا ہے… - - Firefox کے لیے سائن ان کریں + + سائن اپ کریں سائن آؤٹ رہیں Sync چالو ہے سائن ان کرنے میں ناکام - - خودکار رازداری - - رازداری اور سلامتی سیٹنگز ٹریکرز، مالویئر، اور آپ کا پیچھا کرنے والی کمپنیوں کو روکتی ہیں۔ معیاری (پہلے سے طے شدہ) - - چند ٹریکروں کو روکتا ہے۔ صفحات عام طور پر لوڈ ہوں گے۔ سخت (سفارش شدا) سخت - - زیادہ ٹریکر ، اشتہارات اور پاپ اپ کو بلاک کرتا ہے۔ صفحات تیزی سے لوڈ ہوتے ہے ، لیکن کچھ فعالیت کام نہیں کرسکتی ہے۔ - - ایک پہلو چنے رازداری سے براؤز کریں @@ -1383,10 +1386,6 @@ آٹوفل لاگ ان کو Sync کریں - - آن - - آف ‏‏پھر جوڑیں @@ -1439,8 +1438,12 @@ سائٹ کو کلپ بورڈ میں کاپی کیا گیا پاس ورڈ نقل کریں + + پاس ورڈ صاف کریں صارف نام نقل کریں + + صارف نام صاف کریں سائٹ کاپی کریں @@ -1474,6 +1477,41 @@ لاگ ان مینو کو ترتیب دیں + + کارڈ شامل کریں + + کارڈ میں تدوین کریں + + کارڈ نمبر + + میعاد ختم ہونے کی تاریخ + + میعاد ختم ہونے کی تاریخ کا مہینہ + + میعاد ختم ہونے کی تاریخ کا سال + + کارڈ پر نام + + کارڈ کا نام + + کارڈ حذف کریں + + کارڈ حذف کریں + + محفوظ کریں + + محفوظ کریں + + منسوخ کریں + + محفوظ شدہ کارڈ + + ابھی سیٹ اپ کریں + + بعد میں + + اپنے آلے کو ان لاک کریں + تلاش انجن شامل کریں @@ -1617,7 +1655,9 @@ ٹھیک ہے سمجھ گیا - + + سب سے زیادہ ملاحظہ کی جانے والی سائٹیں دکھائیں + نام ٹھیک ہے @@ -1627,12 +1667,13 @@ ہٹائیں - - %s کا زیادہ سے زیادہ فائدہ اٹھائیں۔ + + تفصیلات کے لیے کلک کریں + + + اوپر جائیں + + + بند کریں - - آپ کے لئے اہم چیزیں جمع کریں - - ایک طرح کی تلاشیں ، سائٹیں اور ٹیبز کو بعد میں فوری رسائی کے لئے گروہ بندی کریں۔ - + diff --git a/app/src/main/res/values-vi/strings.xml b/app/src/main/res/values-vi/strings.xml index 0890effa6..58d7e9562 100644 --- a/app/src/main/res/values-vi/strings.xml +++ b/app/src/main/res/values-vi/strings.xml @@ -5,6 +5,7 @@ %s riêng tư %s (Riêng tư) + Tùy chọn khác @@ -48,6 +49,16 @@ Đã chọn + + + Đã lưu gần đây + + Dấu trang đã lưu gần đây + + Hiển thị tất cả + + Hiển thị nút tất cả dấu trang đã lưu + %1$s được sản xuất bởi Mozilla. @@ -93,13 +104,6 @@ Bỏ qua - - Thay đổi bố cục của các thẻ đang mở. Đi tới cài đặt và chọn lưới trong chế độ xem thẻ. - - Đi tới cài đặt - - Bỏ qua - Thẻ mới @@ -109,6 +113,12 @@ Trang web hàng đầu + + + Quay lại trang trước + + Hiển thị tất cả + Các thẻ đang mở @@ -184,6 +194,10 @@ Chỉnh sửa + + + Màn hình chính + Không thể kết nối. Không thể nhận dạng URL. @@ -544,8 +558,6 @@ Thẻ mới Tìm trong trang - - Các thẻ đã đồng bộ Danh sách đọc @@ -590,6 +602,15 @@ Sau một tháng + + + Bắt đầu tại màn hình chính + + Sau bốn giờ + + Luôn luôn + + Không bao giờ Đóng thủ công @@ -1561,6 +1582,10 @@ Số thẻ Ngày hết hạn + + Tháng hết hạn + + Năm hết hạn Tên trên thẻ @@ -1582,6 +1607,23 @@ Vui lòng nhập số thẻ tín dụng hợp lệ + + Vui lòng điền vào trường này + + Mở khóa để xem các thẻ tín dụng đã lưu của bạn + + Bảo mật thẻ tín dụng của bạn + + Thiết lập màn hình khóa thiết bị với mẫu hình, mã PIN hoặc mật khẩu để bảo vệ thẻ tín dụng đã lưu của bạn không bị truy cập nếu người khác có thiết bị của bạn. + + Thiết lập ngay + + Để sau + + Mở khóa thiết bị của bạn + + Mở khóa để sử dụng thông tin thẻ tín dụng được lưu trữ + Thêm công cụ tìm kiếm diff --git a/app/src/main/res/values-zh-rCN/strings.xml b/app/src/main/res/values-zh-rCN/strings.xml index af863296b..ce8f4eca8 100644 --- a/app/src/main/res/values-zh-rCN/strings.xml +++ b/app/src/main/res/values-zh-rCN/strings.xml @@ -6,6 +6,7 @@ 私密 %s %s (隐私模式) + 更多选项 @@ -53,6 +54,16 @@ 已选择 + + + 最近保存 + + 最近保存的书签 + + 显示全部 + + 显示所有保存书签按钮 + %1$s 由 Mozilla 倾力打造。 @@ -97,13 +108,6 @@ 知道了 - - 要更改打开的标签页布局。请转至设置,在“标签页视图”下选择“网格”。 - - 前往设置 - - 关闭 - 新建标签页 @@ -113,6 +117,12 @@ 常用网站 + + + 回到先前页面 + + 显示全部 + 打开的标签页 @@ -191,6 +201,10 @@ 编辑 + + + 主屏幕 + 未知的 URL 规范,无法连接。 @@ -564,8 +578,6 @@ 新建标签页 在页面中查找 - - 受同步的标签页 阅读列表 @@ -610,6 +622,15 @@ 1 个月后 + + + 启动后进入主屏幕 + + 4 小时后 + + 总是 + + 永不 手动关闭 @@ -1612,6 +1633,10 @@ 卡号 失效日期 + + 到期月份 + + 到期年份 卡上姓名 @@ -1633,6 +1658,25 @@ 请输入有效的信用卡卡号 + + 请填写此栏 + + 解锁后即可查看保存的卡片信息 + + 保护您的卡片信息 + + + 设置锁定方式、PIN 码或密码以保护您保存的卡片信息,避免他人盗用。 + + 立即设置 + + 以后再说 + + 解锁设备 + + + 解锁以使用存储的卡片信息 + 添加搜索引擎 diff --git a/app/src/main/res/values-zh-rTW/strings.xml b/app/src/main/res/values-zh-rTW/strings.xml index 881dc581f..b71d6787c 100644 --- a/app/src/main/res/values-zh-rTW/strings.xml +++ b/app/src/main/res/values-zh-rTW/strings.xml @@ -6,6 +6,7 @@ 隱私 %s %s(隱私) + 更多選項 @@ -51,6 +52,16 @@ 已選取 + + + 最近儲存 + + 最近加入的書籤 + + 顯示全部 + + 顯示所有儲存書籤按鈕 + %1$s 是由 Mozilla 所打造。 @@ -94,13 +105,6 @@ 知道了! - - 可到設定,於「分頁檢視」下方選擇「格線」來更改開啟分頁的版面。 - - 開啟設定 - - 關閉 - 開新分頁 @@ -110,6 +114,12 @@ 熱門網站 + + + 回到先前開啟頁面 + + 顯示全部 + 開啟分頁 @@ -187,6 +197,10 @@ 編輯 + + + 主畫面 + 不認識的通訊協定,無法連線。 @@ -554,8 +568,6 @@ 開新分頁 在頁面中搜尋 - - 同步的分頁 閱讀清單 @@ -601,6 +613,15 @@ 1 個月後 + + + 啟動時,直接進入主畫面 + + 4 小時後 + + 總是 + + 永不 手動關閉 @@ -1555,7 +1576,7 @@ 保護您的登入資訊與密碼 - 設定裝備解鎖圖形、PIN 碼或密碼來保護您儲存下來的登入資訊與密碼,避免別人盜用。 + 設定裝置解鎖圖形、PIN 碼或密碼來保護您儲存下來的登入資訊與密碼,避免別人盜用。 稍後處理 @@ -1599,6 +1620,10 @@ 卡號 到期日 + + 到期月份 + + 到期年份 持卡人姓名 @@ -1620,6 +1645,24 @@ 請輸入有效的信用卡號 + + 請填寫此欄位 + + 解鎖後即可檢視儲存的卡片資訊 + + 保護您的信用卡資訊 + + 設定裝置解鎖圖形、PIN 碼或密碼來保護您儲存的信用卡資訊,避免別人盜用。 + + 立即設定 + + 稍後再設 + + 裝置解鎖 + + + 解鎖後,即可使用儲存的信用卡資訊 + 新增搜尋引擎 diff --git a/app/src/main/res/values/arrays.xml b/app/src/main/res/values/arrays.xml index 1143fed8a..de00358b1 100644 --- a/app/src/main/res/values/arrays.xml +++ b/app/src/main/res/values/arrays.xml @@ -39,4 +39,4 @@ @string/chrome_scheme @string/about_scheme - \ No newline at end of file + diff --git a/app/src/main/res/values/attrs.xml b/app/src/main/res/values/attrs.xml index 1c8ce3c53..8f71ae4a4 100644 --- a/app/src/main/res/values/attrs.xml +++ b/app/src/main/res/values/attrs.xml @@ -27,6 +27,7 @@ + @@ -96,6 +97,7 @@ + diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml index 0809ebebf..de34efd09 100644 --- a/app/src/main/res/values/colors.xml +++ b/app/src/main/res/values/colors.xml @@ -3,25 +3,17 @@ - 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/. --> - - #7A312A65 - #529059FF - #7A9059FF - #1F592ACB - #15141A - #E7DFFF - - #20123A + @color/photonInk80 @color/photonGrey50 @color/primary_text_dark_theme @color/photonLightGrey90 - #F9F9FB - #E0E0E6 + @color/photonLightGrey10 + @color/photonLightGrey30 #FFF - #312A65 - #592ACB - #592ACB + @color/photonInk20 + @color/photonViolet70 + @color/photonViolet70 @color/accent_light_theme @color/accent_light_theme @color/photonGrey30 @@ -34,7 +26,7 @@ #FF15141A #0015141A @color/photonLightGrey30 - @color/dark_grey_90 + @color/photonDarkGrey90 #7542E5 #0250BB #E31587 @@ -47,7 +39,7 @@ @color/accent_light_theme #C45A27 #FFFDE2 - #E0E0E6 + @color/photonLightGrey30 #F0F0F4 @color/accent_light_theme @color/accent_bright_light_theme @@ -72,28 +64,28 @@ #E5DFF4 @color/photonLightGrey10 @color/photonLightGrey30 - #ffffff - #312A65 + @color/photonWhite + @color/photonInk20 @color/photonInk20 - @color/ink_20_48a + @color/photonInk20A48 @color/accent_normal_theme @color/photonLightGrey10 @color/photonLightGrey60 - @color/violet_70_12a + @color/photonViolet70A12 @color/tab_tray_item_selected_background_light_theme - #FBFBFE + @color/photonLightGrey05 #A7A2B7 @color/primary_text_dark_theme @color/photonLightGrey70 - #1C1B22 + @color/photonDarkGrey80 #32313C #32313C - #9059FF - #592ACB + @color/photonViolet50 + @color/photonViolet70 #AB71FF #AB71FF @color/accent_dark_theme @@ -114,7 +106,7 @@ @color/foundation_dark_theme @color/foundation_dark_theme @color/foundation_dark_theme - #52525E + @color/photonDarkGrey10 @color/accent_on_dark_background_normal_theme #FFF36E #5B5846 @@ -131,6 +123,7 @@ #2ac3a2 #0090ed @color/accent_high_contrast_dark_theme + @color/photonDarkGrey10 @color/photonDarkGrey50 @color/photonDarkGrey10 @@ -142,27 +135,27 @@ #412E69 @color/photonDarkGrey50 @color/photonDarkGrey10 - #9059FF + @color/photonViolet50 @color/photonViolet50 @color/photonLightGrey05 @color/photonLightGrey05 @color/photonDarkGrey50 @color/photonDarkGrey05 - @color/violet_50_32a + @color/photonViolet50A32 @color/tab_tray_item_selected_background_dark_theme - #FBFBFE + @color/photonLightGrey05 #A7A2B7 @color/primary_text_private_theme @color/photonLightGrey70 #261E4B @color/photonInk50 @color/photonInk50 - #9059FF - #592ACB + @color/photonViolet50 + @color/photonViolet70 #AB71FF #AA71FF #F565FF @@ -178,7 +171,7 @@ #7529A7 #492E85 #383372 - #52525E + @color/photonDarkGrey10 @color/accent_on_dark_background_private_theme @color/primary_text_private_theme #C45A27 @@ -205,9 +198,9 @@ #422875 @color/photonInk50 @color/photonDarkGrey10 - #9059FF + @color/photonViolet50 @color/photonViolet50 - @color/violet_50_48a + @color/photonViolet50A48 @color/tab_tray_item_selected_background_dark_theme @@ -255,10 +248,12 @@ @color/search_suggestion_indicator_icon_color_light_theme @color/search_suggestion_indicator_icon_bookmark_color_light_theme @color/accent_bright_light_theme + @color/accent_bright_light_theme @color/mozac_widget_favicon_background_light_theme @color/mozac_widget_favicon_border_light_theme @color/accent_bright_light_theme @color/menu_item_button_light_theme + @color/inset_light_theme @color/tab_tray_item_text_light_theme @@ -285,7 +280,7 @@ @color/top_site_title_text_light_theme @color/photonLightGrey30 @color/photonLightGrey50 - @color/photonInk20 + @color/foundation_dark_theme @color/photonLightGrey30 @@ -315,8 +310,8 @@ #D4C1FA #2E2060 - #E0E0E6 - #20123A + @color/photonLightGrey30 + @color/photonInk80 #C60084 #FFB4DB @@ -350,7 +345,7 @@ @color/photonGrey10 - @color/dark_grey_90 + @color/photonDarkGrey90 @color/photonLightGrey05 @color/photonLightGrey05 @color/toggle_off_knob_light_theme @@ -359,7 +354,7 @@ #5C592ACB @color/foundation_private_theme - #FBFBFE + @color/photonLightGrey05 @color/white_color #cccccc #232749 @@ -374,35 +369,35 @@ #1F000000 - #20123A + @color/photonInk80 #FFFFFF - #F9F9FB - #312A65 + @color/photonLightGrey10 + @color/photonInk20 #E3E2E3 #F091C3 #D4C1FA - #20123A + @color/photonInk80 #FDFDFD #220033 - #312A65 + @color/photonInk20 @color/default_launcher_background - #E0E0E6 - #C50042 - #312A65 + @color/photonLightGrey30 + @color/destructive_normal_theme + @color/photonInk20 @color/white_color #FF000000 - #737373 + @color/photonGrey50 - #592ACB + @color/photonViolet70 #00B3F4 @@ -411,7 +406,7 @@ #F5F5F5 - #5B5B66 + @color/photonDarkGrey05 @color/destructive_light_theme diff --git a/app/src/main/res/values/dimens.xml b/app/src/main/res/values/dimens.xml index 32440af48..3a0506e8c 100644 --- a/app/src/main/res/values/dimens.xml +++ b/app/src/main/res/values/dimens.xml @@ -206,21 +206,21 @@ 48dp - 60dp - 12dp 84dp 8dp 12dp 8dp + 36dp + 0dp + 4dp + + 60dp + 12dp + 6dp + 8dp + 1dp - - 48dp - - 16dp - 16sp 16dp 48dp diff --git a/app/src/main/res/values/mozonline_strings.xml b/app/src/main/res/values/mozonline_strings.xml index 61724501e..a9b52aba1 100644 --- a/app/src/main/res/values/mozonline_strings.xml +++ b/app/src/main/res/values/mozonline_strings.xml @@ -36,4 +36,3 @@ https://firefox.com.cn/pair]]> - diff --git a/app/src/main/res/values/preference_keys.xml b/app/src/main/res/values/preference_keys.xml index 6a1996bae..ef1e717e5 100644 --- a/app/src/main/res/values/preference_keys.xml +++ b/app/src/main/res/values/preference_keys.xml @@ -91,6 +91,10 @@ pref_key_fxa_has_synced_items pref_key_search_widget_installed pref_key_saved_logins_sorting_strategy + + pref_key_sync_credit_cards + + pref_key_sync_address pref_key_search_engine_list @@ -177,7 +181,7 @@ pref_key_saved_logins pref_key_password_sync_logins pref_key_logins_secure_warning_sync - pref_key_logins_secure_warning + pref_key_secure_warning @@ -186,10 +190,14 @@ pref_key_credit_cards_save_and_autofill_cards pref_key_credit_cards_sync_cards_across_devices - - pref_key_credit_cards_add_credit_card - pref_key_credit_cards_manage_saved_cards + pref_key_credit_cards_manage_cards + + pref_key_credit_cards_saved_count + + pref_key_credit_cards_deleted_count + + pref_key_credit_cards_autofilled_count pref_key_open_links_in_a_private_tab @@ -252,6 +260,8 @@ pref_key_default_browser + pref_key_fxa_signed_in + pref_key_login_exceptions pref_key_show_collections_home @@ -265,6 +275,7 @@ pref_key_close_tabs_after_one_week pref_key_close_tabs_after_one_month pref_key_new_tabs_tray + pref_key_allow_third_party_cert_roots pref_key_camera_permissions_needed @@ -281,7 +292,6 @@ pref_key_search_region_current - pref_key_show_credit_cards_feature pref_key_show_address_feature pref_key_nimbus_experiments diff --git a/app/src/main/res/values/static_strings.xml b/app/src/main/res/values/static_strings.xml index cca417637..4045be6d8 100644 --- a/app/src/main/res/values/static_strings.xml +++ b/app/src/main/res/values/static_strings.xml @@ -37,12 +37,14 @@ Secret Debug Info Enable Address Autofill - - Enable Credit Card Autofill Use new Tabs Tray A refactored tabs tray that will include Synced Tabs. + + Use third party CA certificates + + Allows the use of third party certificates from the Android CA store Nimbus Experiments diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index e89fd06f6..6345e97d2 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -412,6 +412,10 @@ The first parameter is the application name, the second is the device manufacturer name and the third is the device model. --> %1$s on %2$s %3$s + + Credit cards + + Addresses @@ -785,8 +789,6 @@ Deleted %1$s Add folder - - Bookmark created. Bookmark saved! @@ -1448,10 +1450,8 @@ Autofill Sync logins - - On - - Off + + Sync logins across devices Reconnect @@ -1554,6 +1554,8 @@ Data is encrypted Sync cards across devices + + Sync cards Add credit card @@ -1582,6 +1584,22 @@ Cancel Saved cards + + Please enter a valid credit card number + + Unlock to view your saved cards + + Secure your credit cards + + Set up a device lock pattern, PIN, or password to protect your saved credit cards from being accessed if someone else has your device. + + Set up now + + Later + + Unlock your device + + Unlock to use stored credit card information Add search engine @@ -1770,19 +1788,13 @@ Remove - - Get the most out of %s. - Click for more details - - Collect the things that matter to you - - Group together similar searches, sites, and tabs for quick access later. - - You are signed in as %s on another Firefox browser on this phone. Would you like to sign in with this account? - - You can easily add this website to your phone’s Home screen to have instant access and browse faster with an app-like experience. + + Navigate up + + + Close + diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml index 143fd6b7a..9d6230374 100644 --- a/app/src/main/res/values/styles.xml +++ b/app/src/main/res/values/styles.xml @@ -28,6 +28,7 @@ @color/destructive_normal_theme @style/SelectLoginHeaderTextStyle + @style/SelectCreditCardHeaderTextStyle @color/accent_high_contrast_normal_theme @@ -81,8 +82,10 @@ @color/search_suggestion_indicator_icon_color_normal_theme @color/search_suggestion_indicator_icon_bookmark_color_normal_theme @color/select_login_header_normal_theme + @color/select_credit_card_header_normal_theme @color/preference_section_header_normal_theme @color/menu_item_button_normal_theme + @color/recently_used_share_theme @color/primary_text_normal_theme @@ -136,6 +139,11 @@ ?accentHighContrast + + - + + + +