summaryrefslogtreecommitdiffstats
path: root/mobile/android/android-components/components/compose
diff options
context:
space:
mode:
Diffstat (limited to 'mobile/android/android-components/components/compose')
-rw-r--r--mobile/android/android-components/components/compose/awesomebar/README.md19
-rw-r--r--mobile/android/android-components/components/compose/awesomebar/build.gradle68
-rw-r--r--mobile/android/android-components/components/compose/awesomebar/proguard-rules.pro21
-rw-r--r--mobile/android/android-components/components/compose/awesomebar/src/main/AndroidManifest.xml4
-rw-r--r--mobile/android/android-components/components/compose/awesomebar/src/main/java/mozilla/components/compose/browser/awesomebar/AwesomeBar.kt121
-rw-r--r--mobile/android/android-components/components/compose/awesomebar/src/main/java/mozilla/components/compose/browser/awesomebar/AwesomeBarColors.kt18
-rw-r--r--mobile/android/android-components/components/compose/awesomebar/src/main/java/mozilla/components/compose/browser/awesomebar/AwesomeBarDefaults.kt39
-rw-r--r--mobile/android/android-components/components/compose/awesomebar/src/main/java/mozilla/components/compose/browser/awesomebar/AwesomeBarFacts.kt44
-rw-r--r--mobile/android/android-components/components/compose/awesomebar/src/main/java/mozilla/components/compose/browser/awesomebar/AwesomeBarOrientation.kt13
-rw-r--r--mobile/android/android-components/components/compose/awesomebar/src/main/java/mozilla/components/compose/browser/awesomebar/internal/Suggestion.kt184
-rw-r--r--mobile/android/android-components/components/compose/awesomebar/src/main/java/mozilla/components/compose/browser/awesomebar/internal/SuggestionFetcher.kt160
-rw-r--r--mobile/android/android-components/components/compose/awesomebar/src/main/java/mozilla/components/compose/browser/awesomebar/internal/SuggestionGroup.kt35
-rw-r--r--mobile/android/android-components/components/compose/awesomebar/src/main/java/mozilla/components/compose/browser/awesomebar/internal/Suggestions.kt168
-rw-r--r--mobile/android/android-components/components/compose/awesomebar/src/main/res/values-am/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/awesomebar/src/main/res/values-ar/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/awesomebar/src/main/res/values-ast/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/awesomebar/src/main/res/values-azb/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/awesomebar/src/main/res/values-ban/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/awesomebar/src/main/res/values-be/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/awesomebar/src/main/res/values-bg/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/awesomebar/src/main/res/values-br/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/awesomebar/src/main/res/values-bs/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/awesomebar/src/main/res/values-ca/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/awesomebar/src/main/res/values-cak/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/awesomebar/src/main/res/values-ceb/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/awesomebar/src/main/res/values-ckb/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/awesomebar/src/main/res/values-co/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/awesomebar/src/main/res/values-cs/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/awesomebar/src/main/res/values-cy/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/awesomebar/src/main/res/values-da/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/awesomebar/src/main/res/values-de/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/awesomebar/src/main/res/values-dsb/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/awesomebar/src/main/res/values-el/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/awesomebar/src/main/res/values-en-rCA/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/awesomebar/src/main/res/values-en-rGB/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/awesomebar/src/main/res/values-eo/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/awesomebar/src/main/res/values-es-rAR/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/awesomebar/src/main/res/values-es-rCL/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/awesomebar/src/main/res/values-es-rES/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/awesomebar/src/main/res/values-es-rMX/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/awesomebar/src/main/res/values-es/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/awesomebar/src/main/res/values-et/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/awesomebar/src/main/res/values-eu/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/awesomebar/src/main/res/values-fa/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/awesomebar/src/main/res/values-fi/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/awesomebar/src/main/res/values-fr/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/awesomebar/src/main/res/values-fur/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/awesomebar/src/main/res/values-fy-rNL/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/awesomebar/src/main/res/values-gd/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/awesomebar/src/main/res/values-gl/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/awesomebar/src/main/res/values-gn/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/awesomebar/src/main/res/values-hi-rIN/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/awesomebar/src/main/res/values-hr/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/awesomebar/src/main/res/values-hsb/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/awesomebar/src/main/res/values-hu/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/awesomebar/src/main/res/values-hy-rAM/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/awesomebar/src/main/res/values-ia/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/awesomebar/src/main/res/values-in/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/awesomebar/src/main/res/values-is/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/awesomebar/src/main/res/values-it/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/awesomebar/src/main/res/values-iw/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/awesomebar/src/main/res/values-ja/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/awesomebar/src/main/res/values-ka/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/awesomebar/src/main/res/values-kaa/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/awesomebar/src/main/res/values-kab/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/awesomebar/src/main/res/values-kk/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/awesomebar/src/main/res/values-kmr/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/awesomebar/src/main/res/values-ko/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/awesomebar/src/main/res/values-lo/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/awesomebar/src/main/res/values-lt/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/awesomebar/src/main/res/values-mr/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/awesomebar/src/main/res/values-my/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/awesomebar/src/main/res/values-nb-rNO/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/awesomebar/src/main/res/values-ne-rNP/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/awesomebar/src/main/res/values-nl/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/awesomebar/src/main/res/values-nn-rNO/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/awesomebar/src/main/res/values-oc/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/awesomebar/src/main/res/values-or/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/awesomebar/src/main/res/values-pa-rIN/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/awesomebar/src/main/res/values-pa-rPK/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/awesomebar/src/main/res/values-pl/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/awesomebar/src/main/res/values-pt-rBR/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/awesomebar/src/main/res/values-pt-rPT/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/awesomebar/src/main/res/values-rm/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/awesomebar/src/main/res/values-ru/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/awesomebar/src/main/res/values-sat/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/awesomebar/src/main/res/values-sc/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/awesomebar/src/main/res/values-si/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/awesomebar/src/main/res/values-sk/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/awesomebar/src/main/res/values-skr/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/awesomebar/src/main/res/values-sl/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/awesomebar/src/main/res/values-sq/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/awesomebar/src/main/res/values-sr/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/awesomebar/src/main/res/values-su/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/awesomebar/src/main/res/values-sv-rSE/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/awesomebar/src/main/res/values-szl/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/awesomebar/src/main/res/values-ta/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/awesomebar/src/main/res/values-tg/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/awesomebar/src/main/res/values-th/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/awesomebar/src/main/res/values-tl/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/awesomebar/src/main/res/values-tok/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/awesomebar/src/main/res/values-tr/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/awesomebar/src/main/res/values-trs/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/awesomebar/src/main/res/values-tt/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/awesomebar/src/main/res/values-ug/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/awesomebar/src/main/res/values-uk/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/awesomebar/src/main/res/values-ur/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/awesomebar/src/main/res/values-uz/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/awesomebar/src/main/res/values-vi/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/awesomebar/src/main/res/values-yo/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/awesomebar/src/main/res/values-zh-rCN/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/awesomebar/src/main/res/values-zh-rTW/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/awesomebar/src/main/res/values/strings.xml8
-rw-r--r--mobile/android/android-components/components/compose/awesomebar/src/test/java/mozilla/components/compose/browser/awesomebar/internal/SuggestionFetcherTest.kt69
-rw-r--r--mobile/android/android-components/components/compose/awesomebar/src/test/java/mozilla/components/compose/browser/awesomebar/internal/SuggestionsTest.kt173
-rw-r--r--mobile/android/android-components/components/compose/awesomebar/src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker2
-rw-r--r--mobile/android/android-components/components/compose/browser-toolbar/README.md19
-rw-r--r--mobile/android/android-components/components/compose/browser-toolbar/build.gradle54
-rw-r--r--mobile/android/android-components/components/compose/browser-toolbar/proguard-rules.pro21
-rw-r--r--mobile/android/android-components/components/compose/browser-toolbar/src/main/AndroidManifest.xml4
-rw-r--r--mobile/android/android-components/components/compose/browser-toolbar/src/main/java/mozilla/components/compose/browser/toolbar/BrowserDisplayToolbar.kt62
-rw-r--r--mobile/android/android-components/components/compose/browser-toolbar/src/main/java/mozilla/components/compose/browser/toolbar/BrowserEditToolbar.kt93
-rw-r--r--mobile/android/android-components/components/compose/browser-toolbar/src/main/java/mozilla/components/compose/browser/toolbar/BrowserToolbar.kt77
-rw-r--r--mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-am/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-ar/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-ast/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-azb/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-ban/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-be/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-bg/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-br/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-bs/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-ca/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-cak/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-ceb/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-ckb/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-co/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-cs/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-cy/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-da/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-de/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-dsb/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-el/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-en-rCA/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-en-rGB/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-eo/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-es-rAR/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-es-rCL/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-es-rES/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-es-rMX/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-es/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-et/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-eu/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-fa/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-fi/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-fr/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-fur/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-fy-rNL/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-gd/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-gl/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-gn/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-hi-rIN/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-hil/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-hr/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-hsb/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-hu/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-hy-rAM/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-ia/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-in/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-is/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-it/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-iw/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-ja/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-ka/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-kaa/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-kab/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-kk/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-kmr/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-ko/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-lo/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-lt/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-mix/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-mr/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-my/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-nb-rNO/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-ne-rNP/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-nl/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-nn-rNO/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-oc/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-pa-rIN/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-pa-rPK/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-pl/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-pt-rBR/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-pt-rPT/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-rm/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-ru/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-sat/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-sc/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-si/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-sk/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-skr/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-sl/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-sq/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-sr/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-su/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-sv-rSE/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-szl/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-ta/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-te/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-tg/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-th/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-tl/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-tok/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-tr/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-trs/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-tt/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-tzm/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-ug/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-uk/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-ur/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-uz/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-vec/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-vi/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-yo/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-zh-rCN/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-zh-rTW/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values/strings.xml8
-rw-r--r--mobile/android/android-components/components/compose/browser-toolbar/src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker2
-rw-r--r--mobile/android/android-components/components/compose/cfr/README.md49
-rw-r--r--mobile/android/android-components/components/compose/cfr/build.gradle63
-rw-r--r--mobile/android/android-components/components/compose/cfr/proguard-rules.pro21
-rw-r--r--mobile/android/android-components/components/compose/cfr/src/main/AndroidManifest.xml4
-rw-r--r--mobile/android/android-components/components/compose/cfr/src/main/java/mozilla/components/compose/cfr/CFRPopup.kt195
-rw-r--r--mobile/android/android-components/components/compose/cfr/src/main/java/mozilla/components/compose/cfr/CFRPopupContent.kt186
-rw-r--r--mobile/android/android-components/components/compose/cfr/src/main/java/mozilla/components/compose/cfr/CFRPopupFullscreenLayout.kt537
-rw-r--r--mobile/android/android-components/components/compose/cfr/src/main/java/mozilla/components/compose/cfr/CFRPopupShape.kt272
-rw-r--r--mobile/android/android-components/components/compose/cfr/src/main/java/mozilla/components/compose/cfr/helper/DisplayOrientationListener.kt65
-rw-r--r--mobile/android/android-components/components/compose/cfr/src/main/java/mozilla/components/compose/cfr/helper/ViewDetachedListener.kt19
-rw-r--r--mobile/android/android-components/components/compose/cfr/src/main/res/values-am/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/cfr/src/main/res/values-ast/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/cfr/src/main/res/values-azb/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/cfr/src/main/res/values-be/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/cfr/src/main/res/values-bg/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/cfr/src/main/res/values-br/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/cfr/src/main/res/values-bs/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/cfr/src/main/res/values-ca/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/cfr/src/main/res/values-cak/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/cfr/src/main/res/values-ckb/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/cfr/src/main/res/values-co/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/cfr/src/main/res/values-cs/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/cfr/src/main/res/values-cy/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/cfr/src/main/res/values-da/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/cfr/src/main/res/values-de/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/cfr/src/main/res/values-dsb/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/cfr/src/main/res/values-el/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/cfr/src/main/res/values-en-rCA/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/cfr/src/main/res/values-en-rGB/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/cfr/src/main/res/values-eo/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/cfr/src/main/res/values-es-rAR/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/cfr/src/main/res/values-es-rCL/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/cfr/src/main/res/values-es-rES/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/cfr/src/main/res/values-es-rMX/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/cfr/src/main/res/values-es/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/cfr/src/main/res/values-et/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/cfr/src/main/res/values-eu/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/cfr/src/main/res/values-fa/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/cfr/src/main/res/values-fi/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/cfr/src/main/res/values-fr/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/cfr/src/main/res/values-fur/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/cfr/src/main/res/values-fy-rNL/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/cfr/src/main/res/values-gd/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/cfr/src/main/res/values-gl/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/cfr/src/main/res/values-gn/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/cfr/src/main/res/values-hr/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/cfr/src/main/res/values-hsb/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/cfr/src/main/res/values-hu/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/cfr/src/main/res/values-hy-rAM/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/cfr/src/main/res/values-ia/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/cfr/src/main/res/values-in/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/cfr/src/main/res/values-is/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/cfr/src/main/res/values-it/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/cfr/src/main/res/values-iw/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/cfr/src/main/res/values-ja/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/cfr/src/main/res/values-ka/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/cfr/src/main/res/values-kaa/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/cfr/src/main/res/values-kab/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/cfr/src/main/res/values-kk/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/cfr/src/main/res/values-kmr/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/cfr/src/main/res/values-ko/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/cfr/src/main/res/values-lo/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/cfr/src/main/res/values-lt/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/cfr/src/main/res/values-nb-rNO/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/cfr/src/main/res/values-nl/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/cfr/src/main/res/values-nn-rNO/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/cfr/src/main/res/values-oc/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/cfr/src/main/res/values-pa-rIN/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/cfr/src/main/res/values-pa-rPK/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/cfr/src/main/res/values-pl/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/cfr/src/main/res/values-pt-rBR/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/cfr/src/main/res/values-pt-rPT/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/cfr/src/main/res/values-rm/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/cfr/src/main/res/values-ru/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/cfr/src/main/res/values-sat/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/cfr/src/main/res/values-sc/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/cfr/src/main/res/values-si/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/cfr/src/main/res/values-sk/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/cfr/src/main/res/values-skr/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/cfr/src/main/res/values-sl/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/cfr/src/main/res/values-sq/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/cfr/src/main/res/values-sr/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/cfr/src/main/res/values-su/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/cfr/src/main/res/values-sv-rSE/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/cfr/src/main/res/values-szl/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/cfr/src/main/res/values-tg/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/cfr/src/main/res/values-th/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/cfr/src/main/res/values-tr/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/cfr/src/main/res/values-trs/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/cfr/src/main/res/values-tt/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/cfr/src/main/res/values-ug/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/cfr/src/main/res/values-uk/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/cfr/src/main/res/values-uz/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/cfr/src/main/res/values-vec/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/cfr/src/main/res/values-vi/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/cfr/src/main/res/values-zh-rCN/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/cfr/src/main/res/values-zh-rTW/strings.xml5
-rw-r--r--mobile/android/android-components/components/compose/cfr/src/main/res/values/strings.xml8
-rw-r--r--mobile/android/android-components/components/compose/cfr/src/test/java/mozilla/components/compose/cfr/CFRPopupFullscreenLayoutTest.kt561
-rw-r--r--mobile/android/android-components/components/compose/cfr/src/test/java/mozilla/components/compose/cfr/helper/DisplayOrientationListenerTest.kt136
-rw-r--r--mobile/android/android-components/components/compose/cfr/src/test/java/mozilla/components/compose/cfr/helper/ViewDetachedListenerTest.kt32
-rw-r--r--mobile/android/android-components/components/compose/cfr/src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker2
-rw-r--r--mobile/android/android-components/components/compose/engine/README.md19
-rw-r--r--mobile/android/android-components/components/compose/engine/build.gradle61
-rw-r--r--mobile/android/android-components/components/compose/engine/proguard-rules.pro21
-rw-r--r--mobile/android/android-components/components/compose/engine/src/main/AndroidManifest.xml4
-rw-r--r--mobile/android/android-components/components/compose/engine/src/main/java/mozilla/components/compose/engine/WebContent.kt62
-rw-r--r--mobile/android/android-components/components/compose/engine/src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker2
-rw-r--r--mobile/android/android-components/components/compose/engine/src/test/resources/robolectric.properties1
-rw-r--r--mobile/android/android-components/components/compose/tabstray/README.md19
-rw-r--r--mobile/android/android-components/components/compose/tabstray/build.gradle58
-rw-r--r--mobile/android/android-components/components/compose/tabstray/proguard-rules.pro21
-rw-r--r--mobile/android/android-components/components/compose/tabstray/src/main/AndroidManifest.xml4
-rw-r--r--mobile/android/android-components/components/compose/tabstray/src/main/java/mozilla/components/compose/tabstray/Tab.kt97
-rw-r--r--mobile/android/android-components/components/compose/tabstray/src/main/java/mozilla/components/compose/tabstray/TabCounterButton.kt79
-rw-r--r--mobile/android/android-components/components/compose/tabstray/src/main/java/mozilla/components/compose/tabstray/TabList.kt77
-rw-r--r--mobile/android/android-components/components/compose/tabstray/src/main/res/drawable/mozac_tabcounter_background.xml15
-rw-r--r--mobile/android/android-components/components/compose/tabstray/src/main/res/values-am/strings.xml7
-rw-r--r--mobile/android/android-components/components/compose/tabstray/src/main/res/values-ar/strings.xml7
-rw-r--r--mobile/android/android-components/components/compose/tabstray/src/main/res/values-ast/strings.xml7
-rw-r--r--mobile/android/android-components/components/compose/tabstray/src/main/res/values-azb/strings.xml7
-rw-r--r--mobile/android/android-components/components/compose/tabstray/src/main/res/values-be/strings.xml7
-rw-r--r--mobile/android/android-components/components/compose/tabstray/src/main/res/values-bg/strings.xml7
-rw-r--r--mobile/android/android-components/components/compose/tabstray/src/main/res/values-br/strings.xml7
-rw-r--r--mobile/android/android-components/components/compose/tabstray/src/main/res/values-bs/strings.xml7
-rw-r--r--mobile/android/android-components/components/compose/tabstray/src/main/res/values-ca/strings.xml7
-rw-r--r--mobile/android/android-components/components/compose/tabstray/src/main/res/values-cak/strings.xml7
-rw-r--r--mobile/android/android-components/components/compose/tabstray/src/main/res/values-ceb/strings.xml7
-rw-r--r--mobile/android/android-components/components/compose/tabstray/src/main/res/values-ckb/strings.xml7
-rw-r--r--mobile/android/android-components/components/compose/tabstray/src/main/res/values-co/strings.xml7
-rw-r--r--mobile/android/android-components/components/compose/tabstray/src/main/res/values-cs/strings.xml7
-rw-r--r--mobile/android/android-components/components/compose/tabstray/src/main/res/values-cy/strings.xml7
-rw-r--r--mobile/android/android-components/components/compose/tabstray/src/main/res/values-da/strings.xml7
-rw-r--r--mobile/android/android-components/components/compose/tabstray/src/main/res/values-de/strings.xml7
-rw-r--r--mobile/android/android-components/components/compose/tabstray/src/main/res/values-dsb/strings.xml7
-rw-r--r--mobile/android/android-components/components/compose/tabstray/src/main/res/values-el/strings.xml7
-rw-r--r--mobile/android/android-components/components/compose/tabstray/src/main/res/values-en-rCA/strings.xml7
-rw-r--r--mobile/android/android-components/components/compose/tabstray/src/main/res/values-en-rGB/strings.xml7
-rw-r--r--mobile/android/android-components/components/compose/tabstray/src/main/res/values-eo/strings.xml7
-rw-r--r--mobile/android/android-components/components/compose/tabstray/src/main/res/values-es-rAR/strings.xml7
-rw-r--r--mobile/android/android-components/components/compose/tabstray/src/main/res/values-es-rCL/strings.xml7
-rw-r--r--mobile/android/android-components/components/compose/tabstray/src/main/res/values-es-rES/strings.xml7
-rw-r--r--mobile/android/android-components/components/compose/tabstray/src/main/res/values-es-rMX/strings.xml7
-rw-r--r--mobile/android/android-components/components/compose/tabstray/src/main/res/values-es/strings.xml7
-rw-r--r--mobile/android/android-components/components/compose/tabstray/src/main/res/values-et/strings.xml7
-rw-r--r--mobile/android/android-components/components/compose/tabstray/src/main/res/values-eu/strings.xml7
-rw-r--r--mobile/android/android-components/components/compose/tabstray/src/main/res/values-fa/strings.xml7
-rw-r--r--mobile/android/android-components/components/compose/tabstray/src/main/res/values-fi/strings.xml7
-rw-r--r--mobile/android/android-components/components/compose/tabstray/src/main/res/values-fr/strings.xml7
-rw-r--r--mobile/android/android-components/components/compose/tabstray/src/main/res/values-fur/strings.xml7
-rw-r--r--mobile/android/android-components/components/compose/tabstray/src/main/res/values-fy-rNL/strings.xml7
-rw-r--r--mobile/android/android-components/components/compose/tabstray/src/main/res/values-gd/strings.xml7
-rw-r--r--mobile/android/android-components/components/compose/tabstray/src/main/res/values-gl/strings.xml7
-rw-r--r--mobile/android/android-components/components/compose/tabstray/src/main/res/values-gn/strings.xml7
-rw-r--r--mobile/android/android-components/components/compose/tabstray/src/main/res/values-hi-rIN/strings.xml7
-rw-r--r--mobile/android/android-components/components/compose/tabstray/src/main/res/values-hr/strings.xml7
-rw-r--r--mobile/android/android-components/components/compose/tabstray/src/main/res/values-hsb/strings.xml7
-rw-r--r--mobile/android/android-components/components/compose/tabstray/src/main/res/values-hu/strings.xml7
-rw-r--r--mobile/android/android-components/components/compose/tabstray/src/main/res/values-hy-rAM/strings.xml7
-rw-r--r--mobile/android/android-components/components/compose/tabstray/src/main/res/values-ia/strings.xml8
-rw-r--r--mobile/android/android-components/components/compose/tabstray/src/main/res/values-in/strings.xml7
-rw-r--r--mobile/android/android-components/components/compose/tabstray/src/main/res/values-is/strings.xml7
-rw-r--r--mobile/android/android-components/components/compose/tabstray/src/main/res/values-it/strings.xml7
-rw-r--r--mobile/android/android-components/components/compose/tabstray/src/main/res/values-iw/strings.xml7
-rw-r--r--mobile/android/android-components/components/compose/tabstray/src/main/res/values-ja/strings.xml7
-rw-r--r--mobile/android/android-components/components/compose/tabstray/src/main/res/values-ka/strings.xml7
-rw-r--r--mobile/android/android-components/components/compose/tabstray/src/main/res/values-kaa/strings.xml7
-rw-r--r--mobile/android/android-components/components/compose/tabstray/src/main/res/values-kab/strings.xml7
-rw-r--r--mobile/android/android-components/components/compose/tabstray/src/main/res/values-kk/strings.xml7
-rw-r--r--mobile/android/android-components/components/compose/tabstray/src/main/res/values-kmr/strings.xml7
-rw-r--r--mobile/android/android-components/components/compose/tabstray/src/main/res/values-ko/strings.xml7
-rw-r--r--mobile/android/android-components/components/compose/tabstray/src/main/res/values-lo/strings.xml7
-rw-r--r--mobile/android/android-components/components/compose/tabstray/src/main/res/values-lt/strings.xml7
-rw-r--r--mobile/android/android-components/components/compose/tabstray/src/main/res/values-mr/strings.xml7
-rw-r--r--mobile/android/android-components/components/compose/tabstray/src/main/res/values-my/strings.xml7
-rw-r--r--mobile/android/android-components/components/compose/tabstray/src/main/res/values-nb-rNO/strings.xml7
-rw-r--r--mobile/android/android-components/components/compose/tabstray/src/main/res/values-ne-rNP/strings.xml7
-rw-r--r--mobile/android/android-components/components/compose/tabstray/src/main/res/values-nl/strings.xml7
-rw-r--r--mobile/android/android-components/components/compose/tabstray/src/main/res/values-nn-rNO/strings.xml7
-rw-r--r--mobile/android/android-components/components/compose/tabstray/src/main/res/values-oc/strings.xml7
-rw-r--r--mobile/android/android-components/components/compose/tabstray/src/main/res/values-pa-rIN/strings.xml7
-rw-r--r--mobile/android/android-components/components/compose/tabstray/src/main/res/values-pa-rPK/strings.xml7
-rw-r--r--mobile/android/android-components/components/compose/tabstray/src/main/res/values-pl/strings.xml7
-rw-r--r--mobile/android/android-components/components/compose/tabstray/src/main/res/values-pt-rBR/strings.xml7
-rw-r--r--mobile/android/android-components/components/compose/tabstray/src/main/res/values-pt-rPT/strings.xml7
-rw-r--r--mobile/android/android-components/components/compose/tabstray/src/main/res/values-rm/strings.xml7
-rw-r--r--mobile/android/android-components/components/compose/tabstray/src/main/res/values-ro/strings.xml7
-rw-r--r--mobile/android/android-components/components/compose/tabstray/src/main/res/values-ru/strings.xml7
-rw-r--r--mobile/android/android-components/components/compose/tabstray/src/main/res/values-sat/strings.xml7
-rw-r--r--mobile/android/android-components/components/compose/tabstray/src/main/res/values-sc/strings.xml7
-rw-r--r--mobile/android/android-components/components/compose/tabstray/src/main/res/values-si/strings.xml7
-rw-r--r--mobile/android/android-components/components/compose/tabstray/src/main/res/values-sk/strings.xml7
-rw-r--r--mobile/android/android-components/components/compose/tabstray/src/main/res/values-skr/strings.xml7
-rw-r--r--mobile/android/android-components/components/compose/tabstray/src/main/res/values-sl/strings.xml7
-rw-r--r--mobile/android/android-components/components/compose/tabstray/src/main/res/values-sq/strings.xml7
-rw-r--r--mobile/android/android-components/components/compose/tabstray/src/main/res/values-sr/strings.xml7
-rw-r--r--mobile/android/android-components/components/compose/tabstray/src/main/res/values-su/strings.xml7
-rw-r--r--mobile/android/android-components/components/compose/tabstray/src/main/res/values-sv-rSE/strings.xml7
-rw-r--r--mobile/android/android-components/components/compose/tabstray/src/main/res/values-szl/strings.xml7
-rw-r--r--mobile/android/android-components/components/compose/tabstray/src/main/res/values-ta/strings.xml7
-rw-r--r--mobile/android/android-components/components/compose/tabstray/src/main/res/values-tg/strings.xml7
-rw-r--r--mobile/android/android-components/components/compose/tabstray/src/main/res/values-th/strings.xml7
-rw-r--r--mobile/android/android-components/components/compose/tabstray/src/main/res/values-tl/strings.xml7
-rw-r--r--mobile/android/android-components/components/compose/tabstray/src/main/res/values-tr/strings.xml7
-rw-r--r--mobile/android/android-components/components/compose/tabstray/src/main/res/values-trs/strings.xml7
-rw-r--r--mobile/android/android-components/components/compose/tabstray/src/main/res/values-tt/strings.xml7
-rw-r--r--mobile/android/android-components/components/compose/tabstray/src/main/res/values-ug/strings.xml7
-rw-r--r--mobile/android/android-components/components/compose/tabstray/src/main/res/values-uk/strings.xml7
-rw-r--r--mobile/android/android-components/components/compose/tabstray/src/main/res/values-ur/strings.xml7
-rw-r--r--mobile/android/android-components/components/compose/tabstray/src/main/res/values-uz/strings.xml7
-rw-r--r--mobile/android/android-components/components/compose/tabstray/src/main/res/values-vec/strings.xml7
-rw-r--r--mobile/android/android-components/components/compose/tabstray/src/main/res/values-vi/strings.xml7
-rw-r--r--mobile/android/android-components/components/compose/tabstray/src/main/res/values-yo/strings.xml7
-rw-r--r--mobile/android/android-components/components/compose/tabstray/src/main/res/values-zh-rCN/strings.xml7
-rw-r--r--mobile/android/android-components/components/compose/tabstray/src/main/res/values-zh-rTW/strings.xml7
-rw-r--r--mobile/android/android-components/components/compose/tabstray/src/main/res/values/strings.xml10
-rw-r--r--mobile/android/android-components/components/compose/tabstray/src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker2
-rw-r--r--mobile/android/android-components/components/compose/tabstray/src/test/resources/robolectric.properties1
446 files changed, 6321 insertions, 0 deletions
diff --git a/mobile/android/android-components/components/compose/awesomebar/README.md b/mobile/android/android-components/components/compose/awesomebar/README.md
new file mode 100644
index 0000000000..6d1e606e39
--- /dev/null
+++ b/mobile/android/android-components/components/compose/awesomebar/README.md
@@ -0,0 +1,19 @@
+# [Android Components](../../../README.md) > Compose > Awesomebar
+
+A customizable awesomebar for browsers using Jetpack Compose.
+
+## Usage
+
+### Setting up the dependency
+
+Use Gradle to download the library from [maven.mozilla.org](https://maven.mozilla.org/) ([Setup repository](../../../README.md#maven-repository)):
+
+```Groovy
+implementation "org.mozilla.components:compose-awesomebar:{latest-version}"
+```
+
+## License
+
+ 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/
diff --git a/mobile/android/android-components/components/compose/awesomebar/build.gradle b/mobile/android/android-components/components/compose/awesomebar/build.gradle
new file mode 100644
index 0000000000..65691db0e5
--- /dev/null
+++ b/mobile/android/android-components/components/compose/awesomebar/build.gradle
@@ -0,0 +1,68 @@
+/* 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 org.jetbrains.kotlin.gradle.tasks.KotlinCompile
+
+apply plugin: 'com.android.library'
+apply plugin: 'kotlin-android'
+apply plugin: 'kotlin-parcelize'
+
+android {
+ defaultConfig {
+ minSdkVersion config.minSdkVersion
+ compileSdk config.compileSdkVersion
+ targetSdkVersion config.targetSdkVersion
+ }
+
+ buildTypes {
+ release {
+ minifyEnabled false
+ proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
+ }
+ }
+
+ buildFeatures {
+ compose true
+ }
+
+ composeOptions {
+ kotlinCompilerExtensionVersion = Versions.compose_compiler
+ }
+
+ namespace 'mozilla.components.compose.browser.awesomebar'
+
+}
+
+tasks.withType(KotlinCompile).configureEach {
+ kotlinOptions.freeCompilerArgs += "-Xjvm-default=all"
+}
+
+dependencies {
+ implementation platform(ComponentsDependencies.androidx_compose_bom)
+ implementation project(":concept-awesomebar")
+ implementation project(":browser-state")
+ implementation project(":support-base")
+ implementation project(":support-utils")
+ implementation project(":ui-icons")
+
+ implementation ComponentsDependencies.kotlin_coroutines
+
+ implementation ComponentsDependencies.androidx_core_ktx
+ implementation ComponentsDependencies.androidx_compose_ui
+ implementation ComponentsDependencies.androidx_compose_ui_tooling_preview
+ implementation ComponentsDependencies.androidx_compose_foundation
+ implementation ComponentsDependencies.androidx_compose_material
+
+ debugImplementation ComponentsDependencies.androidx_compose_ui_tooling
+
+ testImplementation project(':support-test')
+ testImplementation ComponentsDependencies.androidx_compose_ui_test
+ testImplementation ComponentsDependencies.androidx_test_core
+ testImplementation ComponentsDependencies.androidx_test_junit
+ testImplementation ComponentsDependencies.testing_robolectric
+}
+
+apply from: '../../../android-lint.gradle'
+apply from: '../../../publish.gradle'
+ext.configurePublish(config.componentsGroupId, archivesBaseName, project.ext.description)
diff --git a/mobile/android/android-components/components/compose/awesomebar/proguard-rules.pro b/mobile/android/android-components/components/compose/awesomebar/proguard-rules.pro
new file mode 100644
index 0000000000..f1b424510d
--- /dev/null
+++ b/mobile/android/android-components/components/compose/awesomebar/proguard-rules.pro
@@ -0,0 +1,21 @@
+# Add project specific ProGuard rules here.
+# You can control the set of applied configuration files using the
+# proguardFiles setting in build.gradle.
+#
+# For more details, see
+# http://developer.android.com/guide/developing/tools/proguard.html
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+# public *;
+#}
+
+# Uncomment this to preserve the line number information for
+# debugging stack traces.
+#-keepattributes SourceFile,LineNumberTable
+
+# If you keep the line number information, uncomment this to
+# hide the original source file name.
+#-renamesourcefileattribute SourceFile
diff --git a/mobile/android/android-components/components/compose/awesomebar/src/main/AndroidManifest.xml b/mobile/android/android-components/components/compose/awesomebar/src/main/AndroidManifest.xml
new file mode 100644
index 0000000000..e16cda1d34
--- /dev/null
+++ b/mobile/android/android-components/components/compose/awesomebar/src/main/AndroidManifest.xml
@@ -0,0 +1,4 @@
+<!-- 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/. -->
+<manifest />
diff --git a/mobile/android/android-components/components/compose/awesomebar/src/main/java/mozilla/components/compose/browser/awesomebar/AwesomeBar.kt b/mobile/android/android-components/components/compose/awesomebar/src/main/java/mozilla/components/compose/browser/awesomebar/AwesomeBar.kt
new file mode 100644
index 0000000000..a5d3f10e2a
--- /dev/null
+++ b/mobile/android/android-components/components/compose/awesomebar/src/main/java/mozilla/components/compose/browser/awesomebar/AwesomeBar.kt
@@ -0,0 +1,121 @@
+/* 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 mozilla.components.compose.browser.awesomebar
+
+import android.annotation.SuppressLint
+import androidx.compose.foundation.background
+import androidx.compose.foundation.layout.Column
+import androidx.compose.foundation.layout.fillMaxWidth
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.LaunchedEffect
+import androidx.compose.runtime.derivedStateOf
+import androidx.compose.runtime.remember
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.platform.testTag
+import mozilla.components.compose.browser.awesomebar.internal.SuggestionFetcher
+import mozilla.components.compose.browser.awesomebar.internal.Suggestions
+import mozilla.components.concept.awesomebar.AwesomeBar
+import mozilla.components.concept.base.profiler.Profiler
+
+/**
+ * An awesome bar displaying suggestions from the list of provided [AwesomeBar.SuggestionProvider]s.
+ *
+ * @param text The text entered by the user and for which the AwesomeBar should show suggestions for.
+ * @param colors The color scheme the AwesomeBar will use for the UI.
+ * @param providers The list of suggestion providers to query whenever the [text] changes.
+ * @param orientation Whether the AwesomeBar is oriented to the top or the bottom of the screen.
+ * @param onSuggestionClicked Gets invoked whenever the user clicks on a suggestion in the AwesomeBar.
+ * @param onAutoComplete Gets invoked when the user clicks on the "autocomplete" icon of a suggestion.
+ * @param onVisibilityStateUpdated Gets invoked when the list of currently displayed suggestions changes.
+ * @param onScroll Gets invoked at the beginning of the user performing a scroll gesture.
+ */
+@Composable
+fun AwesomeBar(
+ text: String,
+ colors: AwesomeBarColors = AwesomeBarDefaults.colors(),
+ providers: List<AwesomeBar.SuggestionProvider>,
+ orientation: AwesomeBarOrientation = AwesomeBarOrientation.TOP,
+ onSuggestionClicked: (AwesomeBar.Suggestion) -> Unit,
+ onAutoComplete: (AwesomeBar.Suggestion) -> Unit,
+ onVisibilityStateUpdated: (AwesomeBar.VisibilityState) -> Unit = {},
+ onScroll: () -> Unit = {},
+ profiler: Profiler? = null,
+) {
+ val groups = remember(providers) {
+ providers
+ .groupBy { it.groupTitle() }
+ .map {
+ AwesomeBar.SuggestionProviderGroup(
+ providers = it.value,
+ title = it.key,
+ )
+ }
+ }
+
+ AwesomeBar(
+ text = text,
+ colors = colors,
+ groups = groups,
+ orientation = orientation,
+ onSuggestionClicked = { _, suggestion -> onSuggestionClicked(suggestion) },
+ onAutoComplete = { _, suggestion -> onAutoComplete(suggestion) },
+ onVisibilityStateUpdated = onVisibilityStateUpdated,
+ onScroll = onScroll,
+ profiler = profiler,
+ )
+}
+
+/**
+ * An awesome bar displaying suggestions in groups from the list of provided [AwesomeBar.SuggestionProviderGroup]s.
+ *
+ * @param text The text entered by the user and for which the AwesomeBar should show suggestions for.
+ * @param colors The color scheme the AwesomeBar will use for the UI.
+ * @param groups The list of groups of suggestion providers to query whenever the [text] changes.
+ * @param orientation Whether the AwesomeBar is oriented to the top or the bottom of the screen.
+ * @param onSuggestionClicked Gets invoked whenever the user clicks on a suggestion in the AwesomeBar.
+ * @param onAutoComplete Gets invoked when the user clicks on the "autocomplete" icon of a suggestion.
+ * @param onVisibilityStateUpdated Gets invoked when the list of currently displayed suggestions changes.
+ * @param onScroll Gets invoked at the beginning of the user performing a scroll gesture.
+ */
+@Composable
+fun AwesomeBar(
+ text: String,
+ colors: AwesomeBarColors = AwesomeBarDefaults.colors(),
+ groups: List<AwesomeBar.SuggestionProviderGroup>,
+ orientation: AwesomeBarOrientation = AwesomeBarOrientation.TOP,
+ onSuggestionClicked: (AwesomeBar.SuggestionProviderGroup, AwesomeBar.Suggestion) -> Unit,
+ onAutoComplete: (AwesomeBar.SuggestionProviderGroup, AwesomeBar.Suggestion) -> Unit,
+ onVisibilityStateUpdated: (AwesomeBar.VisibilityState) -> Unit = {},
+ onScroll: () -> Unit = {},
+ profiler: Profiler? = null,
+) {
+ Column(
+ modifier = Modifier
+ .fillMaxWidth()
+ .testTag("mozac.awesomebar")
+ .background(colors.background),
+ ) {
+ val fetcher = remember(groups) { SuggestionFetcher(groups, profiler) }
+
+ // This state does not need to be remembered, because it can change if the providers list changes.
+ @SuppressLint("UnrememberedMutableState")
+ val suggestions = derivedStateOf { fetcher.state.value }.value.toList()
+ .sortedByDescending { it.first.priority }.toMap(LinkedHashMap())
+
+ LaunchedEffect(text, fetcher) {
+ fetcher.fetch(text)
+ }
+
+ Suggestions(
+ suggestions,
+ colors,
+ orientation,
+ onSuggestionClicked,
+ onAutoComplete,
+ onVisibilityStateUpdated,
+ onScroll,
+ )
+ }
+}
diff --git a/mobile/android/android-components/components/compose/awesomebar/src/main/java/mozilla/components/compose/browser/awesomebar/AwesomeBarColors.kt b/mobile/android/android-components/components/compose/awesomebar/src/main/java/mozilla/components/compose/browser/awesomebar/AwesomeBarColors.kt
new file mode 100644
index 0000000000..fe31e36153
--- /dev/null
+++ b/mobile/android/android-components/components/compose/awesomebar/src/main/java/mozilla/components/compose/browser/awesomebar/AwesomeBarColors.kt
@@ -0,0 +1,18 @@
+/* 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 mozilla.components.compose.browser.awesomebar
+
+import androidx.compose.ui.graphics.Color
+
+/**
+ * Represents the colors used by the AwesomeBar.
+ */
+data class AwesomeBarColors(
+ val background: Color,
+ val title: Color,
+ val description: Color,
+ val autocompleteIcon: Color,
+ val groupTitle: Color,
+)
diff --git a/mobile/android/android-components/components/compose/awesomebar/src/main/java/mozilla/components/compose/browser/awesomebar/AwesomeBarDefaults.kt b/mobile/android/android-components/components/compose/awesomebar/src/main/java/mozilla/components/compose/browser/awesomebar/AwesomeBarDefaults.kt
new file mode 100644
index 0000000000..a804ad86df
--- /dev/null
+++ b/mobile/android/android-components/components/compose/awesomebar/src/main/java/mozilla/components/compose/browser/awesomebar/AwesomeBarDefaults.kt
@@ -0,0 +1,39 @@
+/* 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 mozilla.components.compose.browser.awesomebar
+
+import androidx.compose.material.ContentAlpha
+import androidx.compose.material.MaterialTheme
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.graphics.Color
+
+/**
+ * Contains the default values used by the AwesomeBar.
+ */
+object AwesomeBarDefaults {
+ /**
+ * Creates an [AwesomeBarColors] that represents the default colors used in an AwesomeBar.
+ *
+ * @param background The background of the AwesomeBar.
+ * @param title The text color for the title of a suggestion.
+ * @param description The text color for the description of a suggestion.
+ */
+ @Composable
+ fun colors(
+ background: Color = MaterialTheme.colors.background,
+ title: Color = MaterialTheme.colors.onBackground,
+ description: Color = MaterialTheme.colors.onBackground.copy(
+ alpha = ContentAlpha.medium,
+ ),
+ autocompleteIcon: Color = MaterialTheme.colors.onSurface,
+ groupTitle: Color = MaterialTheme.colors.onBackground,
+ ) = AwesomeBarColors(
+ background,
+ title,
+ description,
+ autocompleteIcon,
+ groupTitle,
+ )
+}
diff --git a/mobile/android/android-components/components/compose/awesomebar/src/main/java/mozilla/components/compose/browser/awesomebar/AwesomeBarFacts.kt b/mobile/android/android-components/components/compose/awesomebar/src/main/java/mozilla/components/compose/browser/awesomebar/AwesomeBarFacts.kt
new file mode 100644
index 0000000000..bfa748cb06
--- /dev/null
+++ b/mobile/android/android-components/components/compose/awesomebar/src/main/java/mozilla/components/compose/browser/awesomebar/AwesomeBarFacts.kt
@@ -0,0 +1,44 @@
+/* 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 mozilla.components.compose.browser.awesomebar
+
+import mozilla.components.support.base.Component
+import mozilla.components.support.base.facts.Action
+import mozilla.components.support.base.facts.Fact
+import mozilla.components.support.base.facts.collect
+
+/**
+ * Facts emitted for telemetry related to the AwesomeBar composable.
+ */
+object AwesomeBarFacts {
+ /**
+ * Specific types of telemetry items.
+ */
+ object Items {
+ const val PROVIDER_DURATION = "provider_duration"
+ }
+
+ /**
+ * Keys used to record metadata about [Items].
+ */
+ object MetadataKeys {
+ const val DURATION_PAIR = "duration_pair"
+ }
+
+ internal fun emitAwesomeBarFact(
+ action: Action,
+ item: String,
+ value: String? = null,
+ metadata: Map<String, Any>? = null,
+ ) {
+ Fact(
+ Component.COMPOSE_AWESOMEBAR,
+ action,
+ item,
+ value,
+ metadata,
+ ).collect()
+ }
+}
diff --git a/mobile/android/android-components/components/compose/awesomebar/src/main/java/mozilla/components/compose/browser/awesomebar/AwesomeBarOrientation.kt b/mobile/android/android-components/components/compose/awesomebar/src/main/java/mozilla/components/compose/browser/awesomebar/AwesomeBarOrientation.kt
new file mode 100644
index 0000000000..246f917c1e
--- /dev/null
+++ b/mobile/android/android-components/components/compose/awesomebar/src/main/java/mozilla/components/compose/browser/awesomebar/AwesomeBarOrientation.kt
@@ -0,0 +1,13 @@
+/* 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 mozilla.components.compose.browser.awesomebar
+
+/**
+ * The orientation of the AwesomeBar, whether it's oriented to the bottom or the top.
+ */
+enum class AwesomeBarOrientation {
+ TOP,
+ BOTTOM,
+}
diff --git a/mobile/android/android-components/components/compose/awesomebar/src/main/java/mozilla/components/compose/browser/awesomebar/internal/Suggestion.kt b/mobile/android/android-components/components/compose/awesomebar/src/main/java/mozilla/components/compose/browser/awesomebar/internal/Suggestion.kt
new file mode 100644
index 0000000000..275e336414
--- /dev/null
+++ b/mobile/android/android-components/components/compose/awesomebar/src/main/java/mozilla/components/compose/browser/awesomebar/internal/Suggestion.kt
@@ -0,0 +1,184 @@
+/* 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 mozilla.components.compose.browser.awesomebar.internal
+
+import android.graphics.Bitmap
+import android.graphics.drawable.Drawable
+import androidx.compose.foundation.Image
+import androidx.compose.foundation.clickable
+import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.layout.Column
+import androidx.compose.foundation.layout.IntrinsicSize
+import androidx.compose.foundation.layout.Row
+import androidx.compose.foundation.layout.defaultMinSize
+import androidx.compose.foundation.layout.height
+import androidx.compose.foundation.layout.padding
+import androidx.compose.foundation.layout.size
+import androidx.compose.foundation.layout.width
+import androidx.compose.foundation.shape.RoundedCornerShape
+import androidx.compose.material.Text
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.Alignment
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.draw.clip
+import androidx.compose.ui.draw.rotate
+import androidx.compose.ui.graphics.ColorFilter
+import androidx.compose.ui.graphics.asImageBitmap
+import androidx.compose.ui.layout.ContentScale
+import androidx.compose.ui.platform.testTag
+import androidx.compose.ui.res.painterResource
+import androidx.compose.ui.res.stringResource
+import androidx.compose.ui.text.style.TextOverflow
+import androidx.compose.ui.unit.dp
+import androidx.compose.ui.unit.sp
+import androidx.core.graphics.drawable.toBitmap
+import mozilla.components.compose.browser.awesomebar.AwesomeBarColors
+import mozilla.components.compose.browser.awesomebar.AwesomeBarOrientation
+import mozilla.components.compose.browser.awesomebar.R
+import mozilla.components.concept.awesomebar.AwesomeBar
+import mozilla.components.ui.icons.R as iconsR
+
+// We only show one row of text, covering at max screen width.
+// Limit bigger texts that could cause slowdowns or even crashes.
+private const val SUGGESTION_TEXT_MAX_LENGTH = 100
+
+@Composable
+internal fun Suggestion(
+ suggestion: AwesomeBar.Suggestion,
+ colors: AwesomeBarColors,
+ orientation: AwesomeBarOrientation,
+ onSuggestionClicked: () -> Unit,
+ onAutoComplete: () -> Unit,
+) {
+ Row(
+ modifier = Modifier
+ .clickable { onSuggestionClicked() }
+ .defaultMinSize(minHeight = 56.dp)
+ .testTag("mozac.awesomebar.suggestion")
+ .padding(start = 16.dp, top = 8.dp, bottom = 8.dp, end = 8.dp),
+ ) {
+ val icon = suggestion.icon
+ if (icon != null) {
+ SuggestionIcon(
+ icon = icon,
+ indicator = suggestion.indicatorIcon,
+ )
+ }
+ SuggestionTitleAndDescription(
+ title = suggestion.title?.take(SUGGESTION_TEXT_MAX_LENGTH),
+ description = suggestion.description?.take(SUGGESTION_TEXT_MAX_LENGTH),
+ colors = colors,
+ modifier = Modifier
+ .weight(1f)
+ .align(Alignment.CenterVertically),
+ )
+ if (suggestion.editSuggestion != null) {
+ AutocompleteButton(
+ onAutoComplete = onAutoComplete,
+ orientation = orientation,
+ colors = colors,
+ modifier = Modifier.align(Alignment.CenterVertically),
+ )
+ }
+ }
+}
+
+@Composable
+private fun SuggestionTitleAndDescription(
+ title: String?,
+ description: String?,
+ colors: AwesomeBarColors,
+ modifier: Modifier = Modifier,
+) {
+ Column(
+ modifier = modifier,
+ ) {
+ Text(
+ text = if (title.isNullOrEmpty()) {
+ description ?: ""
+ } else {
+ title
+ },
+ color = colors.title,
+ fontSize = 15.sp,
+ maxLines = 1,
+ overflow = TextOverflow.Ellipsis,
+ modifier = Modifier
+ .width(IntrinsicSize.Max)
+ .padding(start = 2.dp, end = 8.dp),
+ )
+ if (description?.isNotEmpty() == true) {
+ Text(
+ text = description,
+ color = colors.description,
+ fontSize = 12.sp,
+ maxLines = 1,
+ overflow = TextOverflow.Ellipsis,
+ modifier = Modifier
+ .width(IntrinsicSize.Max)
+ .padding(start = 2.dp, end = 8.dp),
+ )
+ }
+ }
+}
+
+@Composable
+private fun SuggestionIcon(
+ icon: Bitmap,
+ indicator: Drawable?,
+) {
+ Box(
+ modifier = Modifier
+ .width(30.dp)
+ .height(38.dp),
+ ) {
+ Image(
+ icon.asImageBitmap(),
+ contentDescription = null,
+ modifier = Modifier
+ .padding(top = 8.dp)
+ .clip(RoundedCornerShape(2.dp))
+ .width(24.dp)
+ .height(24.dp),
+ contentScale = ContentScale.Crop,
+ )
+ if (indicator != null) {
+ Image(
+ indicator.toBitmap().asImageBitmap(),
+ contentDescription = null,
+ modifier = Modifier
+ .padding(top = 22.dp, start = 14.dp)
+ .width(16.dp)
+ .height(16.dp),
+ )
+ }
+ }
+}
+
+@Composable
+@Suppress("MagicNumber")
+private fun AutocompleteButton(
+ onAutoComplete: () -> Unit,
+ colors: AwesomeBarColors,
+ orientation: AwesomeBarOrientation,
+ modifier: Modifier,
+) {
+ Image(
+ painterResource(iconsR.drawable.mozac_ic_append_up_left_24),
+ colorFilter = ColorFilter.tint(colors.autocompleteIcon),
+ contentDescription = stringResource(R.string.mozac_browser_awesomebar_edit_suggestion),
+ modifier = modifier
+ .size(48.dp)
+ .rotate(
+ if (orientation == AwesomeBarOrientation.BOTTOM) {
+ 270f
+ } else {
+ 0f
+ },
+ )
+ .clickable { onAutoComplete() }
+ .padding(12.dp),
+ )
+}
diff --git a/mobile/android/android-components/components/compose/awesomebar/src/main/java/mozilla/components/compose/browser/awesomebar/internal/SuggestionFetcher.kt b/mobile/android/android-components/components/compose/awesomebar/src/main/java/mozilla/components/compose/browser/awesomebar/internal/SuggestionFetcher.kt
new file mode 100644
index 0000000000..354d2a25c5
--- /dev/null
+++ b/mobile/android/android-components/components/compose/awesomebar/src/main/java/mozilla/components/compose/browser/awesomebar/internal/SuggestionFetcher.kt
@@ -0,0 +1,160 @@
+/* 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 mozilla.components.compose.browser.awesomebar.internal
+
+import android.os.SystemClock
+import androidx.annotation.VisibleForTesting
+import androidx.compose.runtime.RememberObserver
+import androidx.compose.runtime.mutableStateOf
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.Job
+import kotlinx.coroutines.asCoroutineDispatcher
+import kotlinx.coroutines.launch
+import mozilla.components.compose.browser.awesomebar.AwesomeBarFacts
+import mozilla.components.compose.browser.awesomebar.AwesomeBarFacts.emitAwesomeBarFact
+import mozilla.components.concept.awesomebar.AwesomeBar
+import mozilla.components.concept.base.profiler.Profiler
+import mozilla.components.support.base.facts.Action
+import mozilla.components.support.base.utils.NamedThreadFactory
+import mozilla.components.support.utils.ThreadUtils
+import java.util.concurrent.Executors
+
+/**
+ * Class responsible for fetching search suggestions and exposing a [state] to observe the current
+ * list of suggestions from a composable.
+ */
+internal class SuggestionFetcher(
+ private val groups: List<AwesomeBar.SuggestionProviderGroup>,
+ private val profiler: Profiler?,
+) : RememberObserver {
+ private val dispatcher = Executors.newFixedThreadPool(
+ groups.fold(0, { acc, group -> acc + group.providers.size }),
+ NamedThreadFactory("SuggestionFetcher"),
+ ).asCoroutineDispatcher()
+
+ @VisibleForTesting
+ internal var fetchJob: Job? = null
+
+ /**
+ * The current list of suggestions as an observable list.
+ */
+ val state = mutableStateOf<Map<AwesomeBar.SuggestionProviderGroup, List<AwesomeBar.Suggestion>>>(emptyMap())
+
+ /**
+ * Fetches suggestions for [text] from all providers in all [groups] asynchronously.
+ *
+ * The [state] property will be updated whenever new suggestions are available.
+ */
+ suspend fun fetch(text: String) {
+ profiler?.addMarker("SuggestionFetcher.fetch") // DO NOT ADD ANYTHING ABOVE THIS addMarker CALL.
+
+ fetchJob?.cancel()
+
+ fetchJob = CoroutineScope(dispatcher).launch {
+ groups.forEach { group ->
+ group.providers.forEach { provider ->
+ val profilerStartTime = profiler?.getProfilerTime() // DO NOT ADD ANYTHING ABOVE getProfilerTime.
+ launch(dispatcher) { fetchFrom(group, provider, text, profilerStartTime) }
+ }
+ }
+ }
+ }
+
+ /**
+ * Fetches suggestions from [provider].
+ */
+ @VisibleForTesting
+ internal suspend fun fetchFrom(
+ group: AwesomeBar.SuggestionProviderGroup,
+ provider: AwesomeBar.SuggestionProvider,
+ text: String,
+ profilerStartTime: Double?,
+ ) {
+ // At this point, we have a timing value for a provider.
+ // We have a choice here - we can try grouping different timings together for a
+ // single user input value, or we can just treat them as entirely independent values.
+ // These timings are correlated with each other in a sense that they act on the same
+ // inputs, and are executed at the same time. However, our goal here is to track performance
+ // of the providers. Each provider acts independently from another; recording their performance
+ // at an individual level will allow us to track that performance over time.
+ // Tracked value will be reflected both in perceived user experience (how quickly results from
+ // a provider show up), and in a purely technical interpretation of how quickly providers
+ // fulfill requests.
+ // Grouping also poses timing challenges - as user is typing, we're trying to cancel these
+ // provider requests. Given that each request can take an arbitrary amount of time to execute,
+ // grouping correctly becomes tricky and we run a risk of omitting certain values - or, of
+ // adding a bunch of complexity just for the sake of "correct grouping".
+ val start = SystemClock.elapsedRealtimeNanos()
+ val suggestions = provider.onInputChanged(text)
+ val end = SystemClock.elapsedRealtimeNanos()
+ emitProviderQueryTimingFact(provider, timingNs = end - start)
+
+ processResultFrom(group, provider, suggestions, profilerStartTime)
+ }
+
+ /**
+ * Updates [state] to include the [suggestions] from [provider].
+ */
+ @Synchronized
+ @VisibleForTesting
+ internal fun processResultFrom(
+ group: AwesomeBar.SuggestionProviderGroup,
+ provider: AwesomeBar.SuggestionProvider,
+ suggestions: List<AwesomeBar.Suggestion>,
+ profilerStartTime: Double?,
+ ) {
+ val suggestionMap = state.value
+
+ val updatedSuggestions = (suggestionMap[group] ?: emptyList())
+ .filter { suggestion -> suggestion.provider != provider }
+ .toMutableList()
+
+ updatedSuggestions.addAll(suggestions)
+ updatedSuggestions.sortByDescending { suggestion -> suggestion.score }
+
+ if (updatedSuggestions.isNotEmpty()) {
+ group.priority = updatedSuggestions[0].score
+ }
+
+ val updatedSuggestionMap = suggestionMap.toMutableMap()
+ updatedSuggestionMap[group] = updatedSuggestions
+ state.value = updatedSuggestionMap
+ val profilerEndTime = profiler?.getProfilerTime() // THIS MUST OCCUR RIGHT AFTER STATE UPDATE.
+
+ // Markers can only be added on the main thread right now.
+ profiler?.let {
+ ThreadUtils.postToMainThread {
+ profiler.addMarker(
+ "Suggestion update",
+ profilerStartTime,
+ profilerEndTime,
+ provider::class.simpleName,
+ )
+ }
+ }
+ }
+
+ override fun onAbandoned() {
+ dispatcher.close()
+ }
+
+ override fun onForgotten() {
+ dispatcher.close()
+ }
+
+ override fun onRemembered() = Unit
+}
+
+@Suppress("MagicNumber")
+internal fun emitProviderQueryTimingFact(provider: AwesomeBar.SuggestionProvider, timingNs: Long) {
+ emitAwesomeBarFact(
+ Action.INTERACTION,
+ AwesomeBarFacts.Items.PROVIDER_DURATION,
+ metadata = mapOf(
+ // We only care about millisecond precision here, so convert from ns to ms before emitting.
+ AwesomeBarFacts.MetadataKeys.DURATION_PAIR to (provider to (timingNs / 1_000_000L)),
+ ),
+ )
+}
diff --git a/mobile/android/android-components/components/compose/awesomebar/src/main/java/mozilla/components/compose/browser/awesomebar/internal/SuggestionGroup.kt b/mobile/android/android-components/components/compose/awesomebar/src/main/java/mozilla/components/compose/browser/awesomebar/internal/SuggestionGroup.kt
new file mode 100644
index 0000000000..0d76d0c21a
--- /dev/null
+++ b/mobile/android/android-components/components/compose/awesomebar/src/main/java/mozilla/components/compose/browser/awesomebar/internal/SuggestionGroup.kt
@@ -0,0 +1,35 @@
+/* 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 mozilla.components.compose.browser.awesomebar.internal
+
+import androidx.compose.foundation.layout.fillMaxWidth
+import androidx.compose.foundation.layout.padding
+import androidx.compose.material.Text
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.unit.dp
+import androidx.compose.ui.unit.sp
+import mozilla.components.compose.browser.awesomebar.AwesomeBarColors
+
+/**
+ * Renders a header for a group of suggestions.
+ */
+@Composable
+internal fun SuggestionGroup(
+ title: String,
+ colors: AwesomeBarColors,
+) {
+ Text(
+ title,
+ color = colors.groupTitle,
+ modifier = Modifier
+ .padding(
+ vertical = 12.dp,
+ horizontal = 16.dp,
+ )
+ .fillMaxWidth(),
+ fontSize = 14.sp,
+ )
+}
diff --git a/mobile/android/android-components/components/compose/awesomebar/src/main/java/mozilla/components/compose/browser/awesomebar/internal/Suggestions.kt b/mobile/android/android-components/components/compose/awesomebar/src/main/java/mozilla/components/compose/browser/awesomebar/internal/Suggestions.kt
new file mode 100644
index 0000000000..b505d1503f
--- /dev/null
+++ b/mobile/android/android-components/components/compose/awesomebar/src/main/java/mozilla/components/compose/browser/awesomebar/internal/Suggestions.kt
@@ -0,0 +1,168 @@
+/* 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 mozilla.components.compose.browser.awesomebar.internal
+
+import android.os.Parcelable
+import androidx.compose.foundation.lazy.LazyColumn
+import androidx.compose.foundation.lazy.LazyListState
+import androidx.compose.foundation.lazy.items
+import androidx.compose.foundation.lazy.rememberLazyListState
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.LaunchedEffect
+import androidx.compose.runtime.RememberObserver
+import androidx.compose.runtime.getValue
+import androidx.compose.runtime.remember
+import androidx.compose.runtime.rememberUpdatedState
+import androidx.compose.runtime.snapshotFlow
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.platform.testTag
+import kotlinx.coroutines.flow.combine
+import kotlinx.coroutines.flow.distinctUntilChangedBy
+import kotlinx.parcelize.Parcelize
+import mozilla.components.compose.browser.awesomebar.AwesomeBarColors
+import mozilla.components.compose.browser.awesomebar.AwesomeBarOrientation
+import mozilla.components.concept.awesomebar.AwesomeBar
+
+@Composable
+internal fun Suggestions(
+ suggestions: Map<AwesomeBar.SuggestionProviderGroup, List<AwesomeBar.Suggestion>>,
+ colors: AwesomeBarColors,
+ orientation: AwesomeBarOrientation,
+ onSuggestionClicked: (AwesomeBar.SuggestionProviderGroup, AwesomeBar.Suggestion) -> Unit,
+ onAutoComplete: (AwesomeBar.SuggestionProviderGroup, AwesomeBar.Suggestion) -> Unit,
+ onVisibilityStateUpdated: (AwesomeBar.VisibilityState) -> Unit,
+ onScroll: () -> Unit,
+) {
+ val state = rememberLazyListState()
+
+ ScrollHandler(state, onScroll)
+
+ LazyColumn(
+ state = state,
+ modifier = Modifier.testTag("mozac.awesomebar.suggestions"),
+ ) {
+ suggestions.forEach { (group, suggestions) ->
+ val title = group.title
+ if (suggestions.isNotEmpty() && !title.isNullOrEmpty()) {
+ item(ItemKey.SuggestionGroup(group.id)) {
+ SuggestionGroup(title, colors)
+ }
+ }
+
+ items(
+ items = suggestions.take(group.limit),
+ key = { suggestion -> ItemKey.Suggestion(group.id, suggestion.provider.id, suggestion.id) },
+ ) { suggestion ->
+ Suggestion(
+ suggestion,
+ colors,
+ orientation,
+ onSuggestionClicked = { onSuggestionClicked(group, suggestion) },
+ onAutoComplete = { onAutoComplete(group, suggestion) },
+ )
+ }
+ }
+ }
+
+ val currentSuggestions by rememberUpdatedState(suggestions)
+ val currentOnVisibilityStateUpdated by rememberUpdatedState(onVisibilityStateUpdated)
+
+ LaunchedEffect(Unit) {
+ // This effect is launched on the initial composition, and cancelled when `Suggestions` leaves the Composition.
+ // The flow below emits new values when either the latest list of suggestions changes, or the visibility or
+ // position of any suggestion in that list changes.
+ snapshotFlow { currentSuggestions }
+ .combine(snapshotFlow { state.layoutInfo.visibleItemsInfo }) { suggestions, visibleItemsInfo ->
+ VisibleItems(
+ suggestions = suggestions,
+ visibleItemKeys = visibleItemsInfo.map { it.key as ItemKey },
+ )
+ }
+ .distinctUntilChangedBy { it.visibleItemKeys }
+ .collect { currentOnVisibilityStateUpdated(it.toVisibilityState()) }
+ }
+}
+
+/**
+ * An effect for handling scrolls in a [LazyColumn]. Will invoke [onScroll] at the beginning
+ * of a scroll gesture.
+ */
+@Composable
+private fun ScrollHandler(
+ state: LazyListState,
+ onScroll: () -> Unit,
+) {
+ val scrollInProgress = state.isScrollInProgress
+ remember(scrollInProgress) {
+ ScrollHandlerImpl(scrollInProgress, onScroll)
+ }
+}
+
+/**
+ * [RememberObserver] implementation that will make sure that [onScroll] get called only once as
+ * long as [scrollInProgress] doesn't change.
+ */
+private class ScrollHandlerImpl(
+ private val scrollInProgress: Boolean,
+ private val onScroll: () -> Unit,
+) : RememberObserver {
+ override fun onAbandoned() = Unit
+ override fun onForgotten() = Unit
+
+ override fun onRemembered() {
+ if (scrollInProgress) {
+ onScroll()
+ }
+ }
+}
+
+/**
+ * A stable, unique key for an item in the [Suggestions] list.
+ */
+internal sealed interface ItemKey {
+ @Parcelize
+ data class SuggestionGroup(val id: String) : ItemKey, Parcelable
+
+ @Parcelize
+ data class Suggestion(
+ val groupId: String,
+ val providerId: String,
+ val suggestionId: String,
+ ) : ItemKey, Parcelable
+}
+
+/**
+ * A snapshot of all the fetched suggestions to show in the [Suggestions] list, and the keys of the visible items
+ * in that list, ordered top to bottom. The intersection of the two is the current [AwesomeBar.VisibilityState].
+ */
+internal data class VisibleItems(
+ val suggestions: Map<AwesomeBar.SuggestionProviderGroup, List<AwesomeBar.Suggestion>>,
+ val visibleItemKeys: List<ItemKey>,
+) {
+ fun toVisibilityState(): AwesomeBar.VisibilityState =
+ if (visibleItemKeys.isEmpty()) {
+ AwesomeBar.VisibilityState()
+ } else {
+ AwesomeBar.VisibilityState(
+ // `suggestions` is insertion-ordered, and `toMap()` preserves that order, so the groups in
+ // `visibleProviderGroups` are in the same order as they're shown in the awesomebar.
+ visibleProviderGroups = suggestions.mapNotNull { (group, suggestions) ->
+ val visibleSuggestions = suggestions.filter { suggestion ->
+ val suggestionItemKey = ItemKey.Suggestion(
+ groupId = group.id,
+ providerId = suggestion.provider.id,
+ suggestionId = suggestion.id,
+ )
+ visibleItemKeys.contains(suggestionItemKey)
+ }
+ if (visibleSuggestions.isNotEmpty()) {
+ group to visibleSuggestions
+ } else {
+ null
+ }
+ }.toMap(),
+ )
+ }
+}
diff --git a/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-am/strings.xml b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-am/strings.xml
new file mode 100644
index 0000000000..9c811b081b
--- /dev/null
+++ b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-am/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Description for the button to accept the search suggestion and continue editing the search. -->
+ <string name="mozac_browser_awesomebar_edit_suggestion">ጥቆማን ተቀበል እና አርትዕ</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-ar/strings.xml b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-ar/strings.xml
new file mode 100644
index 0000000000..fca9a6d723
--- /dev/null
+++ b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-ar/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Description for the button to accept the search suggestion and continue editing the search. -->
+ <string name="mozac_browser_awesomebar_edit_suggestion">اقبل الاقتراح وحرّره</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-ast/strings.xml b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-ast/strings.xml
new file mode 100644
index 0000000000..c3681052e8
--- /dev/null
+++ b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-ast/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Description for the button to accept the search suggestion and continue editing the search. -->
+ <string name="mozac_browser_awesomebar_edit_suggestion">Aceptar ya editar la suxerencia</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-azb/strings.xml b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-azb/strings.xml
new file mode 100644
index 0000000000..6856d82e37
--- /dev/null
+++ b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-azb/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Description for the button to accept the search suggestion and continue editing the search. -->
+ <string name="mozac_browser_awesomebar_edit_suggestion">تکلیف‌لری قبول و دوزه‌لیش ائدین</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-ban/strings.xml b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-ban/strings.xml
new file mode 100644
index 0000000000..5592ff756e
--- /dev/null
+++ b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-ban/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Description for the button to accept the search suggestion and continue editing the search. -->
+ <string name="mozac_browser_awesomebar_edit_suggestion">Cumpu miwah uah saran</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-be/strings.xml b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-be/strings.xml
new file mode 100644
index 0000000000..7a05d5c150
--- /dev/null
+++ b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-be/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Description for the button to accept the search suggestion and continue editing the search. -->
+ <string name="mozac_browser_awesomebar_edit_suggestion">Прыняць і рэдагаваць прапанову</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-bg/strings.xml b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-bg/strings.xml
new file mode 100644
index 0000000000..fee7ceb76d
--- /dev/null
+++ b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-bg/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Description for the button to accept the search suggestion and continue editing the search. -->
+ <string name="mozac_browser_awesomebar_edit_suggestion">Приемане и редакция на предложението</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-br/strings.xml b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-br/strings.xml
new file mode 100644
index 0000000000..647d3ccc51
--- /dev/null
+++ b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-br/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Description for the button to accept the search suggestion and continue editing the search. -->
+ <string name="mozac_browser_awesomebar_edit_suggestion">Asantiñ hag embann ar c‘hinnig</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-bs/strings.xml b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-bs/strings.xml
new file mode 100644
index 0000000000..12124a89c9
--- /dev/null
+++ b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-bs/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Description for the button to accept the search suggestion and continue editing the search. -->
+ <string name="mozac_browser_awesomebar_edit_suggestion">Prihvati i uredi prijedlog</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-ca/strings.xml b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-ca/strings.xml
new file mode 100644
index 0000000000..db7a40ac20
--- /dev/null
+++ b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-ca/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Description for the button to accept the search suggestion and continue editing the search. -->
+ <string name="mozac_browser_awesomebar_edit_suggestion">Accepta i edita el suggeriment</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-cak/strings.xml b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-cak/strings.xml
new file mode 100644
index 0000000000..e0ec236f51
--- /dev/null
+++ b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-cak/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Description for the button to accept the search suggestion and continue editing the search. -->
+ <string name="mozac_browser_awesomebar_edit_suggestion">Tik\'ul chuqa\' tinuk\' chilab\'enïk</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-ceb/strings.xml b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-ceb/strings.xml
new file mode 100644
index 0000000000..33fd4d981a
--- /dev/null
+++ b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-ceb/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Description for the button to accept the search suggestion and continue editing the search. -->
+ <string name="mozac_browser_awesomebar_edit_suggestion">Dawata ug usba ang sugyot</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-ckb/strings.xml b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-ckb/strings.xml
new file mode 100644
index 0000000000..32a9820f12
--- /dev/null
+++ b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-ckb/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Description for the button to accept the search suggestion and continue editing the search. -->
+ <string name="mozac_browser_awesomebar_edit_suggestion">ڕازیبە و پێشنیارەکە دەستکاریبکە</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-co/strings.xml b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-co/strings.xml
new file mode 100644
index 0000000000..7485b24bbe
--- /dev/null
+++ b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-co/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Description for the button to accept the search suggestion and continue editing the search. -->
+ <string name="mozac_browser_awesomebar_edit_suggestion">Accettà è mudificà a suggestione</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-cs/strings.xml b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-cs/strings.xml
new file mode 100644
index 0000000000..ef57156331
--- /dev/null
+++ b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-cs/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Description for the button to accept the search suggestion and continue editing the search. -->
+ <string name="mozac_browser_awesomebar_edit_suggestion">Přijmout a upravit návrh</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-cy/strings.xml b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-cy/strings.xml
new file mode 100644
index 0000000000..8476dd6ad7
--- /dev/null
+++ b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-cy/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Description for the button to accept the search suggestion and continue editing the search. -->
+ <string name="mozac_browser_awesomebar_edit_suggestion">Derbyn a golygu awgrym</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-da/strings.xml b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-da/strings.xml
new file mode 100644
index 0000000000..4dd702661c
--- /dev/null
+++ b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-da/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Description for the button to accept the search suggestion and continue editing the search. -->
+ <string name="mozac_browser_awesomebar_edit_suggestion">Accepter og rediger forslag</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-de/strings.xml b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-de/strings.xml
new file mode 100644
index 0000000000..a3e5839463
--- /dev/null
+++ b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-de/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Description for the button to accept the search suggestion and continue editing the search. -->
+ <string name="mozac_browser_awesomebar_edit_suggestion">Vorschlag annehmen und bearbeiten</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-dsb/strings.xml b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-dsb/strings.xml
new file mode 100644
index 0000000000..6e0d778296
--- /dev/null
+++ b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-dsb/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Description for the button to accept the search suggestion and continue editing the search. -->
+ <string name="mozac_browser_awesomebar_edit_suggestion">Naraźenje akceptěrowaś a wobźěłaś</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-el/strings.xml b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-el/strings.xml
new file mode 100644
index 0000000000..f66fb02587
--- /dev/null
+++ b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-el/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Description for the button to accept the search suggestion and continue editing the search. -->
+ <string name="mozac_browser_awesomebar_edit_suggestion">Αποδοχή και επεξεργασία πρότασης</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-en-rCA/strings.xml b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-en-rCA/strings.xml
new file mode 100644
index 0000000000..a5fd6b47e3
--- /dev/null
+++ b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-en-rCA/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Description for the button to accept the search suggestion and continue editing the search. -->
+ <string name="mozac_browser_awesomebar_edit_suggestion">Accept and edit suggestion</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-en-rGB/strings.xml b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-en-rGB/strings.xml
new file mode 100644
index 0000000000..a5fd6b47e3
--- /dev/null
+++ b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-en-rGB/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Description for the button to accept the search suggestion and continue editing the search. -->
+ <string name="mozac_browser_awesomebar_edit_suggestion">Accept and edit suggestion</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-eo/strings.xml b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-eo/strings.xml
new file mode 100644
index 0000000000..79f9e026ed
--- /dev/null
+++ b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-eo/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Description for the button to accept the search suggestion and continue editing the search. -->
+ <string name="mozac_browser_awesomebar_edit_suggestion">Akcepti kaj modifi sugeston</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-es-rAR/strings.xml b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-es-rAR/strings.xml
new file mode 100644
index 0000000000..76061a6811
--- /dev/null
+++ b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-es-rAR/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Description for the button to accept the search suggestion and continue editing the search. -->
+ <string name="mozac_browser_awesomebar_edit_suggestion">Aceptar y editar sugerencia</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-es-rCL/strings.xml b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-es-rCL/strings.xml
new file mode 100644
index 0000000000..76061a6811
--- /dev/null
+++ b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-es-rCL/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Description for the button to accept the search suggestion and continue editing the search. -->
+ <string name="mozac_browser_awesomebar_edit_suggestion">Aceptar y editar sugerencia</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-es-rES/strings.xml b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-es-rES/strings.xml
new file mode 100644
index 0000000000..76061a6811
--- /dev/null
+++ b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-es-rES/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Description for the button to accept the search suggestion and continue editing the search. -->
+ <string name="mozac_browser_awesomebar_edit_suggestion">Aceptar y editar sugerencia</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-es-rMX/strings.xml b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-es-rMX/strings.xml
new file mode 100644
index 0000000000..76061a6811
--- /dev/null
+++ b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-es-rMX/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Description for the button to accept the search suggestion and continue editing the search. -->
+ <string name="mozac_browser_awesomebar_edit_suggestion">Aceptar y editar sugerencia</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-es/strings.xml b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-es/strings.xml
new file mode 100644
index 0000000000..76061a6811
--- /dev/null
+++ b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-es/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Description for the button to accept the search suggestion and continue editing the search. -->
+ <string name="mozac_browser_awesomebar_edit_suggestion">Aceptar y editar sugerencia</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-et/strings.xml b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-et/strings.xml
new file mode 100644
index 0000000000..30d1bc57c6
--- /dev/null
+++ b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-et/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Description for the button to accept the search suggestion and continue editing the search. -->
+ <string name="mozac_browser_awesomebar_edit_suggestion">Nõustu ja muuda soovitust</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-eu/strings.xml b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-eu/strings.xml
new file mode 100644
index 0000000000..c2d90b206e
--- /dev/null
+++ b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-eu/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Description for the button to accept the search suggestion and continue editing the search. -->
+ <string name="mozac_browser_awesomebar_edit_suggestion">Onartu eta editatu iradokizuna</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-fa/strings.xml b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-fa/strings.xml
new file mode 100644
index 0000000000..51d494d857
--- /dev/null
+++ b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-fa/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Description for the button to accept the search suggestion and continue editing the search. -->
+ <string name="mozac_browser_awesomebar_edit_suggestion">پذیرش و ویرایش پیشنهاد</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-fi/strings.xml b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-fi/strings.xml
new file mode 100644
index 0000000000..26c1bf745d
--- /dev/null
+++ b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-fi/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Description for the button to accept the search suggestion and continue editing the search. -->
+ <string name="mozac_browser_awesomebar_edit_suggestion">Hyväksy ehdotus ja muokkaa sitä</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-fr/strings.xml b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-fr/strings.xml
new file mode 100644
index 0000000000..4854ede352
--- /dev/null
+++ b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-fr/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Description for the button to accept the search suggestion and continue editing the search. -->
+ <string name="mozac_browser_awesomebar_edit_suggestion">Accepter et modifier la suggestion</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-fur/strings.xml b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-fur/strings.xml
new file mode 100644
index 0000000000..3fce06ba6c
--- /dev/null
+++ b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-fur/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Description for the button to accept the search suggestion and continue editing the search. -->
+ <string name="mozac_browser_awesomebar_edit_suggestion">Acete e modifiche sugjeriment</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-fy-rNL/strings.xml b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-fy-rNL/strings.xml
new file mode 100644
index 0000000000..e3be14f405
--- /dev/null
+++ b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-fy-rNL/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Description for the button to accept the search suggestion and continue editing the search. -->
+ <string name="mozac_browser_awesomebar_edit_suggestion">Suggestje akseptearje en bewurkje</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-gd/strings.xml b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-gd/strings.xml
new file mode 100644
index 0000000000..48b3251c4b
--- /dev/null
+++ b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-gd/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Description for the button to accept the search suggestion and continue editing the search. -->
+ <string name="mozac_browser_awesomebar_edit_suggestion">Gabh ris is deasaich am moladh</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-gl/strings.xml b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-gl/strings.xml
new file mode 100644
index 0000000000..cc1aafdc78
--- /dev/null
+++ b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-gl/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Description for the button to accept the search suggestion and continue editing the search. -->
+ <string name="mozac_browser_awesomebar_edit_suggestion">Aceptar e editar a suxestión</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-gn/strings.xml b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-gn/strings.xml
new file mode 100644
index 0000000000..041524a8c8
--- /dev/null
+++ b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-gn/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Description for the button to accept the search suggestion and continue editing the search. -->
+ <string name="mozac_browser_awesomebar_edit_suggestion">Emoneĩ ha embosako’i ñe’ẽporã</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-hi-rIN/strings.xml b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-hi-rIN/strings.xml
new file mode 100644
index 0000000000..4bcd2e4b94
--- /dev/null
+++ b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-hi-rIN/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Description for the button to accept the search suggestion and continue editing the search. -->
+ <string name="mozac_browser_awesomebar_edit_suggestion">सुझाव को स्वीकारें और संपादित करें</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-hr/strings.xml b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-hr/strings.xml
new file mode 100644
index 0000000000..12124a89c9
--- /dev/null
+++ b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-hr/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Description for the button to accept the search suggestion and continue editing the search. -->
+ <string name="mozac_browser_awesomebar_edit_suggestion">Prihvati i uredi prijedlog</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-hsb/strings.xml b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-hsb/strings.xml
new file mode 100644
index 0000000000..e83f6c018c
--- /dev/null
+++ b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-hsb/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Description for the button to accept the search suggestion and continue editing the search. -->
+ <string name="mozac_browser_awesomebar_edit_suggestion">Namjet přiwzać a wobdźěłać</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-hu/strings.xml b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-hu/strings.xml
new file mode 100644
index 0000000000..bc890be834
--- /dev/null
+++ b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-hu/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Description for the button to accept the search suggestion and continue editing the search. -->
+ <string name="mozac_browser_awesomebar_edit_suggestion">Elfogadás és a javaslat szerkesztése</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-hy-rAM/strings.xml b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-hy-rAM/strings.xml
new file mode 100644
index 0000000000..5283d8d707
--- /dev/null
+++ b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-hy-rAM/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Description for the button to accept the search suggestion and continue editing the search. -->
+ <string name="mozac_browser_awesomebar_edit_suggestion">Ընդունել և խմբագրել առաջարկությունը</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-ia/strings.xml b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-ia/strings.xml
new file mode 100644
index 0000000000..5631621fdc
--- /dev/null
+++ b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-ia/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Description for the button to accept the search suggestion and continue editing the search. -->
+ <string name="mozac_browser_awesomebar_edit_suggestion">Acceptar e rediger suggestion</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-in/strings.xml b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-in/strings.xml
new file mode 100644
index 0000000000..54967054e7
--- /dev/null
+++ b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-in/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Description for the button to accept the search suggestion and continue editing the search. -->
+ <string name="mozac_browser_awesomebar_edit_suggestion">Terima dan ubah saran</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-is/strings.xml b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-is/strings.xml
new file mode 100644
index 0000000000..10c6b79c14
--- /dev/null
+++ b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-is/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Description for the button to accept the search suggestion and continue editing the search. -->
+ <string name="mozac_browser_awesomebar_edit_suggestion">Samþykkja og breyta tillögu</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-it/strings.xml b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-it/strings.xml
new file mode 100644
index 0000000000..c6812c4865
--- /dev/null
+++ b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-it/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Description for the button to accept the search suggestion and continue editing the search. -->
+ <string name="mozac_browser_awesomebar_edit_suggestion">Accetta e modifica suggerimento</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-iw/strings.xml b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-iw/strings.xml
new file mode 100644
index 0000000000..d595def498
--- /dev/null
+++ b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-iw/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Description for the button to accept the search suggestion and continue editing the search. -->
+ <string name="mozac_browser_awesomebar_edit_suggestion">לקבל ולערוך את ההצעה</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-ja/strings.xml b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-ja/strings.xml
new file mode 100644
index 0000000000..ea9a12d306
--- /dev/null
+++ b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-ja/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Description for the button to accept the search suggestion and continue editing the search. -->
+ <string name="mozac_browser_awesomebar_edit_suggestion">提案を受け入れて編集</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-ka/strings.xml b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-ka/strings.xml
new file mode 100644
index 0000000000..1a1664e0a0
--- /dev/null
+++ b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-ka/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Description for the button to accept the search suggestion and continue editing the search. -->
+ <string name="mozac_browser_awesomebar_edit_suggestion">მიღება და შემოთავაზების ჩასწორება</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-kaa/strings.xml b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-kaa/strings.xml
new file mode 100644
index 0000000000..450efcd9a1
--- /dev/null
+++ b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-kaa/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Description for the button to accept the search suggestion and continue editing the search. -->
+ <string name="mozac_browser_awesomebar_edit_suggestion">Usınıslardı qabıllaw hám ózgertiw</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-kab/strings.xml b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-kab/strings.xml
new file mode 100644
index 0000000000..3117f7591b
--- /dev/null
+++ b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-kab/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Description for the button to accept the search suggestion and continue editing the search. -->
+ <string name="mozac_browser_awesomebar_edit_suggestion">Qbel syen ẓreg asumer</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-kk/strings.xml b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-kk/strings.xml
new file mode 100644
index 0000000000..83d4d9261a
--- /dev/null
+++ b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-kk/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Description for the button to accept the search suggestion and continue editing the search. -->
+ <string name="mozac_browser_awesomebar_edit_suggestion">Ұсынысты қабылдау және түзету</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-kmr/strings.xml b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-kmr/strings.xml
new file mode 100644
index 0000000000..d7dc068c21
--- /dev/null
+++ b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-kmr/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Description for the button to accept the search suggestion and continue editing the search. -->
+ <string name="mozac_browser_awesomebar_edit_suggestion">Pêşniyarê bipejirîne û sererast bike</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-ko/strings.xml b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-ko/strings.xml
new file mode 100644
index 0000000000..308e45797f
--- /dev/null
+++ b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-ko/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Description for the button to accept the search suggestion and continue editing the search. -->
+ <string name="mozac_browser_awesomebar_edit_suggestion">제안 수락 및 편집</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-lo/strings.xml b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-lo/strings.xml
new file mode 100644
index 0000000000..eed7f6e8c0
--- /dev/null
+++ b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-lo/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Description for the button to accept the search suggestion and continue editing the search. -->
+ <string name="mozac_browser_awesomebar_edit_suggestion">ຍອມຮັບ ແລະ ແກ້ໄຂຄຳແນະນຳ</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-lt/strings.xml b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-lt/strings.xml
new file mode 100644
index 0000000000..2b5c72b442
--- /dev/null
+++ b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-lt/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Description for the button to accept the search suggestion and continue editing the search. -->
+ <string name="mozac_browser_awesomebar_edit_suggestion">Priimti ir redaguoti pasiūlymą</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-mr/strings.xml b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-mr/strings.xml
new file mode 100644
index 0000000000..42c0a8df5b
--- /dev/null
+++ b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-mr/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Description for the button to accept the search suggestion and continue editing the search. -->
+ <string name="mozac_browser_awesomebar_edit_suggestion">सूचना स्वीकारा व संपादित करा</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-my/strings.xml b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-my/strings.xml
new file mode 100644
index 0000000000..63b5bee53a
--- /dev/null
+++ b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-my/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Description for the button to accept the search suggestion and continue editing the search. -->
+ <string name="mozac_browser_awesomebar_edit_suggestion">အကြံပြုချက်အားလက်ခံ၍တည်းဖြတ်မည်</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-nb-rNO/strings.xml b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-nb-rNO/strings.xml
new file mode 100644
index 0000000000..f141385354
--- /dev/null
+++ b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-nb-rNO/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Description for the button to accept the search suggestion and continue editing the search. -->
+ <string name="mozac_browser_awesomebar_edit_suggestion">Godta og rediger forslag</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-ne-rNP/strings.xml b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-ne-rNP/strings.xml
new file mode 100644
index 0000000000..905e09f84b
--- /dev/null
+++ b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-ne-rNP/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Description for the button to accept the search suggestion and continue editing the search. -->
+ <string name="mozac_browser_awesomebar_edit_suggestion">सुझाव स्वीकार्नुहोस् र सम्पादन गर्नुहोस्</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-nl/strings.xml b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-nl/strings.xml
new file mode 100644
index 0000000000..f2379344d1
--- /dev/null
+++ b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-nl/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Description for the button to accept the search suggestion and continue editing the search. -->
+ <string name="mozac_browser_awesomebar_edit_suggestion">Suggestie accepteren en bewerken</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-nn-rNO/strings.xml b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-nn-rNO/strings.xml
new file mode 100644
index 0000000000..f141385354
--- /dev/null
+++ b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-nn-rNO/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Description for the button to accept the search suggestion and continue editing the search. -->
+ <string name="mozac_browser_awesomebar_edit_suggestion">Godta og rediger forslag</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-oc/strings.xml b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-oc/strings.xml
new file mode 100644
index 0000000000..fce8718fd2
--- /dev/null
+++ b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-oc/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Description for the button to accept the search suggestion and continue editing the search. -->
+ <string name="mozac_browser_awesomebar_edit_suggestion">Acceptar e modificar la suggestion</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-or/strings.xml b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-or/strings.xml
new file mode 100644
index 0000000000..2e861cce89
--- /dev/null
+++ b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-or/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Description for the button to accept the search suggestion and continue editing the search. -->
+ <string name="mozac_browser_awesomebar_edit_suggestion">ସ୍ୱୀକାର କରି ପରାମର୍ଶଟିକୁ ସମ୍ପାଦନ କରନ୍ତୁ</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-pa-rIN/strings.xml b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-pa-rIN/strings.xml
new file mode 100644
index 0000000000..ba64f33a8a
--- /dev/null
+++ b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-pa-rIN/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Description for the button to accept the search suggestion and continue editing the search. -->
+ <string name="mozac_browser_awesomebar_edit_suggestion">ਸੁਝਾਅ ਮੰਨੋ ਤੇ ਸੋਧੋ</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-pa-rPK/strings.xml b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-pa-rPK/strings.xml
new file mode 100644
index 0000000000..1ea85cff8d
--- /dev/null
+++ b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-pa-rPK/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Description for the button to accept the search suggestion and continue editing the search. -->
+ <string name="mozac_browser_awesomebar_edit_suggestion">تجویز منو تے سودھو</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-pl/strings.xml b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-pl/strings.xml
new file mode 100644
index 0000000000..7de1109e3d
--- /dev/null
+++ b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-pl/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Description for the button to accept the search suggestion and continue editing the search. -->
+ <string name="mozac_browser_awesomebar_edit_suggestion">Przyjmij i modyfikuj podpowiedź</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-pt-rBR/strings.xml b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-pt-rBR/strings.xml
new file mode 100644
index 0000000000..478fab2ca3
--- /dev/null
+++ b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-pt-rBR/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Description for the button to accept the search suggestion and continue editing the search. -->
+ <string name="mozac_browser_awesomebar_edit_suggestion">Aceitar e editar sugestão</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-pt-rPT/strings.xml b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-pt-rPT/strings.xml
new file mode 100644
index 0000000000..478fab2ca3
--- /dev/null
+++ b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-pt-rPT/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Description for the button to accept the search suggestion and continue editing the search. -->
+ <string name="mozac_browser_awesomebar_edit_suggestion">Aceitar e editar sugestão</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-rm/strings.xml b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-rm/strings.xml
new file mode 100644
index 0000000000..693ab380d5
--- /dev/null
+++ b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-rm/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Description for the button to accept the search suggestion and continue editing the search. -->
+ <string name="mozac_browser_awesomebar_edit_suggestion">Acceptar la proposta e modifitgar</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-ru/strings.xml b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-ru/strings.xml
new file mode 100644
index 0000000000..c690872c02
--- /dev/null
+++ b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-ru/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Description for the button to accept the search suggestion and continue editing the search. -->
+ <string name="mozac_browser_awesomebar_edit_suggestion">Выбрать и изменить подсказку</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-sat/strings.xml b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-sat/strings.xml
new file mode 100644
index 0000000000..a57202cf0c
--- /dev/null
+++ b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-sat/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Description for the button to accept the search suggestion and continue editing the search. -->
+ <string name="mozac_browser_awesomebar_edit_suggestion">ᱵᱟᱛᱟᱣᱢᱮ ᱟᱨ ᱥᱩᱡᱷᱟᱹᱣ ᱥᱟᱯᱲᱟᱣ ᱢᱮ</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-sc/strings.xml b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-sc/strings.xml
new file mode 100644
index 0000000000..ea90dc6e82
--- /dev/null
+++ b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-sc/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Description for the button to accept the search suggestion and continue editing the search. -->
+ <string name="mozac_browser_awesomebar_edit_suggestion">Atzeta e modìfica su cussìgiu</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-si/strings.xml b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-si/strings.xml
new file mode 100644
index 0000000000..2ebd54bc30
--- /dev/null
+++ b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-si/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Description for the button to accept the search suggestion and continue editing the search. -->
+ <string name="mozac_browser_awesomebar_edit_suggestion">යෝජනාව පිළිගෙන සංස්කරණය</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-sk/strings.xml b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-sk/strings.xml
new file mode 100644
index 0000000000..e9b00f0de7
--- /dev/null
+++ b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-sk/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Description for the button to accept the search suggestion and continue editing the search. -->
+ <string name="mozac_browser_awesomebar_edit_suggestion">Akceptovať návrh a pokračovať v úprave</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-skr/strings.xml b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-skr/strings.xml
new file mode 100644
index 0000000000..10bff0878f
--- /dev/null
+++ b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-skr/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Description for the button to accept the search suggestion and continue editing the search. -->
+ <string name="mozac_browser_awesomebar_edit_suggestion">تجویز کوں قبول کرو تے تبدیلی کرو</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-sl/strings.xml b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-sl/strings.xml
new file mode 100644
index 0000000000..7fe0c78a16
--- /dev/null
+++ b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-sl/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Description for the button to accept the search suggestion and continue editing the search. -->
+ <string name="mozac_browser_awesomebar_edit_suggestion">Sprejmi in uredi predlog</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-sq/strings.xml b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-sq/strings.xml
new file mode 100644
index 0000000000..d4a0920d65
--- /dev/null
+++ b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-sq/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Description for the button to accept the search suggestion and continue editing the search. -->
+ <string name="mozac_browser_awesomebar_edit_suggestion">Pranoni dhe përpunoni sugjerimin</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-sr/strings.xml b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-sr/strings.xml
new file mode 100644
index 0000000000..f361a3045d
--- /dev/null
+++ b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-sr/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Description for the button to accept the search suggestion and continue editing the search. -->
+ <string name="mozac_browser_awesomebar_edit_suggestion">Прихвати и уреди предлог</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-su/strings.xml b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-su/strings.xml
new file mode 100644
index 0000000000..4b049e8e1f
--- /dev/null
+++ b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-su/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Description for the button to accept the search suggestion and continue editing the search. -->
+ <string name="mozac_browser_awesomebar_edit_suggestion">Tampa jeung édit saran</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-sv-rSE/strings.xml b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-sv-rSE/strings.xml
new file mode 100644
index 0000000000..e9e8f2d57e
--- /dev/null
+++ b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-sv-rSE/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Description for the button to accept the search suggestion and continue editing the search. -->
+ <string name="mozac_browser_awesomebar_edit_suggestion">Acceptera och redigera förslag</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-szl/strings.xml b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-szl/strings.xml
new file mode 100644
index 0000000000..01a3221de9
--- /dev/null
+++ b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-szl/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Description for the button to accept the search suggestion and continue editing the search. -->
+ <string name="mozac_browser_awesomebar_edit_suggestion">Akceptuj i edytuj dorada</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-ta/strings.xml b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-ta/strings.xml
new file mode 100644
index 0000000000..822e2ca5da
--- /dev/null
+++ b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-ta/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Description for the button to accept the search suggestion and continue editing the search. -->
+ <string name="mozac_browser_awesomebar_edit_suggestion">பரிந்துரையை ஏற்று திருத்து</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-tg/strings.xml b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-tg/strings.xml
new file mode 100644
index 0000000000..d7716c120b
--- /dev/null
+++ b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-tg/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Description for the button to accept the search suggestion and continue editing the search. -->
+ <string name="mozac_browser_awesomebar_edit_suggestion">Пешниҳодро қабул ва таҳрир намоед</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-th/strings.xml b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-th/strings.xml
new file mode 100644
index 0000000000..4f22694ca9
--- /dev/null
+++ b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-th/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Description for the button to accept the search suggestion and continue editing the search. -->
+ <string name="mozac_browser_awesomebar_edit_suggestion">ยอมรับและแก้ไขข้อเสนอแนะ</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-tl/strings.xml b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-tl/strings.xml
new file mode 100644
index 0000000000..5df1097dc7
--- /dev/null
+++ b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-tl/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Description for the button to accept the search suggestion and continue editing the search. -->
+ <string name="mozac_browser_awesomebar_edit_suggestion">Tanggapin at i-edit ang mungkahi</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-tok/strings.xml b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-tok/strings.xml
new file mode 100644
index 0000000000..1cdbb57528
--- /dev/null
+++ b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-tok/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Description for the button to accept the search suggestion and continue editing the search. -->
+ <string name="mozac_browser_awesomebar_edit_suggestion">o kama jo, o ante</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-tr/strings.xml b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-tr/strings.xml
new file mode 100644
index 0000000000..a50a78776c
--- /dev/null
+++ b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-tr/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Description for the button to accept the search suggestion and continue editing the search. -->
+ <string name="mozac_browser_awesomebar_edit_suggestion">Öneriyi kabul et ve düzenle</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-trs/strings.xml b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-trs/strings.xml
new file mode 100644
index 0000000000..087edecc87
--- /dev/null
+++ b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-trs/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Description for the button to accept the search suggestion and continue editing the search. -->
+ <string name="mozac_browser_awesomebar_edit_suggestion">Gārāyina nī nādūnāt nuguan\’ narikij</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-tt/strings.xml b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-tt/strings.xml
new file mode 100644
index 0000000000..c15a889dbb
--- /dev/null
+++ b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-tt/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Description for the button to accept the search suggestion and continue editing the search. -->
+ <string name="mozac_browser_awesomebar_edit_suggestion">Тәкъдимне кабул итү һәм үзгәртү</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-ug/strings.xml b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-ug/strings.xml
new file mode 100644
index 0000000000..476b29d8a2
--- /dev/null
+++ b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-ug/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Description for the button to accept the search suggestion and continue editing the search. -->
+ <string name="mozac_browser_awesomebar_edit_suggestion">تەكلىپنى قوبۇل قىلىپ تەھرىرلەيدۇ</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-uk/strings.xml b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-uk/strings.xml
new file mode 100644
index 0000000000..0ae5b6ef4f
--- /dev/null
+++ b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-uk/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Description for the button to accept the search suggestion and continue editing the search. -->
+ <string name="mozac_browser_awesomebar_edit_suggestion">Прийняти та змінити пропозицію</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-ur/strings.xml b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-ur/strings.xml
new file mode 100644
index 0000000000..defe8f4812
--- /dev/null
+++ b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-ur/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Description for the button to accept the search suggestion and continue editing the search. -->
+ <string name="mozac_browser_awesomebar_edit_suggestion">تجویز کو قبول کریں اور ترمیم کریں</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-uz/strings.xml b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-uz/strings.xml
new file mode 100644
index 0000000000..4dcf317d8c
--- /dev/null
+++ b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-uz/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Description for the button to accept the search suggestion and continue editing the search. -->
+ <string name="mozac_browser_awesomebar_edit_suggestion">Tavsiyani qabul qilish va tahrir qilish</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-vi/strings.xml b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-vi/strings.xml
new file mode 100644
index 0000000000..292a5cd7fb
--- /dev/null
+++ b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-vi/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Description for the button to accept the search suggestion and continue editing the search. -->
+ <string name="mozac_browser_awesomebar_edit_suggestion">Chấp nhận và chỉnh sửa đề xuất</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-yo/strings.xml b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-yo/strings.xml
new file mode 100644
index 0000000000..9112ee0856
--- /dev/null
+++ b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-yo/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Description for the button to accept the search suggestion and continue editing the search. -->
+ <string name="mozac_browser_awesomebar_edit_suggestion">Gbà á, kí o sì ṣe àtuṣe àbá</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-zh-rCN/strings.xml b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-zh-rCN/strings.xml
new file mode 100644
index 0000000000..b21cab3d6c
--- /dev/null
+++ b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-zh-rCN/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Description for the button to accept the search suggestion and continue editing the search. -->
+ <string name="mozac_browser_awesomebar_edit_suggestion">接受并编辑建议</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-zh-rTW/strings.xml b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-zh-rTW/strings.xml
new file mode 100644
index 0000000000..87481af094
--- /dev/null
+++ b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-zh-rTW/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Description for the button to accept the search suggestion and continue editing the search. -->
+ <string name="mozac_browser_awesomebar_edit_suggestion">接受並編輯建議</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/awesomebar/src/main/res/values/strings.xml b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values/strings.xml
new file mode 100644
index 0000000000..467a778b07
--- /dev/null
+++ b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values/strings.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- This Source Code Form is subject to the terms of the Mozilla Public
+ - License, v. 2.0. If a copy of the MPL was not distributed with this
+ - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
+<resources>
+ <!-- Description for the button to accept the search suggestion and continue editing the search. -->
+ <string name="mozac_browser_awesomebar_edit_suggestion">Accept and edit suggestion</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/awesomebar/src/test/java/mozilla/components/compose/browser/awesomebar/internal/SuggestionFetcherTest.kt b/mobile/android/android-components/components/compose/awesomebar/src/test/java/mozilla/components/compose/browser/awesomebar/internal/SuggestionFetcherTest.kt
new file mode 100644
index 0000000000..489b13c834
--- /dev/null
+++ b/mobile/android/android-components/components/compose/awesomebar/src/test/java/mozilla/components/compose/browser/awesomebar/internal/SuggestionFetcherTest.kt
@@ -0,0 +1,69 @@
+/* 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 mozilla.components.compose.browser.awesomebar.internal
+
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.Job
+import mozilla.components.concept.awesomebar.AwesomeBar
+import mozilla.components.concept.awesomebar.AwesomeBar.SuggestionProvider
+import mozilla.components.concept.awesomebar.AwesomeBar.SuggestionProviderGroup
+import mozilla.components.support.test.any
+import mozilla.components.support.test.mock
+import mozilla.components.support.test.rule.MainCoroutineRule
+import mozilla.components.support.test.rule.runTestOnMain
+import org.junit.Assert.assertEquals
+import org.junit.Rule
+import org.junit.Test
+import org.mockito.Mockito.doAnswer
+import org.mockito.Mockito.inOrder
+import org.mockito.Mockito.spy
+
+@ExperimentalCoroutinesApi // for runTestOnMain
+class SuggestionFetcherTest {
+ @get:Rule
+ val coroutinesTestRule = MainCoroutineRule()
+
+ @Test
+ fun `GIVEN a new fetch request THEN all previous queries are cancelled`() = runTestOnMain {
+ val provider: SuggestionProvider = mock()
+ val providerGroup = SuggestionProviderGroup(listOf(provider))
+ val fetcher = spy(SuggestionFetcher(listOf(providerGroup), null))
+ val previousFetchJob: Job = mock()
+ fetcher.fetchJob = previousFetchJob
+ doAnswer {}.`when`(fetcher).fetchFrom(any(), any(), any(), any())
+ val orderVerifier = inOrder(previousFetchJob, fetcher)
+
+ fetcher.fetch("test")
+
+ orderVerifier.verify(previousFetchJob)!!.cancel()
+ orderVerifier.verify(fetcher).fetchFrom(providerGroup, provider, "test", null)
+ }
+
+ @Test
+ fun `GIVEN a suggestion group THEN the group's priority becomes highest suggestions' score within the group`() = runTestOnMain {
+ val provider: SuggestionProvider = mock()
+ val providerGroup = SuggestionProviderGroup(listOf(provider))
+ val suggestions = listOf(
+ AwesomeBar.Suggestion(
+ provider = provider,
+ score = Int.MAX_VALUE,
+ ),
+ AwesomeBar.Suggestion(
+ provider = provider,
+ score = Int.MIN_VALUE,
+ ),
+ )
+ val fetcher = spy(SuggestionFetcher(listOf(providerGroup), null))
+
+ fetcher.processResultFrom(
+ group = providerGroup,
+ provider = provider,
+ suggestions = suggestions,
+ profilerStartTime = null,
+ )
+
+ assertEquals(providerGroup.priority, Int.MAX_VALUE)
+ }
+}
diff --git a/mobile/android/android-components/components/compose/awesomebar/src/test/java/mozilla/components/compose/browser/awesomebar/internal/SuggestionsTest.kt b/mobile/android/android-components/components/compose/awesomebar/src/test/java/mozilla/components/compose/browser/awesomebar/internal/SuggestionsTest.kt
new file mode 100644
index 0000000000..488103f99a
--- /dev/null
+++ b/mobile/android/android-components/components/compose/awesomebar/src/test/java/mozilla/components/compose/browser/awesomebar/internal/SuggestionsTest.kt
@@ -0,0 +1,173 @@
+/* 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 mozilla.components.compose.browser.awesomebar.internal
+
+import mozilla.components.concept.awesomebar.AwesomeBar.Suggestion
+import mozilla.components.concept.awesomebar.AwesomeBar.SuggestionProvider
+import mozilla.components.concept.awesomebar.AwesomeBar.SuggestionProviderGroup
+import mozilla.components.support.test.mock
+import mozilla.components.support.test.whenever
+import org.junit.Assert.assertEquals
+import org.junit.Assert.assertTrue
+import org.junit.Test
+
+class SuggestionsTest {
+ @Test
+ fun `GIVEN 1 suggestion in 1 group WHEN neither are visible THEN return an empty visibility state`() {
+ val provider: SuggestionProvider = mock()
+
+ val visibleItems = VisibleItems(
+ suggestions = mapOf(SuggestionProviderGroup(listOf(provider)) to listOf(Suggestion(provider))),
+ visibleItemKeys = emptyList(),
+ )
+
+ val visibilityState = visibleItems.toVisibilityState()
+ assertTrue(visibilityState.visibleProviderGroups.isEmpty())
+ }
+
+ @Test
+ fun `GIVEN 1 suggestion in 1 group WHEN both are visible THEN return a visibility state containing the suggestion`() {
+ val provider: SuggestionProvider = mock()
+ whenever(provider.id).thenReturn("provider")
+ val providerGroup = SuggestionProviderGroup(listOf(provider))
+ val providerGroupSuggestions = listOf(Suggestion(provider))
+
+ val visibleItems = VisibleItems(
+ suggestions = mapOf(providerGroup to providerGroupSuggestions),
+ visibleItemKeys = listOf(
+ ItemKey.SuggestionGroup(providerGroup.id),
+ ItemKey.Suggestion(providerGroup.id, provider.id, providerGroupSuggestions[0].id),
+ ),
+ )
+
+ val visibilityState = visibleItems.toVisibilityState()
+ assertEquals(
+ visibilityState.visibleProviderGroups,
+ mapOf(
+ providerGroup to providerGroupSuggestions,
+ ),
+ )
+ }
+
+ @Test
+ fun `GIVEN 1 suggestion in 1 group WHEN only the suggestion is visible THEN return a visibility state containing the suggestion`() {
+ val provider: SuggestionProvider = mock()
+ whenever(provider.id).thenReturn("provider")
+ val providerGroup = SuggestionProviderGroup(listOf(provider))
+ val providerGroupSuggestions = listOf(Suggestion(provider))
+
+ val visibleItems = VisibleItems(
+ suggestions = mapOf(providerGroup to providerGroupSuggestions),
+ visibleItemKeys = listOf(
+ ItemKey.Suggestion(providerGroup.id, provider.id, providerGroupSuggestions[0].id),
+ ),
+ )
+
+ val visibilityState = visibleItems.toVisibilityState()
+ assertEquals(
+ visibilityState.visibleProviderGroups,
+ mapOf(
+ providerGroup to providerGroupSuggestions,
+ ),
+ )
+ }
+
+ @Test
+ fun `GIVEN 2 suggestions in 1 group WHEN all are visible THEN return a visibility state containing the suggestions`() {
+ val provider: SuggestionProvider = mock()
+ whenever(provider.id).thenReturn("provider")
+ val providerGroup = SuggestionProviderGroup(listOf(provider))
+ val providerGroupSuggestions = listOf(Suggestion(provider), Suggestion(provider))
+
+ val visibleItems = VisibleItems(
+ suggestions = mapOf(providerGroup to providerGroupSuggestions),
+ visibleItemKeys = listOf(
+ ItemKey.SuggestionGroup(providerGroup.id),
+ ItemKey.Suggestion(providerGroup.id, provider.id, providerGroupSuggestions[0].id),
+ ItemKey.Suggestion(providerGroup.id, provider.id, providerGroupSuggestions[1].id),
+ ),
+ )
+
+ val visibilityState = visibleItems.toVisibilityState()
+ assertEquals(
+ visibilityState.visibleProviderGroups,
+ mapOf(
+ providerGroup to providerGroupSuggestions,
+ ),
+ )
+ }
+
+ @Test
+ fun `GIVEN 2 suggestions in 2 groups WHEN 1 suggestion is visible in 1 group THEN return a visibility state containing the suggestion`() {
+ val firstProvider: SuggestionProvider = mock()
+ whenever(firstProvider.id).thenReturn("firstProvider")
+ val secondProvider: SuggestionProvider = mock()
+ whenever(secondProvider.id).thenReturn("secondProvider")
+ val thirdProvider: SuggestionProvider = mock()
+ whenever(thirdProvider.id).thenReturn("thirdProvider")
+ val firstProviderGroup = SuggestionProviderGroup(listOf(firstProvider, secondProvider))
+ val firstProviderGroupSuggestions = listOf(Suggestion(firstProvider), Suggestion(secondProvider))
+ val secondProviderGroup = SuggestionProviderGroup(listOf(secondProvider, thirdProvider))
+ val secondProviderGroupSuggestions = listOf(Suggestion(secondProvider), Suggestion(thirdProvider))
+
+ val visibleItems = VisibleItems(
+ suggestions = mapOf(
+ firstProviderGroup to firstProviderGroupSuggestions,
+ secondProviderGroup to secondProviderGroupSuggestions,
+ ),
+ visibleItemKeys = listOf(
+ ItemKey.SuggestionGroup(firstProviderGroup.id),
+ ItemKey.Suggestion(firstProviderGroup.id, secondProvider.id, firstProviderGroupSuggestions[1].id),
+ ),
+ )
+
+ val visibilityState = visibleItems.toVisibilityState()
+ assertEquals(
+ visibilityState.visibleProviderGroups,
+ mapOf(
+ firstProviderGroup to listOf(firstProviderGroupSuggestions[1]),
+ ),
+ )
+ }
+
+ @Test
+ fun `GIVEN 2 suggestions in 2 groups WHEN 1 suggestion is visible in each group THEN return a visibility state containing the suggestions`() {
+ val firstProvider: SuggestionProvider = mock()
+ whenever(firstProvider.id).thenReturn("firstProvider")
+
+ val secondProvider: SuggestionProvider = mock()
+ whenever(secondProvider.id).thenReturn("secondProvider")
+
+ val thirdProvider: SuggestionProvider = mock()
+ whenever(thirdProvider.id).thenReturn("thirdProvider")
+
+ val firstProviderGroup = SuggestionProviderGroup(listOf(firstProvider, secondProvider))
+ val firstProviderGroupSuggestions = listOf(Suggestion(firstProvider), Suggestion(secondProvider))
+
+ val secondProviderGroup = SuggestionProviderGroup(listOf(secondProvider, thirdProvider))
+ val secondProviderGroupSuggestions = listOf(Suggestion(secondProvider), Suggestion(thirdProvider))
+
+ val visibleItems = VisibleItems(
+ suggestions = mapOf(
+ firstProviderGroup to firstProviderGroupSuggestions,
+ secondProviderGroup to secondProviderGroupSuggestions,
+ ),
+ visibleItemKeys = listOf(
+ ItemKey.SuggestionGroup(firstProviderGroup.id),
+ ItemKey.Suggestion(firstProviderGroup.id, firstProvider.id, firstProviderGroupSuggestions[0].id),
+ ItemKey.SuggestionGroup(secondProviderGroup.id),
+ ItemKey.Suggestion(secondProviderGroup.id, thirdProvider.id, secondProviderGroupSuggestions[1].id),
+ ),
+ )
+ val visibilityState = visibleItems.toVisibilityState()
+ assertEquals(
+ visibilityState.visibleProviderGroups,
+ mapOf(
+ firstProviderGroup to listOf(firstProviderGroupSuggestions[0]),
+ secondProviderGroup to listOf(secondProviderGroupSuggestions[1]),
+ ),
+ )
+ }
+}
diff --git a/mobile/android/android-components/components/compose/awesomebar/src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker b/mobile/android/android-components/components/compose/awesomebar/src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker
new file mode 100644
index 0000000000..cf1c399ea8
--- /dev/null
+++ b/mobile/android/android-components/components/compose/awesomebar/src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker
@@ -0,0 +1,2 @@
+mock-maker-inline
+// This allows mocking final classes (classes are final by default in Kotlin)
diff --git a/mobile/android/android-components/components/compose/browser-toolbar/README.md b/mobile/android/android-components/components/compose/browser-toolbar/README.md
new file mode 100644
index 0000000000..1f6bdde813
--- /dev/null
+++ b/mobile/android/android-components/components/compose/browser-toolbar/README.md
@@ -0,0 +1,19 @@
+# [Android Components](../../../README.md) > Compose > Browser Toolbar
+
+A customizable toolbar for browsers using Jetpack Compose.
+
+## Usage
+
+### Setting up the dependency
+
+Use Gradle to download the library from [maven.mozilla.org](https://maven.mozilla.org/) ([Setup repository](../../../README.md#maven-repository)):
+
+```Groovy
+implementation "org.mozilla.components:compose-browser-toolbar:{latest-version}"
+```
+
+## License
+
+ 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/
diff --git a/mobile/android/android-components/components/compose/browser-toolbar/build.gradle b/mobile/android/android-components/components/compose/browser-toolbar/build.gradle
new file mode 100644
index 0000000000..cf81cb173f
--- /dev/null
+++ b/mobile/android/android-components/components/compose/browser-toolbar/build.gradle
@@ -0,0 +1,54 @@
+/* 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/. */
+
+apply plugin: 'com.android.library'
+apply plugin: 'kotlin-android'
+
+android {
+ defaultConfig {
+ minSdkVersion config.minSdkVersion
+ compileSdk config.compileSdkVersion
+ targetSdkVersion config.targetSdkVersion
+ }
+
+ buildTypes {
+ release {
+ minifyEnabled false
+ proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
+ }
+ }
+
+ buildFeatures {
+ compose true
+ }
+
+ composeOptions {
+ kotlinCompilerExtensionVersion = Versions.compose_compiler
+ }
+
+ namespace 'mozilla.components.compose.browser.toolbar'
+}
+
+dependencies {
+ implementation project(":concept-engine")
+ implementation project(":browser-state")
+ implementation project(":feature-session")
+ implementation project(":ui-icons")
+ implementation ComponentsDependencies.androidx_compose_ui
+ implementation ComponentsDependencies.androidx_compose_ui_tooling_preview
+ implementation ComponentsDependencies.androidx_compose_foundation
+ implementation ComponentsDependencies.androidx_compose_material
+
+ debugImplementation ComponentsDependencies.androidx_compose_ui_tooling
+
+ testImplementation project(':support-test')
+ testImplementation ComponentsDependencies.androidx_compose_ui_test
+ testImplementation ComponentsDependencies.androidx_test_core
+ testImplementation ComponentsDependencies.androidx_test_junit
+ testImplementation ComponentsDependencies.testing_robolectric
+}
+
+apply from: '../../../android-lint.gradle'
+apply from: '../../../publish.gradle'
+ext.configurePublish(config.componentsGroupId, archivesBaseName, project.ext.description)
diff --git a/mobile/android/android-components/components/compose/browser-toolbar/proguard-rules.pro b/mobile/android/android-components/components/compose/browser-toolbar/proguard-rules.pro
new file mode 100644
index 0000000000..f1b424510d
--- /dev/null
+++ b/mobile/android/android-components/components/compose/browser-toolbar/proguard-rules.pro
@@ -0,0 +1,21 @@
+# Add project specific ProGuard rules here.
+# You can control the set of applied configuration files using the
+# proguardFiles setting in build.gradle.
+#
+# For more details, see
+# http://developer.android.com/guide/developing/tools/proguard.html
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+# public *;
+#}
+
+# Uncomment this to preserve the line number information for
+# debugging stack traces.
+#-keepattributes SourceFile,LineNumberTable
+
+# If you keep the line number information, uncomment this to
+# hide the original source file name.
+#-renamesourcefileattribute SourceFile
diff --git a/mobile/android/android-components/components/compose/browser-toolbar/src/main/AndroidManifest.xml b/mobile/android/android-components/components/compose/browser-toolbar/src/main/AndroidManifest.xml
new file mode 100644
index 0000000000..e16cda1d34
--- /dev/null
+++ b/mobile/android/android-components/components/compose/browser-toolbar/src/main/AndroidManifest.xml
@@ -0,0 +1,4 @@
+<!-- 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/. -->
+<manifest />
diff --git a/mobile/android/android-components/components/compose/browser-toolbar/src/main/java/mozilla/components/compose/browser/toolbar/BrowserDisplayToolbar.kt b/mobile/android/android-components/components/compose/browser-toolbar/src/main/java/mozilla/components/compose/browser/toolbar/BrowserDisplayToolbar.kt
new file mode 100644
index 0000000000..f4169184aa
--- /dev/null
+++ b/mobile/android/android-components/components/compose/browser-toolbar/src/main/java/mozilla/components/compose/browser/toolbar/BrowserDisplayToolbar.kt
@@ -0,0 +1,62 @@
+/* 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 mozilla.components.compose.browser.toolbar
+
+import androidx.compose.foundation.background
+import androidx.compose.foundation.clickable
+import androidx.compose.foundation.layout.Row
+import androidx.compose.foundation.layout.padding
+import androidx.compose.material.Button
+import androidx.compose.material.MaterialTheme
+import androidx.compose.material.Text
+import androidx.compose.material.contentColorFor
+import androidx.compose.material.primarySurface
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.Alignment
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.unit.dp
+
+/**
+ * Sub-component of the [BrowserToolbar] responsible for displaying the URL and related
+ * controls ("display mode").
+ *
+ * @param url The URL to be displayed.
+ * @param onUrlClicked Will be called when the user clicks on the URL.
+ * @param onMenuClicked Will be called when the user clicks on the menu button.
+ * @param browserActions Additional browser actions to be displayed on the right side of the toolbar
+ * (outside of the URL bounding box) in display mode. Also see:
+ * [MDN docs](https://developer.mozilla.org/en-US/Add-ons/WebExtensions/user_interface/Browser_action)
+ */
+@Composable
+fun BrowserDisplayToolbar(
+ url: String,
+ onUrlClicked: () -> Unit = {},
+ onMenuClicked: () -> Unit = {},
+ browserActions: @Composable () -> Unit = {},
+) {
+ val backgroundColor = MaterialTheme.colors.primarySurface
+ val foregroundColor = contentColorFor(backgroundColor)
+
+ Row(
+ Modifier.background(backgroundColor),
+ ) {
+ Text(
+ url,
+ color = foregroundColor,
+ modifier = Modifier
+ .clickable { onUrlClicked() }
+ .padding(8.dp)
+ .weight(1f)
+ .align(Alignment.CenterVertically),
+ maxLines = 1,
+ )
+
+ browserActions()
+
+ Button(onClick = { onMenuClicked() }) {
+ Text(":")
+ }
+ }
+}
diff --git a/mobile/android/android-components/components/compose/browser-toolbar/src/main/java/mozilla/components/compose/browser/toolbar/BrowserEditToolbar.kt b/mobile/android/android-components/components/compose/browser-toolbar/src/main/java/mozilla/components/compose/browser/toolbar/BrowserEditToolbar.kt
new file mode 100644
index 0000000000..455fc1b2a0
--- /dev/null
+++ b/mobile/android/android-components/components/compose/browser-toolbar/src/main/java/mozilla/components/compose/browser/toolbar/BrowserEditToolbar.kt
@@ -0,0 +1,93 @@
+/* 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 mozilla.components.compose.browser.toolbar
+
+import androidx.compose.foundation.layout.fillMaxWidth
+import androidx.compose.foundation.layout.requiredSize
+import androidx.compose.foundation.text.KeyboardActions
+import androidx.compose.foundation.text.KeyboardOptions
+import androidx.compose.material.Icon
+import androidx.compose.material.IconButton
+import androidx.compose.material.MaterialTheme
+import androidx.compose.material.TextField
+import androidx.compose.material.TextFieldDefaults
+import androidx.compose.material.contentColorFor
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.res.painterResource
+import androidx.compose.ui.res.stringResource
+import androidx.compose.ui.text.input.ImeAction
+import androidx.compose.ui.text.input.KeyboardType
+import androidx.compose.ui.unit.dp
+import mozilla.components.ui.icons.R as iconsR
+
+/**
+ * Sub-component of the [BrowserToolbar] responsible for allowing the user to edit the current
+ * URL ("edit mode").
+ *
+ * @param url The initial URL to be edited.
+ * @param onUrlEdit Will be called when the URL value changes. An updated text value comes as a
+ * parameter of the callback.
+ * @param onUrlCommitted Will be called when the user has finished editing and wants to initiate
+ * loading the entered URL. The committed text value comes as a parameter of the callback.
+ * @param editActions Optional actions to be displayed on the right side of the toolbar.
+ */
+@Composable
+fun BrowserEditToolbar(
+ url: String,
+ onUrlEdit: (String) -> Unit = {},
+ onUrlCommitted: (String) -> Unit = {},
+ editActions: @Composable () -> Unit = {},
+) {
+ val backgroundColor = MaterialTheme.colors.surface
+ val foregroundColor = contentColorFor(backgroundColor)
+
+ TextField(
+ url,
+ onValueChange = { value ->
+ onUrlEdit(value)
+ },
+ colors = TextFieldDefaults.textFieldColors(
+ textColor = foregroundColor,
+ backgroundColor = backgroundColor,
+ ),
+ singleLine = true,
+ keyboardOptions = KeyboardOptions(
+ keyboardType = KeyboardType.Uri,
+ imeAction = ImeAction.Go,
+ ),
+ keyboardActions = KeyboardActions(
+ onGo = { onUrlCommitted(url) },
+ ),
+ modifier = Modifier.fillMaxWidth(),
+ trailingIcon = {
+ editActions()
+
+ if (url.isNotEmpty()) {
+ ClearButton(onButtonClicked = { onUrlEdit("") })
+ }
+ },
+ )
+}
+
+/**
+ * Sub-component of the [BrowserEditToolbar] responsible for displaying a clear icon button.
+ *
+ * @param onButtonClicked Will be called when the user clicks on the button.
+ */
+@Composable
+fun ClearButton(onButtonClicked: () -> Unit = {}) {
+ IconButton(
+ modifier = Modifier.requiredSize(40.dp),
+ onClick = { onButtonClicked() },
+ ) {
+ Icon(
+ painter = painterResource(iconsR.drawable.mozac_ic_cross_circle_fill_24),
+ contentDescription = stringResource(R.string.mozac_clear_button_description),
+ tint = Color.Black,
+ )
+ }
+}
diff --git a/mobile/android/android-components/components/compose/browser-toolbar/src/main/java/mozilla/components/compose/browser/toolbar/BrowserToolbar.kt b/mobile/android/android-components/components/compose/browser-toolbar/src/main/java/mozilla/components/compose/browser/toolbar/BrowserToolbar.kt
new file mode 100644
index 0000000000..37c4b8f19f
--- /dev/null
+++ b/mobile/android/android-components/components/compose/browser-toolbar/src/main/java/mozilla/components/compose/browser/toolbar/BrowserToolbar.kt
@@ -0,0 +1,77 @@
+/* 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 mozilla.components.compose.browser.toolbar
+
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.getValue
+import mozilla.components.browser.state.helper.Target
+import mozilla.components.browser.state.state.SessionState
+import mozilla.components.browser.state.store.BrowserStore
+
+/**
+ * A customizable toolbar for browsers.
+ *
+ * The toolbar can switch between two modes: display and edit. The display mode displays the current
+ * URL and controls for navigation. In edit mode the current URL can be edited. Those two modes are
+ * implemented by the [BrowserDisplayToolbar] and [BrowserEditToolbar] composables.
+ *
+ * @param store The store to observe the [target] from.
+ * @param target The target tab to observe.
+ * @param onDisplayMenuClicked Function to get executed when the user clicks on the menu button in
+ * "display" mode.
+ * @param onTextEdit Function to get executed whenever the user edits the text in the toolbar in
+ * "edit" mode.
+ * @param onTextCommit Function to get executed when the user has finished editing the URL and wants
+ * to load the entered text.
+ * @param onDisplayToolbarClick Function to get executed when the user clicks on the URL in "display"
+ * mode.
+ * @param hint Text displayed in the toolbar when there's no URL to display (no tab or empty URL)
+ * @param editMode Whether the toolbar is in "edit" or "display" mode.
+ * @param editText The text the user is editing in "edit" mode.
+ * @param browserActions Additional browser actions to be displayed on the right side of the toolbar
+ * (outside of the URL bounding box) in display mode. Also see:
+ * [MDN docs](https://developer.mozilla.org/en-US/Add-ons/WebExtensions/user_interface/Browser_action)
+ */
+@Composable
+fun BrowserToolbar(
+ store: BrowserStore,
+ target: Target,
+ onDisplayMenuClicked: () -> Unit,
+ onTextEdit: (String) -> Unit,
+ onTextCommit: (String) -> Unit,
+ onDisplayToolbarClick: () -> Unit,
+ hint: String = "",
+ editMode: Boolean = false,
+ editText: String? = null,
+ browserActions: @Composable () -> Unit = {},
+) {
+ val selectedTab: SessionState? by target.observeAsComposableStateFrom(
+ store = store,
+ observe = { tab -> tab?.content?.url },
+ )
+
+ val url = selectedTab?.content?.url ?: ""
+ val input = when (editText) {
+ null -> url
+ else -> editText
+ }
+
+ if (editMode) {
+ BrowserEditToolbar(
+ url = input,
+ onUrlCommitted = { text -> onTextCommit(text) },
+ onUrlEdit = { text -> onTextEdit(text) },
+ )
+ } else {
+ BrowserDisplayToolbar(
+ url = selectedTab?.content?.url ?: hint,
+ onUrlClicked = {
+ onDisplayToolbarClick()
+ },
+ onMenuClicked = { onDisplayMenuClicked() },
+ browserActions = browserActions,
+ )
+ }
+}
diff --git a/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-am/strings.xml b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-am/strings.xml
new file mode 100644
index 0000000000..cc83ed16e6
--- /dev/null
+++ b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-am/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description for the clear URL text button. -->
+ <string name="mozac_clear_button_description">አጽዳ</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-ar/strings.xml b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-ar/strings.xml
new file mode 100644
index 0000000000..c9d3504f7a
--- /dev/null
+++ b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-ar/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description for the clear URL text button. -->
+ <string name="mozac_clear_button_description">امسح</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-ast/strings.xml b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-ast/strings.xml
new file mode 100644
index 0000000000..8969801e9c
--- /dev/null
+++ b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-ast/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description for the clear URL text button. -->
+ <string name="mozac_clear_button_description">Borrar</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-azb/strings.xml b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-azb/strings.xml
new file mode 100644
index 0000000000..6f4f648a48
--- /dev/null
+++ b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-azb/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description for the clear URL text button. -->
+ <string name="mozac_clear_button_description">تمیزله</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-ban/strings.xml b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-ban/strings.xml
new file mode 100644
index 0000000000..d5f16e8163
--- /dev/null
+++ b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-ban/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description for the clear URL text button. -->
+ <string name="mozac_clear_button_description">Puyung</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-be/strings.xml b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-be/strings.xml
new file mode 100644
index 0000000000..70c10b132a
--- /dev/null
+++ b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-be/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description for the clear URL text button. -->
+ <string name="mozac_clear_button_description">Ачысціць</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-bg/strings.xml b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-bg/strings.xml
new file mode 100644
index 0000000000..0f5a47334b
--- /dev/null
+++ b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-bg/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description for the clear URL text button. -->
+ <string name="mozac_clear_button_description">Изчистване</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-br/strings.xml b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-br/strings.xml
new file mode 100644
index 0000000000..d38dc27f6b
--- /dev/null
+++ b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-br/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description for the clear URL text button. -->
+ <string name="mozac_clear_button_description">Skarzhañ</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-bs/strings.xml b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-bs/strings.xml
new file mode 100644
index 0000000000..8bc86d499b
--- /dev/null
+++ b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-bs/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description for the clear URL text button. -->
+ <string name="mozac_clear_button_description">Očisti</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-ca/strings.xml b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-ca/strings.xml
new file mode 100644
index 0000000000..018996c9c9
--- /dev/null
+++ b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-ca/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description for the clear URL text button. -->
+ <string name="mozac_clear_button_description">Esborra</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-cak/strings.xml b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-cak/strings.xml
new file mode 100644
index 0000000000..bbd7009b91
--- /dev/null
+++ b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-cak/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description for the clear URL text button. -->
+ <string name="mozac_clear_button_description">Tijosq\'ïx</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-ceb/strings.xml b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-ceb/strings.xml
new file mode 100644
index 0000000000..2925ea5493
--- /dev/null
+++ b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-ceb/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description for the clear URL text button. -->
+ <string name="mozac_clear_button_description">i-Clear</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-ckb/strings.xml b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-ckb/strings.xml
new file mode 100644
index 0000000000..086ca6fc70
--- /dev/null
+++ b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-ckb/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description for the clear URL text button. -->
+ <string name="mozac_clear_button_description">پاککردنەوە</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-co/strings.xml b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-co/strings.xml
new file mode 100644
index 0000000000..b5fe5d43e5
--- /dev/null
+++ b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-co/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description for the clear URL text button. -->
+ <string name="mozac_clear_button_description">Squassà</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-cs/strings.xml b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-cs/strings.xml
new file mode 100644
index 0000000000..32faa95f9c
--- /dev/null
+++ b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-cs/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description for the clear URL text button. -->
+ <string name="mozac_clear_button_description">Vymazat</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-cy/strings.xml b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-cy/strings.xml
new file mode 100644
index 0000000000..69f49ff160
--- /dev/null
+++ b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-cy/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description for the clear URL text button. -->
+ <string name="mozac_clear_button_description">Clirio</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-da/strings.xml b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-da/strings.xml
new file mode 100644
index 0000000000..3b0a1d032f
--- /dev/null
+++ b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-da/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description for the clear URL text button. -->
+ <string name="mozac_clear_button_description">Ryd</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-de/strings.xml b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-de/strings.xml
new file mode 100644
index 0000000000..6858b4ca9c
--- /dev/null
+++ b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-de/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description for the clear URL text button. -->
+ <string name="mozac_clear_button_description">Löschen</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-dsb/strings.xml b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-dsb/strings.xml
new file mode 100644
index 0000000000..b63020c065
--- /dev/null
+++ b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-dsb/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description for the clear URL text button. -->
+ <string name="mozac_clear_button_description">Lašowaś</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-el/strings.xml b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-el/strings.xml
new file mode 100644
index 0000000000..081fa1408f
--- /dev/null
+++ b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-el/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description for the clear URL text button. -->
+ <string name="mozac_clear_button_description">Απαλοιφή</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-en-rCA/strings.xml b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-en-rCA/strings.xml
new file mode 100644
index 0000000000..4623e3ea6f
--- /dev/null
+++ b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-en-rCA/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description for the clear URL text button. -->
+ <string name="mozac_clear_button_description">Clear</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-en-rGB/strings.xml b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-en-rGB/strings.xml
new file mode 100644
index 0000000000..4623e3ea6f
--- /dev/null
+++ b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-en-rGB/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description for the clear URL text button. -->
+ <string name="mozac_clear_button_description">Clear</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-eo/strings.xml b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-eo/strings.xml
new file mode 100644
index 0000000000..147fe28ba9
--- /dev/null
+++ b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-eo/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description for the clear URL text button. -->
+ <string name="mozac_clear_button_description">Viŝi</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-es-rAR/strings.xml b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-es-rAR/strings.xml
new file mode 100644
index 0000000000..3bee2874ce
--- /dev/null
+++ b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-es-rAR/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description for the clear URL text button. -->
+ <string name="mozac_clear_button_description">Eliminar</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-es-rCL/strings.xml b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-es-rCL/strings.xml
new file mode 100644
index 0000000000..4d4c14d193
--- /dev/null
+++ b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-es-rCL/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description for the clear URL text button. -->
+ <string name="mozac_clear_button_description">Limpiar</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-es-rES/strings.xml b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-es-rES/strings.xml
new file mode 100644
index 0000000000..8969801e9c
--- /dev/null
+++ b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-es-rES/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description for the clear URL text button. -->
+ <string name="mozac_clear_button_description">Borrar</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-es-rMX/strings.xml b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-es-rMX/strings.xml
new file mode 100644
index 0000000000..4d4c14d193
--- /dev/null
+++ b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-es-rMX/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description for the clear URL text button. -->
+ <string name="mozac_clear_button_description">Limpiar</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-es/strings.xml b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-es/strings.xml
new file mode 100644
index 0000000000..8969801e9c
--- /dev/null
+++ b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-es/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description for the clear URL text button. -->
+ <string name="mozac_clear_button_description">Borrar</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-et/strings.xml b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-et/strings.xml
new file mode 100644
index 0000000000..2257c3c05b
--- /dev/null
+++ b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-et/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description for the clear URL text button. -->
+ <string name="mozac_clear_button_description">Tühjenda</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-eu/strings.xml b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-eu/strings.xml
new file mode 100644
index 0000000000..ff2b1734b6
--- /dev/null
+++ b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-eu/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description for the clear URL text button. -->
+ <string name="mozac_clear_button_description">Garbitu</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-fa/strings.xml b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-fa/strings.xml
new file mode 100644
index 0000000000..d5f3070338
--- /dev/null
+++ b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-fa/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description for the clear URL text button. -->
+ <string name="mozac_clear_button_description">پاک کردن</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-fi/strings.xml b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-fi/strings.xml
new file mode 100644
index 0000000000..a2b754496a
--- /dev/null
+++ b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-fi/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description for the clear URL text button. -->
+ <string name="mozac_clear_button_description">Tyhjennä</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-fr/strings.xml b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-fr/strings.xml
new file mode 100644
index 0000000000..2fa9bb437d
--- /dev/null
+++ b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-fr/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description for the clear URL text button. -->
+ <string name="mozac_clear_button_description">Effacer</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-fur/strings.xml b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-fur/strings.xml
new file mode 100644
index 0000000000..0dac627d5a
--- /dev/null
+++ b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-fur/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description for the clear URL text button. -->
+ <string name="mozac_clear_button_description">Nete</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-fy-rNL/strings.xml b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-fy-rNL/strings.xml
new file mode 100644
index 0000000000..91cb2126f6
--- /dev/null
+++ b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-fy-rNL/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description for the clear URL text button. -->
+ <string name="mozac_clear_button_description">Wiskje</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-gd/strings.xml b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-gd/strings.xml
new file mode 100644
index 0000000000..f3515f5318
--- /dev/null
+++ b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-gd/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description for the clear URL text button. -->
+ <string name="mozac_clear_button_description">Falamhaich</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-gl/strings.xml b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-gl/strings.xml
new file mode 100644
index 0000000000..8969801e9c
--- /dev/null
+++ b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-gl/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description for the clear URL text button. -->
+ <string name="mozac_clear_button_description">Borrar</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-gn/strings.xml b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-gn/strings.xml
new file mode 100644
index 0000000000..f1f838a3fa
--- /dev/null
+++ b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-gn/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description for the clear URL text button. -->
+ <string name="mozac_clear_button_description">Mopotĩ</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-hi-rIN/strings.xml b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-hi-rIN/strings.xml
new file mode 100644
index 0000000000..3066768614
--- /dev/null
+++ b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-hi-rIN/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description for the clear URL text button. -->
+ <string name="mozac_clear_button_description">साफ करें</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-hil/strings.xml b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-hil/strings.xml
new file mode 100644
index 0000000000..f213be78ce
--- /dev/null
+++ b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-hil/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description for the clear URL text button. -->
+ <string name="mozac_clear_button_description">Maathag</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-hr/strings.xml b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-hr/strings.xml
new file mode 100644
index 0000000000..8bc86d499b
--- /dev/null
+++ b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-hr/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description for the clear URL text button. -->
+ <string name="mozac_clear_button_description">Očisti</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-hsb/strings.xml b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-hsb/strings.xml
new file mode 100644
index 0000000000..db7ed389d1
--- /dev/null
+++ b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-hsb/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description for the clear URL text button. -->
+ <string name="mozac_clear_button_description">Zhašeć</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-hu/strings.xml b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-hu/strings.xml
new file mode 100644
index 0000000000..240457e51a
--- /dev/null
+++ b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-hu/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description for the clear URL text button. -->
+ <string name="mozac_clear_button_description">Törlés</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-hy-rAM/strings.xml b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-hy-rAM/strings.xml
new file mode 100644
index 0000000000..3161e41469
--- /dev/null
+++ b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-hy-rAM/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description for the clear URL text button. -->
+ <string name="mozac_clear_button_description">Մաքրել</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-ia/strings.xml b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-ia/strings.xml
new file mode 100644
index 0000000000..9e74fc636d
--- /dev/null
+++ b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-ia/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description for the clear URL text button. -->
+ <string name="mozac_clear_button_description">Vacuar</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-in/strings.xml b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-in/strings.xml
new file mode 100644
index 0000000000..5b7255a507
--- /dev/null
+++ b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-in/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description for the clear URL text button. -->
+ <string name="mozac_clear_button_description">Bersihkan</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-is/strings.xml b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-is/strings.xml
new file mode 100644
index 0000000000..937c569911
--- /dev/null
+++ b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-is/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description for the clear URL text button. -->
+ <string name="mozac_clear_button_description">Hreinsa</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-it/strings.xml b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-it/strings.xml
new file mode 100644
index 0000000000..50fac45c09
--- /dev/null
+++ b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-it/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description for the clear URL text button. -->
+ <string name="mozac_clear_button_description">Cancella</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-iw/strings.xml b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-iw/strings.xml
new file mode 100644
index 0000000000..6d2a870121
--- /dev/null
+++ b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-iw/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description for the clear URL text button. -->
+ <string name="mozac_clear_button_description">ניקוי</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-ja/strings.xml b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-ja/strings.xml
new file mode 100644
index 0000000000..aac287abba
--- /dev/null
+++ b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-ja/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description for the clear URL text button. -->
+ <string name="mozac_clear_button_description">消去</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-ka/strings.xml b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-ka/strings.xml
new file mode 100644
index 0000000000..8f2d68db5a
--- /dev/null
+++ b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-ka/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description for the clear URL text button. -->
+ <string name="mozac_clear_button_description">გასუფთავება</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-kaa/strings.xml b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-kaa/strings.xml
new file mode 100644
index 0000000000..d353a36ede
--- /dev/null
+++ b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-kaa/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description for the clear URL text button. -->
+ <string name="mozac_clear_button_description">Tazalaw</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-kab/strings.xml b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-kab/strings.xml
new file mode 100644
index 0000000000..57e718ffd4
--- /dev/null
+++ b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-kab/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description for the clear URL text button. -->
+ <string name="mozac_clear_button_description">Sfeḍ</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-kk/strings.xml b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-kk/strings.xml
new file mode 100644
index 0000000000..f37edf1617
--- /dev/null
+++ b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-kk/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description for the clear URL text button. -->
+ <string name="mozac_clear_button_description">Тазарту</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-kmr/strings.xml b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-kmr/strings.xml
new file mode 100644
index 0000000000..ea5900bfd7
--- /dev/null
+++ b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-kmr/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description for the clear URL text button. -->
+ <string name="mozac_clear_button_description">Paqij bike</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-ko/strings.xml b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-ko/strings.xml
new file mode 100644
index 0000000000..35026ad285
--- /dev/null
+++ b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-ko/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description for the clear URL text button. -->
+ <string name="mozac_clear_button_description">지우기</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-lo/strings.xml b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-lo/strings.xml
new file mode 100644
index 0000000000..fc861c9736
--- /dev/null
+++ b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-lo/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description for the clear URL text button. -->
+ <string name="mozac_clear_button_description">ລົບລ້າງ</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-lt/strings.xml b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-lt/strings.xml
new file mode 100644
index 0000000000..b13f1a2607
--- /dev/null
+++ b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-lt/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description for the clear URL text button. -->
+ <string name="mozac_clear_button_description">Išvalyti</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-mix/strings.xml b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-mix/strings.xml
new file mode 100644
index 0000000000..32ec654860
--- /dev/null
+++ b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-mix/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description for the clear URL text button. -->
+ <string name="mozac_clear_button_description">Stòo</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-mr/strings.xml b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-mr/strings.xml
new file mode 100644
index 0000000000..15f1015506
--- /dev/null
+++ b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-mr/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description for the clear URL text button. -->
+ <string name="mozac_clear_button_description">पुसा</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-my/strings.xml b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-my/strings.xml
new file mode 100644
index 0000000000..e6d5127701
--- /dev/null
+++ b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-my/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description for the clear URL text button. -->
+ <string name="mozac_clear_button_description">ရှင်းမည်</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-nb-rNO/strings.xml b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-nb-rNO/strings.xml
new file mode 100644
index 0000000000..cc9fc95eaf
--- /dev/null
+++ b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-nb-rNO/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description for the clear URL text button. -->
+ <string name="mozac_clear_button_description">Tøm</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-ne-rNP/strings.xml b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-ne-rNP/strings.xml
new file mode 100644
index 0000000000..5701e65481
--- /dev/null
+++ b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-ne-rNP/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description for the clear URL text button. -->
+ <string name="mozac_clear_button_description">मेटाउनुहोस्</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-nl/strings.xml b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-nl/strings.xml
new file mode 100644
index 0000000000..d0a8d68480
--- /dev/null
+++ b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-nl/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description for the clear URL text button. -->
+ <string name="mozac_clear_button_description">Wissen</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-nn-rNO/strings.xml b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-nn-rNO/strings.xml
new file mode 100644
index 0000000000..cc9fc95eaf
--- /dev/null
+++ b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-nn-rNO/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description for the clear URL text button. -->
+ <string name="mozac_clear_button_description">Tøm</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-oc/strings.xml b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-oc/strings.xml
new file mode 100644
index 0000000000..7c2f957fea
--- /dev/null
+++ b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-oc/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description for the clear URL text button. -->
+ <string name="mozac_clear_button_description">Escafar</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-pa-rIN/strings.xml b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-pa-rIN/strings.xml
new file mode 100644
index 0000000000..146f91fc44
--- /dev/null
+++ b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-pa-rIN/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description for the clear URL text button. -->
+ <string name="mozac_clear_button_description">ਮਿਟਾਓ</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-pa-rPK/strings.xml b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-pa-rPK/strings.xml
new file mode 100644
index 0000000000..638b35e354
--- /dev/null
+++ b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-pa-rPK/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description for the clear URL text button. -->
+ <string name="mozac_clear_button_description">صاف کرو</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-pl/strings.xml b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-pl/strings.xml
new file mode 100644
index 0000000000..fba0dba88d
--- /dev/null
+++ b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-pl/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description for the clear URL text button. -->
+ <string name="mozac_clear_button_description">Wyczyść</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-pt-rBR/strings.xml b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-pt-rBR/strings.xml
new file mode 100644
index 0000000000..2bc6e2c75c
--- /dev/null
+++ b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-pt-rBR/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description for the clear URL text button. -->
+ <string name="mozac_clear_button_description">Limpar</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-pt-rPT/strings.xml b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-pt-rPT/strings.xml
new file mode 100644
index 0000000000..2bc6e2c75c
--- /dev/null
+++ b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-pt-rPT/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description for the clear URL text button. -->
+ <string name="mozac_clear_button_description">Limpar</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-rm/strings.xml b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-rm/strings.xml
new file mode 100644
index 0000000000..119b5bb88a
--- /dev/null
+++ b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-rm/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description for the clear URL text button. -->
+ <string name="mozac_clear_button_description">Stizzar</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-ru/strings.xml b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-ru/strings.xml
new file mode 100644
index 0000000000..0047495c9b
--- /dev/null
+++ b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-ru/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description for the clear URL text button. -->
+ <string name="mozac_clear_button_description">Очистить</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-sat/strings.xml b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-sat/strings.xml
new file mode 100644
index 0000000000..45acd3ce30
--- /dev/null
+++ b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-sat/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description for the clear URL text button. -->
+ <string name="mozac_clear_button_description">ᱯᱷᱟᱨᱪᱟ</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-sc/strings.xml b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-sc/strings.xml
new file mode 100644
index 0000000000..5714c62681
--- /dev/null
+++ b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-sc/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description for the clear URL text button. -->
+ <string name="mozac_clear_button_description">Isbòida</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-si/strings.xml b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-si/strings.xml
new file mode 100644
index 0000000000..f293461379
--- /dev/null
+++ b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-si/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description for the clear URL text button. -->
+ <string name="mozac_clear_button_description">මකන්න</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-sk/strings.xml b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-sk/strings.xml
new file mode 100644
index 0000000000..0947ba13c0
--- /dev/null
+++ b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-sk/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description for the clear URL text button. -->
+ <string name="mozac_clear_button_description">Vymazať</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-skr/strings.xml b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-skr/strings.xml
new file mode 100644
index 0000000000..638b35e354
--- /dev/null
+++ b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-skr/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description for the clear URL text button. -->
+ <string name="mozac_clear_button_description">صاف کرو</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-sl/strings.xml b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-sl/strings.xml
new file mode 100644
index 0000000000..a7c9e71591
--- /dev/null
+++ b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-sl/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description for the clear URL text button. -->
+ <string name="mozac_clear_button_description">Počisti</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-sq/strings.xml b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-sq/strings.xml
new file mode 100644
index 0000000000..a64bf5d1cd
--- /dev/null
+++ b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-sq/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description for the clear URL text button. -->
+ <string name="mozac_clear_button_description">Spastroje</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-sr/strings.xml b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-sr/strings.xml
new file mode 100644
index 0000000000..c177a14273
--- /dev/null
+++ b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-sr/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description for the clear URL text button. -->
+ <string name="mozac_clear_button_description">Избриши</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-su/strings.xml b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-su/strings.xml
new file mode 100644
index 0000000000..ff2dd9505c
--- /dev/null
+++ b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-su/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description for the clear URL text button. -->
+ <string name="mozac_clear_button_description">Beresihan</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-sv-rSE/strings.xml b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-sv-rSE/strings.xml
new file mode 100644
index 0000000000..5c48a34f29
--- /dev/null
+++ b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-sv-rSE/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description for the clear URL text button. -->
+ <string name="mozac_clear_button_description">Rensa</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-szl/strings.xml b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-szl/strings.xml
new file mode 100644
index 0000000000..2d780d888d
--- /dev/null
+++ b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-szl/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description for the clear URL text button. -->
+ <string name="mozac_clear_button_description">Wypucuj</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-ta/strings.xml b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-ta/strings.xml
new file mode 100644
index 0000000000..5b59215996
--- /dev/null
+++ b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-ta/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description for the clear URL text button. -->
+ <string name="mozac_clear_button_description">துடை</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-te/strings.xml b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-te/strings.xml
new file mode 100644
index 0000000000..d7291694e8
--- /dev/null
+++ b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-te/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description for the clear URL text button. -->
+ <string name="mozac_clear_button_description">తుడిచివేయి</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-tg/strings.xml b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-tg/strings.xml
new file mode 100644
index 0000000000..04bcc69e4c
--- /dev/null
+++ b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-tg/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description for the clear URL text button. -->
+ <string name="mozac_clear_button_description">Пок кардан</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-th/strings.xml b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-th/strings.xml
new file mode 100644
index 0000000000..19dfaf0570
--- /dev/null
+++ b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-th/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description for the clear URL text button. -->
+ <string name="mozac_clear_button_description">ล้าง</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-tl/strings.xml b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-tl/strings.xml
new file mode 100644
index 0000000000..2c4826414a
--- /dev/null
+++ b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-tl/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description for the clear URL text button. -->
+ <string name="mozac_clear_button_description">Malinaw</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-tok/strings.xml b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-tok/strings.xml
new file mode 100644
index 0000000000..bfb8cb0176
--- /dev/null
+++ b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-tok/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description for the clear URL text button. -->
+ <string name="mozac_clear_button_description">o weka ale</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-tr/strings.xml b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-tr/strings.xml
new file mode 100644
index 0000000000..7f12eb014a
--- /dev/null
+++ b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-tr/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description for the clear URL text button. -->
+ <string name="mozac_clear_button_description">Temizle</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-trs/strings.xml b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-trs/strings.xml
new file mode 100644
index 0000000000..d4117dca83
--- /dev/null
+++ b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-trs/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description for the clear URL text button. -->
+ <string name="mozac_clear_button_description">Nā\'nïn\'</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-tt/strings.xml b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-tt/strings.xml
new file mode 100644
index 0000000000..38e4b155a9
--- /dev/null
+++ b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-tt/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description for the clear URL text button. -->
+ <string name="mozac_clear_button_description">Чистарту</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-tzm/strings.xml b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-tzm/strings.xml
new file mode 100644
index 0000000000..57e718ffd4
--- /dev/null
+++ b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-tzm/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description for the clear URL text button. -->
+ <string name="mozac_clear_button_description">Sfeḍ</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-ug/strings.xml b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-ug/strings.xml
new file mode 100644
index 0000000000..b77a27beb2
--- /dev/null
+++ b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-ug/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description for the clear URL text button. -->
+ <string name="mozac_clear_button_description">تازىلاش</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-uk/strings.xml b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-uk/strings.xml
new file mode 100644
index 0000000000..21148d9315
--- /dev/null
+++ b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-uk/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description for the clear URL text button. -->
+ <string name="mozac_clear_button_description">Очистити</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-ur/strings.xml b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-ur/strings.xml
new file mode 100644
index 0000000000..9ba273e59b
--- /dev/null
+++ b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-ur/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description for the clear URL text button. -->
+ <string name="mozac_clear_button_description">صاف کریں</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-uz/strings.xml b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-uz/strings.xml
new file mode 100644
index 0000000000..2424d47c2a
--- /dev/null
+++ b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-uz/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description for the clear URL text button. -->
+ <string name="mozac_clear_button_description">Tozalash</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-vec/strings.xml b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-vec/strings.xml
new file mode 100644
index 0000000000..5f2923d53a
--- /dev/null
+++ b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-vec/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description for the clear URL text button. -->
+ <string name="mozac_clear_button_description">Pulisi</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-vi/strings.xml b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-vi/strings.xml
new file mode 100644
index 0000000000..192ec68ca5
--- /dev/null
+++ b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-vi/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description for the clear URL text button. -->
+ <string name="mozac_clear_button_description">Xóa</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-yo/strings.xml b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-yo/strings.xml
new file mode 100644
index 0000000000..e49144b27c
--- /dev/null
+++ b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-yo/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description for the clear URL text button. -->
+ <string name="mozac_clear_button_description">Paárẹ́</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-zh-rCN/strings.xml b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-zh-rCN/strings.xml
new file mode 100644
index 0000000000..21720f256a
--- /dev/null
+++ b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-zh-rCN/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description for the clear URL text button. -->
+ <string name="mozac_clear_button_description">清除</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-zh-rTW/strings.xml b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-zh-rTW/strings.xml
new file mode 100644
index 0000000000..21720f256a
--- /dev/null
+++ b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-zh-rTW/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description for the clear URL text button. -->
+ <string name="mozac_clear_button_description">清除</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values/strings.xml b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values/strings.xml
new file mode 100644
index 0000000000..ae85fd5c80
--- /dev/null
+++ b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values/strings.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- This Source Code Form is subject to the terms of the Mozilla Public
+ - License, v. 2.0. If a copy of the MPL was not distributed with this
+ - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
+<resources>
+ <!-- Content description for the clear URL text button. -->
+ <string name="mozac_clear_button_description">Clear</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/browser-toolbar/src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker b/mobile/android/android-components/components/compose/browser-toolbar/src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker
new file mode 100644
index 0000000000..cf1c399ea8
--- /dev/null
+++ b/mobile/android/android-components/components/compose/browser-toolbar/src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker
@@ -0,0 +1,2 @@
+mock-maker-inline
+// This allows mocking final classes (classes are final by default in Kotlin)
diff --git a/mobile/android/android-components/components/compose/cfr/README.md b/mobile/android/android-components/components/compose/cfr/README.md
new file mode 100644
index 0000000000..843ac13f7f
--- /dev/null
+++ b/mobile/android/android-components/components/compose/cfr/README.md
@@ -0,0 +1,49 @@
+# [Android Components](../../../README.md) > Compose > Tabs tray
+
+A standard Contextual Feature Recommendation popup using Jetpack Compose.
+
+## Usage
+
+```kotlin
+CFRPopup(
+ anchor = <View>,
+ properties = CFRPopupProperties(
+ popupWidth = 256.dp,
+ popupAlignment = INDICATOR_CENTERED_IN_ANCHOR,
+ popupBodyColors = listOf(
+ ContextCompat.getColor(context, R.color.color1),
+ ContextCompat.getColor(context, R.color.color2)
+ ),
+ dismissButtonColor = ContextCompat.getColor(context, R.color.color3),
+ ),
+ onDismiss = { <method call> },
+ text = {
+ Text(
+ text = stringResource(R.string.string1),
+ style = MaterialTheme.typography.body2,
+ )
+ },
+ action = {
+ Button(onClick = { <method call> }) {
+ Text(text = stringResource(R.string.string2))
+ }
+ },
+).apply {
+ show()
+}
+```
+
+
+### Setting up the dependency
+
+Use Gradle to download the library from [maven.mozilla.org](https://maven.mozilla.org/) ([Setup repository](../../../README.md#maven-repository)):
+
+```Groovy
+implementation "org.mozilla.components:compose-cfr:{latest-version}"
+```
+
+## License
+
+ 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/
diff --git a/mobile/android/android-components/components/compose/cfr/build.gradle b/mobile/android/android-components/components/compose/cfr/build.gradle
new file mode 100644
index 0000000000..84e722924e
--- /dev/null
+++ b/mobile/android/android-components/components/compose/cfr/build.gradle
@@ -0,0 +1,63 @@
+/* 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/. */
+
+apply plugin: 'com.android.library'
+apply plugin: 'kotlin-android'
+
+android {
+ defaultConfig {
+ minSdkVersion config.minSdkVersion
+ compileSdk config.compileSdkVersion
+ targetSdkVersion config.targetSdkVersion
+ testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
+ }
+
+ buildTypes {
+ release {
+ minifyEnabled false
+ proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
+ }
+ }
+
+ buildFeatures {
+ compose true
+ }
+
+ composeOptions {
+ kotlinCompilerExtensionVersion = Versions.compose_compiler
+ }
+
+ kotlinOptions {
+ freeCompilerArgs += "-Xjvm-default=all"
+ }
+
+ namespace 'mozilla.components.compose.cfr'
+}
+
+dependencies {
+ implementation platform(ComponentsDependencies.androidx_compose_bom)
+ implementation project(':support-ktx')
+ implementation project(':ui-icons')
+
+ implementation ComponentsDependencies.androidx_compose_ui
+ implementation ComponentsDependencies.androidx_compose_ui_tooling_preview
+ implementation ComponentsDependencies.androidx_compose_foundation
+ implementation ComponentsDependencies.androidx_compose_material
+ implementation ComponentsDependencies.androidx_core
+ implementation ComponentsDependencies.androidx_core_ktx
+ implementation ComponentsDependencies.androidx_lifecycle_runtime
+ implementation ComponentsDependencies.androidx_savedstate
+
+ debugImplementation ComponentsDependencies.androidx_compose_ui_tooling
+
+ testImplementation project(':support-test')
+ testImplementation ComponentsDependencies.testing_coroutines
+ testImplementation ComponentsDependencies.androidx_test_core
+ testImplementation ComponentsDependencies.androidx_test_junit
+ testImplementation ComponentsDependencies.testing_junit
+ testImplementation ComponentsDependencies.testing_robolectric
+}
+
+apply from: '../../../publish.gradle'
+ext.configurePublish(config.componentsGroupId, archivesBaseName, project.ext.description)
diff --git a/mobile/android/android-components/components/compose/cfr/proguard-rules.pro b/mobile/android/android-components/components/compose/cfr/proguard-rules.pro
new file mode 100644
index 0000000000..f1b424510d
--- /dev/null
+++ b/mobile/android/android-components/components/compose/cfr/proguard-rules.pro
@@ -0,0 +1,21 @@
+# Add project specific ProGuard rules here.
+# You can control the set of applied configuration files using the
+# proguardFiles setting in build.gradle.
+#
+# For more details, see
+# http://developer.android.com/guide/developing/tools/proguard.html
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+# public *;
+#}
+
+# Uncomment this to preserve the line number information for
+# debugging stack traces.
+#-keepattributes SourceFile,LineNumberTable
+
+# If you keep the line number information, uncomment this to
+# hide the original source file name.
+#-renamesourcefileattribute SourceFile
diff --git a/mobile/android/android-components/components/compose/cfr/src/main/AndroidManifest.xml b/mobile/android/android-components/components/compose/cfr/src/main/AndroidManifest.xml
new file mode 100644
index 0000000000..e16cda1d34
--- /dev/null
+++ b/mobile/android/android-components/components/compose/cfr/src/main/AndroidManifest.xml
@@ -0,0 +1,4 @@
+<!-- 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/. -->
+<manifest />
diff --git a/mobile/android/android-components/components/compose/cfr/src/main/java/mozilla/components/compose/cfr/CFRPopup.kt b/mobile/android/android-components/components/compose/cfr/src/main/java/mozilla/components/compose/cfr/CFRPopup.kt
new file mode 100644
index 0000000000..7d18e795b3
--- /dev/null
+++ b/mobile/android/android-components/components/compose/cfr/src/main/java/mozilla/components/compose/cfr/CFRPopup.kt
@@ -0,0 +1,195 @@
+/* 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 mozilla.components.compose.cfr
+
+import android.view.View
+import androidx.annotation.VisibleForTesting
+import androidx.compose.material.Text
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.graphics.toArgb
+import androidx.compose.ui.unit.Dp
+import androidx.compose.ui.unit.dp
+import mozilla.components.compose.cfr.CFRPopup.IndicatorDirection
+import mozilla.components.compose.cfr.CFRPopup.PopupAlignment
+import java.lang.ref.WeakReference
+
+/**
+ * Properties used to customize the behavior of a [CFRPopup].
+ *
+ * @property popupWidth Width of the popup. Defaults to [CFRPopup.DEFAULT_WIDTH]. To be used as maximum
+ * width when alignment is set to [PopupAlignment.BODY_CENTERED_IN_SCREEN].
+ * @property popupAlignment Where in relation to it's anchor should the popup be placed.
+ * @property popupBodyColors One or more colors serving as the popup background.
+ * If more colors are provided they will be used in a gradient.
+ * @property popupVerticalOffset Vertical distance between the indicator arrow and the anchor.
+ * This only applies if [overlapAnchor] is `false`.
+ * @property dismissButtonColor The tint color that should be applied to the dismiss button.
+ * @property dismissOnBackPress Whether the popup can be dismissed by pressing the back button.
+ * If true, pressing the back button will also call onDismiss().
+ * @property dismissOnClickOutside Whether the popup can be dismissed by clicking outside the
+ * popup's bounds. If true, clicking outside the popup will call onDismiss().
+ * @property overlapAnchor How the popup's indicator will be shown in relation to the anchor:
+ * - true - indicator will be shown exactly in the middle horizontally and vertically
+ * - false - indicator will be shown horizontally in the middle of the anchor but immediately below or above it
+ * @property indicatorDirection The direction the indicator arrow is pointing.
+ * @property indicatorArrowStartOffset Maximum distance between the popup start and the indicator arrow.
+ * If there isn't enough space this could automatically be overridden up to 0 such that
+ * the indicator arrow will be pointing to the middle of the anchor.
+ */
+data class CFRPopupProperties(
+ val popupWidth: Dp = CFRPopup.DEFAULT_WIDTH.dp,
+ val popupAlignment: PopupAlignment = PopupAlignment.BODY_TO_ANCHOR_CENTER,
+ val popupBodyColors: List<Int> = listOf(Color.Blue.toArgb()),
+ val popupVerticalOffset: Dp = CFRPopup.DEFAULT_VERTICAL_OFFSET.dp,
+ val showDismissButton: Boolean = true,
+ val dismissButtonColor: Int = Color.Black.toArgb(),
+ val dismissOnBackPress: Boolean = false,
+ val dismissOnClickOutside: Boolean = false,
+ val overlapAnchor: Boolean = false,
+ val indicatorDirection: IndicatorDirection = IndicatorDirection.UP,
+ val indicatorArrowStartOffset: Dp = CFRPopup.DEFAULT_INDICATOR_START_OFFSET.dp,
+)
+
+/**
+ * CFR - Contextual Feature Recommendation popup.
+ *
+ * @param anchor [View] that will serve as the anchor of the popup and serve as lifecycle owner
+ * for this popup also.
+ * @param properties [CFRPopupProperties] allowing to customize the popup appearance and behavior.
+ * @param onDismiss Callback for when the popup is dismissed indicating also if the dismissal
+ * was explicit - by tapping the "X" button or not.
+ * @param text [Text] already styled and ready to be shown in the popup.
+ * @param action Optional other composable to show just below the popup text.
+ */
+class CFRPopup(
+ @get:VisibleForTesting internal val anchor: View,
+ @get:VisibleForTesting internal val properties: CFRPopupProperties,
+ @get:VisibleForTesting internal val onDismiss: (Boolean) -> Unit = {},
+ @get:VisibleForTesting internal val text: @Composable (() -> Unit),
+ @get:VisibleForTesting internal val action: @Composable (() -> Unit) = {},
+) {
+ // This is just a facade for the CFRPopupFullScreenLayout composable offering a cleaner API.
+
+ @VisibleForTesting
+ internal var popup: WeakReference<CFRPopupFullscreenLayout>? = null
+
+ /**
+ * Construct and display a styled CFR popup shown at the coordinates of [anchor].
+ * This popup will be dismissed when the user clicks on the "x" button or based on other user actions
+ * with such behavior set in [CFRPopupProperties].
+ */
+ fun show() {
+ anchor.post {
+ // When we're in this Runnable, the 'show' method might have been called right before
+ // the activity is no longer attached to the WindowManager. When we get to calling
+ // the CFRPopupFullscreenLayout#show method below, we are now trying to attach the View
+ // with the WindowManager that has an unusable Activity.
+ //
+ // To protect against this, within this same Runnable, we check if the anchor view is
+ // safe to use before continuing.
+ //
+ // See: https://bugzilla.mozilla.org/show_bug.cgi?id=1799996
+ if (anchor.context == null || !anchor.isAttachedToWindow) {
+ return@post
+ }
+
+ CFRPopupFullscreenLayout(anchor, properties, onDismiss, text, action).apply {
+ this.show()
+ popup = WeakReference(this)
+ }
+ }
+ }
+
+ /**
+ * Immediately dismiss this CFR popup.
+ * The [onDismiss] callback won't be fired.
+ */
+ fun dismiss() {
+ popup?.get()?.dismiss()
+ }
+
+ /**
+ * Possible direction for the arrow indicator of a CFR popup.
+ * The direction is expressed in relation with the popup body containing the text.
+ */
+ enum class IndicatorDirection {
+ UP,
+ DOWN,
+ }
+
+ /**
+ * Possible alignments of the popup in relation to it's anchor.
+ */
+ enum class PopupAlignment {
+ /**
+ * The popup body will be centered in the space occupied by the anchor.
+ * Recommended to be used when the anchor is wider than the popup.
+ */
+ BODY_TO_ANCHOR_CENTER,
+
+ /**
+ * The popup body will be shown aligned to exactly the anchor start.
+ */
+ BODY_TO_ANCHOR_START,
+
+ /**
+ * The popup will be aligned such that the indicator arrow will point to exactly the middle of the anchor.
+ * Recommended to be used when there are multiple widgets displayed horizontally so that this will allow
+ * to indicate exactly which widget the popup refers to.
+ */
+ INDICATOR_CENTERED_IN_ANCHOR,
+
+ /**
+ * If the popup doesn't have enough space to expand to its full [CFRPopupProperties.popupWidth],
+ * it will be centred in the screen.
+ * If the popup does have enough space, it defaults to [INDICATOR_CENTERED_IN_ANCHOR].
+ * Recommended to be used when the popup text is very long.
+ */
+ BODY_CENTERED_IN_SCREEN,
+ }
+
+ companion object {
+ /**
+ * Default width for all CFRs.
+ */
+ internal const val DEFAULT_WIDTH = 335
+
+ /**
+ * Fixed horizontal padding.
+ * Allows the close button to extend with 10dp more to the end and intercept touches to
+ * a bit outside of the popup to ensure it respects a11y recommendations of 48dp size while
+ * also offer a bit more space to the text.
+ */
+ internal const val DEFAULT_EXTRA_HORIZONTAL_PADDING = 10
+
+ /**
+ * How tall the indicator arrow should be.
+ * This will also affect the width of the indicator's base which is double the height value.
+ */
+ internal const val DEFAULT_INDICATOR_HEIGHT = 7
+
+ /**
+ * Maximum distance between the popup start and the indicator.
+ */
+ internal const val DEFAULT_INDICATOR_START_OFFSET = 30
+
+ /**
+ * Corner radius for the popup body.
+ */
+ internal const val DEFAULT_CORNER_RADIUS = 12
+
+ /**
+ * Vertical distance between the indicator arrow and the anchor.
+ */
+ internal const val DEFAULT_VERTICAL_OFFSET = 9
+
+ /**
+ * Horizontal margin between the popup and viewport edges used to center the popup when alignment
+ * is set to [PopupAlignment.BODY_CENTERED_IN_SCREEN].
+ */
+ internal const val DEFAULT_HORIZONTAL_VIEWPORT_MARGIN_DP = 16
+ }
+}
diff --git a/mobile/android/android-components/components/compose/cfr/src/main/java/mozilla/components/compose/cfr/CFRPopupContent.kt b/mobile/android/android-components/components/compose/cfr/src/main/java/mozilla/components/compose/cfr/CFRPopupContent.kt
new file mode 100644
index 0000000000..318bf16829
--- /dev/null
+++ b/mobile/android/android-components/components/compose/cfr/src/main/java/mozilla/components/compose/cfr/CFRPopupContent.kt
@@ -0,0 +1,186 @@
+/* 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 mozilla.components.compose.cfr
+
+import android.content.res.Configuration
+import androidx.compose.foundation.background
+import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.layout.Column
+import androidx.compose.foundation.layout.padding
+import androidx.compose.foundation.layout.size
+import androidx.compose.foundation.layout.width
+import androidx.compose.foundation.layout.wrapContentHeight
+import androidx.compose.material.Icon
+import androidx.compose.material.IconButton
+import androidx.compose.material.Surface
+import androidx.compose.material.Text
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.Alignment
+import androidx.compose.ui.ExperimentalComposeUiApi
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.geometry.Offset
+import androidx.compose.ui.graphics.Brush
+import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.graphics.toArgb
+import androidx.compose.ui.res.painterResource
+import androidx.compose.ui.res.stringResource
+import androidx.compose.ui.semantics.semantics
+import androidx.compose.ui.semantics.testTag
+import androidx.compose.ui.semantics.testTagsAsResourceId
+import androidx.compose.ui.tooling.preview.Preview
+import androidx.compose.ui.unit.Dp
+import androidx.compose.ui.unit.dp
+import mozilla.components.compose.cfr.CFRPopup.IndicatorDirection.DOWN
+import mozilla.components.compose.cfr.CFRPopup.IndicatorDirection.UP
+import mozilla.components.ui.icons.R as iconsR
+
+/**
+ * Complete content of the popup.
+ * [CFRPopupShape] with a gradient background containing [text] and a dismiss ("X") button.
+ *
+ * @param popupBodyColors One or more colors serving as the popup background.
+ * @param dismissButtonColor The tint color that should be applied to the dismiss button.
+ * @param indicatorDirection The direction the indicator arrow is pointing to.
+ * @param indicatorArrowStartOffset Maximum distance between the popup start and the indicator arrow.
+ * If there isn't enough space this could automatically be overridden up to 0.
+ * @param onDismiss Callback for when the popup is dismissed indicating also if the dismissal
+ * was explicit - by tapping the "X" button or not.
+ * @param text [Text] already styled and ready to be shown in the popup.
+ * @param action Optional other composable to show just below the popup text.
+ */
+@OptIn(ExperimentalComposeUiApi::class)
+@Composable
+@Suppress("LongMethod")
+fun CFRPopupContent(
+ popupBodyColors: List<Int>,
+ showDismissButton: Boolean,
+ dismissButtonColor: Int,
+ indicatorDirection: CFRPopup.IndicatorDirection,
+ indicatorArrowStartOffset: Dp,
+ onDismiss: (Boolean) -> Unit,
+ popupWidth: Dp = CFRPopup.DEFAULT_WIDTH.dp,
+ text: @Composable (() -> Unit),
+ action: @Composable (() -> Unit) = {},
+) {
+ val popupShape = CFRPopupShape(
+ indicatorDirection,
+ indicatorArrowStartOffset,
+ CFRPopup.DEFAULT_INDICATOR_HEIGHT.dp,
+ CFRPopup.DEFAULT_CORNER_RADIUS.dp,
+ )
+
+ Box(modifier = Modifier.width(popupWidth + CFRPopup.DEFAULT_EXTRA_HORIZONTAL_PADDING.dp)) {
+ Surface(
+ color = Color.Transparent,
+ // Need to override the default RectangleShape to avoid casting shadows for that shape.
+ shape = popupShape,
+ modifier = Modifier
+ .align(Alignment.CenterStart)
+ .background(
+ shape = popupShape,
+ brush = Brush.linearGradient(
+ colors = popupBodyColors.map { Color(it) },
+ end = Offset(0f, Float.POSITIVE_INFINITY),
+ start = Offset(Float.POSITIVE_INFINITY, 0f),
+ ),
+ )
+ .wrapContentHeight()
+ .width(popupWidth),
+ ) {
+ Column(
+ modifier = Modifier
+ .padding(
+ start = 16.dp,
+ top = 16.dp + if (indicatorDirection == CFRPopup.IndicatorDirection.UP) {
+ CFRPopup.DEFAULT_INDICATOR_HEIGHT.dp
+ } else {
+ 0.dp
+ },
+ end = 16.dp,
+ bottom = 16.dp +
+ if (indicatorDirection == CFRPopup.IndicatorDirection.DOWN) {
+ CFRPopup.DEFAULT_INDICATOR_HEIGHT.dp
+ } else {
+ 0.dp
+ },
+ ),
+ ) {
+ Box(
+ modifier = Modifier.padding(
+ end = if (showDismissButton) 24.dp else 16.dp, // 8.dp extra padding to the "X" icon
+ ),
+ ) {
+ text()
+ }
+
+ action()
+ }
+ }
+
+ if (showDismissButton) {
+ IconButton(
+ onClick = { onDismiss(true) },
+ modifier = Modifier
+ .align(Alignment.TopEnd)
+ .padding(
+ end = 6.dp,
+ )
+ .size(48.dp)
+ .semantics {
+ testTagsAsResourceId = true
+ testTag = "cfr.dismiss"
+ },
+ ) {
+ Icon(
+ painter = painterResource(iconsR.drawable.mozac_ic_cross_20),
+ contentDescription = stringResource(R.string.mozac_cfr_dismiss_button_content_description),
+ modifier = Modifier
+ // Following alignment and padding are intended to visually align the middle
+ // of the "X" button with the top of the text.
+ .align(Alignment.Center)
+ .padding(
+ top = if (indicatorDirection == CFRPopup.IndicatorDirection.UP) 9.dp else 0.dp,
+ )
+ .size(24.dp),
+ tint = Color(dismissButtonColor),
+ )
+ }
+ }
+ }
+}
+
+@Composable
+@Preview(locale = "en", name = "LTR")
+@Preview(locale = "ar", name = "RTL")
+@Preview(uiMode = Configuration.UI_MODE_NIGHT_YES, name = "Dark theme")
+@Preview(uiMode = Configuration.UI_MODE_NIGHT_NO, name = "Light theme")
+private fun CFRPopupAbovePreview() {
+ CFRPopupContent(
+ popupBodyColors = listOf(Color.Cyan.toArgb(), Color.Blue.toArgb()),
+ showDismissButton = true,
+ dismissButtonColor = Color.Black.toArgb(),
+ indicatorDirection = DOWN,
+ indicatorArrowStartOffset = CFRPopup.DEFAULT_INDICATOR_START_OFFSET.dp,
+ onDismiss = { },
+ text = { Text("Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod") },
+ )
+}
+
+@Composable
+@Preview(locale = "en", name = "LTR")
+@Preview(locale = "ar", name = "RTL")
+@Preview(uiMode = Configuration.UI_MODE_NIGHT_YES, name = "Dark theme")
+@Preview(uiMode = Configuration.UI_MODE_NIGHT_NO, name = "Light theme")
+private fun CFRPopupBelowPreview() {
+ CFRPopupContent(
+ popupBodyColors = listOf(Color.Cyan.toArgb(), Color.Blue.toArgb()),
+ showDismissButton = true,
+ dismissButtonColor = Color.Black.toArgb(),
+ indicatorDirection = UP,
+ indicatorArrowStartOffset = CFRPopup.DEFAULT_INDICATOR_START_OFFSET.dp,
+ onDismiss = { },
+ text = { Text("Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod") },
+ )
+}
diff --git a/mobile/android/android-components/components/compose/cfr/src/main/java/mozilla/components/compose/cfr/CFRPopupFullscreenLayout.kt b/mobile/android/android-components/components/compose/cfr/src/main/java/mozilla/components/compose/cfr/CFRPopupFullscreenLayout.kt
new file mode 100644
index 0000000000..2ef47182ab
--- /dev/null
+++ b/mobile/android/android-components/components/compose/cfr/src/main/java/mozilla/components/compose/cfr/CFRPopupFullscreenLayout.kt
@@ -0,0 +1,537 @@
+/* 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 mozilla.components.compose.cfr
+
+import android.annotation.SuppressLint
+import android.content.Context
+import android.graphics.PixelFormat
+import android.view.View
+import android.view.WindowManager
+import androidx.annotation.Px
+import androidx.annotation.VisibleForTesting
+import androidx.compose.material.Text
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.platform.AbstractComposeView
+import androidx.compose.ui.platform.LocalConfiguration
+import androidx.compose.ui.platform.LocalDensity
+import androidx.compose.ui.platform.ViewRootForInspector
+import androidx.compose.ui.unit.Dp
+import androidx.compose.ui.unit.IntOffset
+import androidx.compose.ui.unit.IntRect
+import androidx.compose.ui.unit.IntSize
+import androidx.compose.ui.unit.LayoutDirection
+import androidx.compose.ui.unit.LayoutDirection.Ltr
+import androidx.compose.ui.unit.dp
+import androidx.compose.ui.window.Popup
+import androidx.compose.ui.window.PopupPositionProvider
+import androidx.compose.ui.window.PopupProperties
+import androidx.core.view.ViewCompat
+import androidx.core.view.WindowInsetsCompat
+import androidx.lifecycle.findViewTreeLifecycleOwner
+import androidx.lifecycle.setViewTreeLifecycleOwner
+import androidx.savedstate.findViewTreeSavedStateRegistryOwner
+import androidx.savedstate.setViewTreeSavedStateRegistryOwner
+import kotlinx.coroutines.delay
+import kotlinx.coroutines.launch
+import mozilla.components.compose.cfr.CFRPopup.IndicatorDirection.DOWN
+import mozilla.components.compose.cfr.CFRPopup.IndicatorDirection.UP
+import mozilla.components.compose.cfr.CFRPopup.PopupAlignment.BODY_CENTERED_IN_SCREEN
+import mozilla.components.compose.cfr.CFRPopup.PopupAlignment.BODY_TO_ANCHOR_CENTER
+import mozilla.components.compose.cfr.CFRPopup.PopupAlignment.BODY_TO_ANCHOR_START
+import mozilla.components.compose.cfr.CFRPopup.PopupAlignment.INDICATOR_CENTERED_IN_ANCHOR
+import mozilla.components.compose.cfr.CFRPopupShape.Companion
+import mozilla.components.compose.cfr.helper.DisplayOrientationListener
+import mozilla.components.compose.cfr.helper.ViewDetachedListener
+import mozilla.components.support.ktx.android.util.dpToPx
+import mozilla.components.support.ktx.android.view.toScope
+import kotlin.math.absoluteValue
+import kotlin.math.roundToInt
+
+@VisibleForTesting
+internal const val SHOW_AFTER_SCREEN_ORIENTATION_CHANGE_DELAY = 500L
+
+/**
+ * Value class allowing to easily reason about what an `Int` represents.
+ * This is compiled to the underlying `Int` type so incurs no performance penalty.
+ */
+@JvmInline
+@VisibleForTesting
+internal value class Pixels(val value: Int)
+
+/**
+ * Simple wrapper over the absolute x-coordinates of the popup. Includes any paddings.
+ */
+@VisibleForTesting
+internal data class PopupHorizontalBounds(
+ val startCoord: Pixels,
+ val endCoord: Pixels,
+)
+
+/**
+ * [AbstractComposeView] that can be added or removed dynamically in the current window to display
+ * a [Composable] based popup anywhere on the screen.
+ *
+ * @param anchor [View] that will serve as the anchor of the popup and serve as lifecycle owner
+ * for this popup also.
+ * @param properties [CFRPopupProperties] allowing to customize the popup behavior.
+ * @param onDismiss Callback for when the popup is dismissed indicating also if the dismissal
+ * was explicit - by tapping the "X" button or not.
+ * @param text [Text] already styled and ready to be shown in the popup.
+ * @param action Optional other composable to show just below the popup text.
+ */
+@SuppressLint("ViewConstructor") // Intended to be used only in code, don't need a View constructor
+internal class CFRPopupFullscreenLayout(
+ private val anchor: View,
+ private val properties: CFRPopupProperties,
+ private val onDismiss: (Boolean) -> Unit,
+ private val text: @Composable (() -> Unit),
+ private val action: @Composable (() -> Unit) = {},
+) : AbstractComposeView(anchor.context), ViewRootForInspector {
+ private val windowManager = anchor.context.getSystemService(Context.WINDOW_SERVICE) as WindowManager
+
+ /**
+ * Listener for when the anchor is removed from the screen.
+ * Useful in the following situations:
+ * - lack of purpose - if there is no anchor the context/action to which this popup refers to disappeared
+ * - leak from WindowManager - if removing the app from task manager while the popup is shown.
+ *
+ * Will not inform client about this since the user did not expressly dismissed this popup.
+ */
+ private val anchorDetachedListener = ViewDetachedListener {
+ dismiss()
+ }
+
+ /**
+ * When the screen is rotated the popup may get improperly anchored
+ * because of the async nature of insets and screen rotation.
+ * To avoid any improper anchorage the popups are automatically dismissed.
+ *
+ * Will not inform client about this since the user did not expressly dismissed this popup.
+ *
+ * Since a UX decision has been made here:
+ * [link](https://github.com/mozilla-mobile/fenix/issues/27033#issuecomment-1302363014)
+ * to redisplay any **implicitly** dismissed CFRs, a short delay will be added,
+ * after which the CFR will be shown again.
+ *
+ */
+ @VisibleForTesting
+ internal lateinit var orientationChangeListener: DisplayOrientationListener
+
+ override var shouldCreateCompositionOnAttachedToWindow: Boolean = false
+ private set
+
+ /**
+ * Add a new CFR popup to the current window overlaying everything already displayed.
+ * This popup will be dismissed when the user clicks on the "x" button or based on other user actions
+ * with such behavior set in [CFRPopupProperties].
+ */
+ fun show() {
+ setViewTreeLifecycleOwner(anchor.findViewTreeLifecycleOwner())
+ this.setViewTreeSavedStateRegistryOwner(anchor.findViewTreeSavedStateRegistryOwner())
+ anchor.addOnAttachStateChangeListener(anchorDetachedListener)
+ orientationChangeListener = getDisplayOrientationListener(anchor.context).also {
+ it.start()
+ }
+ windowManager.addView(this, createLayoutParams())
+ }
+
+ @Composable
+ override fun Content() {
+ val anchorLocation = IntArray(2).apply {
+ anchor.getLocationInWindow(this)
+ }
+
+ val anchorXCoordMiddle = Pixels(anchorLocation.first() + anchor.width / 2)
+ val indicatorArrowHeight = Pixels(
+ CFRPopup.DEFAULT_INDICATOR_HEIGHT.dp.toPx(),
+ )
+
+ val popupBounds = computePopupHorizontalBounds(
+ anchorMiddleXCoord = anchorXCoordMiddle,
+ arrowIndicatorWidth = Pixels(Companion.getIndicatorBaseWidthForHeight(indicatorArrowHeight.value)),
+ screenWidth = Pixels(LocalConfiguration.current.screenWidthDp.dp.toPx()),
+ layoutDirection = LocalConfiguration.current.layoutDirection,
+ )
+
+ val indicatorOffset = computeIndicatorArrowStartCoord(
+ anchorMiddleXCoord = anchorXCoordMiddle,
+ popupStartCoord = popupBounds.startCoord,
+ arrowIndicatorWidth = Pixels(
+ Companion.getIndicatorBaseWidthForHeight(indicatorArrowHeight.value),
+ ),
+ )
+
+ Popup(
+ popupPositionProvider = getPopupPositionProvider(
+ anchorLocation = anchorLocation,
+ popupBounds = popupBounds,
+ ),
+ properties = PopupProperties(
+ focusable = true,
+ dismissOnBackPress = properties.dismissOnBackPress,
+ dismissOnClickOutside = properties.dismissOnClickOutside,
+ ),
+ onDismissRequest = {
+ // For when tapping outside the popup.
+ dismiss()
+ onDismiss(false)
+ },
+ ) {
+ CFRPopupContent(
+ popupBodyColors = properties.popupBodyColors,
+ showDismissButton = properties.showDismissButton,
+ dismissButtonColor = properties.dismissButtonColor,
+ indicatorDirection = properties.indicatorDirection,
+ indicatorArrowStartOffset = with(LocalDensity.current) {
+ indicatorOffset.value.toDp()
+ },
+ onDismiss = {
+ // For when tapping the "X" button.
+ dismiss()
+ onDismiss(true)
+ },
+ popupWidth = if (shouldCenterPopup(LocalConfiguration.current.screenWidthDp.dp.toPx())) {
+ (LocalConfiguration.current.screenWidthDp - 2 * CFRPopup.DEFAULT_HORIZONTAL_VIEWPORT_MARGIN_DP).dp
+ } else {
+ properties.popupWidth
+ },
+ text = text,
+ action = action,
+ )
+ }
+ }
+
+ @Composable
+ private fun getPopupPositionProvider(
+ anchorLocation: IntArray,
+ popupBounds: PopupHorizontalBounds,
+ ): PopupPositionProvider {
+ return object : PopupPositionProvider {
+ override fun calculatePosition(
+ anchorBounds: IntRect,
+ windowSize: IntSize,
+ layoutDirection: LayoutDirection,
+ popupContentSize: IntSize,
+ ): IntOffset {
+ // Popup will be anchored such that the indicator arrow will point to the middle of the anchor View
+ // but the popup is allowed some space as start padding in which it can be displayed such that the
+ // indicator arrow is exactly at the top-start/bottom-start corner but slightly translated to end.
+ // Values are in pixels.
+ return IntOffset(
+ when (layoutDirection) {
+ Ltr -> popupBounds.startCoord.value
+ else -> popupBounds.endCoord.value
+ },
+ when (properties.indicatorDirection) {
+ UP -> {
+ when (properties.overlapAnchor) {
+ true -> anchorLocation.last() + anchor.height / 2
+ else -> anchorLocation.last() + anchor.height + properties.popupVerticalOffset.toPx()
+ }
+ }
+ DOWN -> {
+ when (properties.overlapAnchor) {
+ true -> anchorLocation.last() - popupContentSize.height + anchor.height / 2
+ else -> anchorLocation.last() - popupContentSize.height -
+ properties.popupVerticalOffset.toPx()
+ }
+ }
+ },
+ )
+ }
+ }
+ }
+
+ /**
+ * Whether or not the popup body should be centered in the screen, this is only true if the screen does not
+ * allow the popup to be centered at its maximum width.
+ */
+ private fun shouldCenterPopup(
+ screenWidth: Int,
+ ): Boolean {
+ val maximumPopupWidth = properties.popupWidth.toPx() +
+ 2 * CFRPopup.DEFAULT_HORIZONTAL_VIEWPORT_MARGIN_DP.dp.toPx()
+ return properties.popupAlignment == BODY_CENTERED_IN_SCREEN && maximumPopupWidth > screenWidth
+ }
+
+ /**
+ * Compute the x-coordinates for the absolute start and end position of the popup, including any padding.
+ * This assumes anchoring is indicated with an arrow to the horizontal middle of the anchor with the popup's
+ * body potentially extending to the `start` of the arrow indicator.
+ *
+ * @param anchorMiddleXCoord x-coordinate for the middle of the anchor.
+ * @param arrowIndicatorWidth x-distance the arrow indicator occupies.
+ * @param screenWidth available width in which the popup will be shown.
+ * @param layoutDirection the layout direction of the anchor layout.
+ */
+ @VisibleForTesting
+ @Suppress("LongMethod")
+ internal fun computePopupHorizontalBounds(
+ anchorMiddleXCoord: Pixels,
+ arrowIndicatorWidth: Pixels,
+ screenWidth: Pixels,
+ layoutDirection: Int,
+ ): PopupHorizontalBounds {
+ val arrowIndicatorHalfWidth = arrowIndicatorWidth.value / 2
+
+ return if (layoutDirection == View.LAYOUT_DIRECTION_LTR) {
+ computeHorizontalBoundsLTR(
+ anchorStart = Pixels(anchorMiddleXCoord.value - arrowIndicatorHalfWidth),
+ screenWidth = screenWidth,
+ )
+ } else {
+ computeHorizontalBoundsRTL(
+ anchorStart = Pixels(anchorMiddleXCoord.value + arrowIndicatorHalfWidth),
+ screenWidth = screenWidth,
+ )
+ }
+ }
+
+ private fun computeHorizontalBoundsLTR(
+ anchorStart: Pixels,
+ screenWidth: Pixels,
+ ): PopupHorizontalBounds {
+ val popupPadding = Pixels(CFRPopup.DEFAULT_EXTRA_HORIZONTAL_PADDING.dp.toPx())
+ val leftInsets = Pixels(getLeftInsets())
+ val popupWidth = Pixels(properties.popupWidth.toPx())
+ val viewportMargin =
+ CFRPopup.DEFAULT_HORIZONTAL_VIEWPORT_MARGIN_DP.dpToPx(anchor.resources.displayMetrics)
+ var startCoord = when (properties.popupAlignment) {
+ BODY_TO_ANCHOR_START -> {
+ Pixels(anchor.x.roundToInt() + leftInsets.value)
+ }
+
+ BODY_TO_ANCHOR_CENTER -> {
+ Pixels(
+ anchor.x.roundToInt()
+ .plus((anchor.width - popupWidth.value) / 2)
+ .plus(leftInsets.value),
+ )
+ }
+
+ INDICATOR_CENTERED_IN_ANCHOR,
+ BODY_CENTERED_IN_SCREEN,
+ -> {
+ if (shouldCenterPopup(screenWidth.value)) {
+ Pixels(viewportMargin + leftInsets.value)
+ } else {
+ Pixels(
+ (anchorStart.value)
+ .minus(properties.indicatorArrowStartOffset.toPx())
+ .coerceAtLeast(leftInsets.value),
+ )
+ }
+ }
+ }
+
+ val endCoord = when (properties.popupAlignment) {
+ BODY_CENTERED_IN_SCREEN,
+ INDICATOR_CENTERED_IN_ANCHOR,
+ -> {
+ if (shouldCenterPopup(screenWidth.value)) {
+ Pixels(screenWidth.value - viewportMargin)
+ } else {
+ var maybeEndCoord = Pixels(
+ startCoord.value
+ .plus(popupWidth.value)
+ .plus(popupPadding.value),
+ )
+ // Handle the scenario in which the popup would get pass the end of the screen.
+ // Allow it to only be shown between [0, screenWidth] and if these bounds are surpassed
+ // translate it horizontally to the start to show as much of it as possible.
+ val endCoordOverflow = maybeEndCoord.value - screenWidth.value
+ if (endCoordOverflow > 0) {
+ startCoord = Pixels(
+ startCoord.value
+ .minus(endCoordOverflow)
+ .coerceAtLeast(leftInsets.value),
+ )
+ maybeEndCoord =
+ Pixels(maybeEndCoord.value.coerceAtMost(screenWidth.value + leftInsets.value))
+ }
+ maybeEndCoord
+ }
+ }
+
+ else -> {
+ Pixels(
+ startCoord.value
+ .plus(popupWidth.value)
+ .plus(popupPadding.value)
+ .coerceAtMost(screenWidth.value + leftInsets.value),
+ )
+ }
+ }
+
+ return PopupHorizontalBounds(
+ startCoord = startCoord,
+ endCoord = endCoord,
+ )
+ }
+
+ private fun computeHorizontalBoundsRTL(
+ anchorStart: Pixels,
+ screenWidth: Pixels,
+ ): PopupHorizontalBounds {
+ val popupPadding = Pixels(CFRPopup.DEFAULT_EXTRA_HORIZONTAL_PADDING.dp.toPx())
+ val leftInsets = Pixels(getLeftInsets())
+ val popupWidth = Pixels(properties.popupWidth.toPx())
+ val viewportMargin =
+ CFRPopup.DEFAULT_HORIZONTAL_VIEWPORT_MARGIN_DP.dpToPx(anchor.resources.displayMetrics)
+ var startCoord = when (properties.popupAlignment) {
+ BODY_TO_ANCHOR_START -> {
+ Pixels(anchor.x.roundToInt() + anchor.width + leftInsets.value)
+ }
+ BODY_TO_ANCHOR_CENTER -> {
+ val anchorEndCoord = anchor.x.roundToInt() + anchor.width
+ Pixels(
+ anchorEndCoord
+ .minus((anchor.width - popupWidth.value) / 2)
+ .plus(leftInsets.value),
+ )
+ }
+
+ BODY_CENTERED_IN_SCREEN,
+ INDICATOR_CENTERED_IN_ANCHOR,
+ -> {
+ if (shouldCenterPopup(screenWidth.value)) {
+ Pixels(screenWidth.value - viewportMargin)
+ } else {
+ Pixels(
+ // Push the popup as far to the start (in RTL) as possible.
+ anchorStart.value
+ .plus(properties.indicatorArrowStartOffset.toPx())
+ .coerceAtMost(screenWidth.value + leftInsets.value),
+ )
+ }
+ }
+ }
+
+ val endCoord = when (properties.popupAlignment) {
+ BODY_CENTERED_IN_SCREEN,
+ INDICATOR_CENTERED_IN_ANCHOR,
+ -> {
+ if (shouldCenterPopup(screenWidth.value)) {
+ Pixels(viewportMargin - leftInsets.value)
+ } else {
+ var maybeEndCoord = Pixels(
+ startCoord.value
+ .minus(popupWidth.value)
+ .minus(popupPadding.value),
+ )
+ val endCoordOverflow = leftInsets.value - maybeEndCoord.value
+ // Handle the scenario in which the popup would get pass the end of the screen (in RTL)
+ // Allow it to only be shown between [0, screenWidth] and if these bounds are surpassed
+ // translate it horizontally to the start to show as much of it as possible.
+ if (endCoordOverflow > 0) {
+ startCoord = Pixels(
+ startCoord.value
+ .plus(endCoordOverflow.absoluteValue)
+ .coerceAtMost(screenWidth.value + leftInsets.value),
+ )
+ maybeEndCoord =
+ Pixels(maybeEndCoord.value.coerceAtLeast(leftInsets.value))
+ }
+ maybeEndCoord
+ }
+ }
+
+ else -> {
+ Pixels(
+ startCoord.value
+ .minus(popupWidth.value)
+ .minus(popupPadding.value)
+ .coerceAtLeast(leftInsets.value),
+ )
+ }
+ }
+
+ return PopupHorizontalBounds(startCoord, endCoord)
+ }
+
+ /**
+ * Compute the x-coordinate for where the popup's indicator arrow should start
+ * relative to the available distance between it and the popup's starting x-coordinate.
+ *
+ * @param anchorMiddleXCoord x-coordinate for the middle of the anchor.
+ * @param popupStartCoord x-coordinate for the popup start
+ * @param arrowIndicatorWidth Width of the arrow indicator.
+ */
+ @Composable
+ private fun computeIndicatorArrowStartCoord(
+ anchorMiddleXCoord: Pixels,
+ popupStartCoord: Pixels,
+ arrowIndicatorWidth: Pixels,
+ ): Pixels {
+ return when (properties.popupAlignment) {
+ BODY_TO_ANCHOR_START,
+ BODY_TO_ANCHOR_CENTER,
+ -> Pixels(properties.indicatorArrowStartOffset.toPx())
+ BODY_CENTERED_IN_SCREEN,
+ INDICATOR_CENTERED_IN_ANCHOR,
+ -> {
+ val arrowIndicatorHalfWidth = arrowIndicatorWidth.value / 2
+ if (LocalConfiguration.current.layoutDirection == View.LAYOUT_DIRECTION_LTR) {
+ Pixels(anchorMiddleXCoord.value - arrowIndicatorHalfWidth - popupStartCoord.value)
+ } else {
+ val visiblePopupEndCoord = popupStartCoord.value
+ Pixels(visiblePopupEndCoord - anchorMiddleXCoord.value - arrowIndicatorHalfWidth)
+ }
+ }
+ }
+ }
+
+ /**
+ * Cleanup and remove the current popup from the screen.
+ * Clients are not automatically informed about this. Use a separate call to [onDismiss] if needed.
+ */
+ internal fun dismiss() {
+ anchor.removeOnAttachStateChangeListener(anchorDetachedListener)
+ orientationChangeListener.stop()
+ disposeComposition()
+ setViewTreeLifecycleOwner(null)
+ this.setViewTreeSavedStateRegistryOwner(null)
+ windowManager.removeViewImmediate(this)
+ }
+
+ /**
+ * Create fullscreen translucent layout params.
+ * This will allow placing the visible popup anywhere on the screen.
+ */
+ @VisibleForTesting
+ internal fun createLayoutParams(): WindowManager.LayoutParams =
+ WindowManager.LayoutParams().apply {
+ type = WindowManager.LayoutParams.TYPE_APPLICATION_PANEL
+ token = anchor.applicationWindowToken
+ width = WindowManager.LayoutParams.MATCH_PARENT
+ height = WindowManager.LayoutParams.MATCH_PARENT
+ format = PixelFormat.TRANSLUCENT
+ flags = WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN or
+ WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED
+ }
+
+ private fun getDisplayOrientationListener(context: Context) = DisplayOrientationListener(context) {
+ dismiss()
+ anchor.toScope().launch {
+ delay(SHOW_AFTER_SCREEN_ORIENTATION_CHANGE_DELAY)
+ show()
+ }
+ }
+
+ /**
+ * Intended to allow querying the insets of the navigation bar.
+ * Value will be `0` except for when the screen is rotated by 90 degrees.
+ */
+ private fun getLeftInsets() = ViewCompat.getRootWindowInsets(anchor)
+ ?.getInsets(WindowInsetsCompat.Type.systemBars())?.left
+ ?: 0.coerceAtLeast(0)
+
+ @Px
+ internal fun Dp.toPx(): Int {
+ return this.value
+ .dpToPx(anchor.resources.displayMetrics)
+ .roundToInt()
+ }
+}
diff --git a/mobile/android/android-components/components/compose/cfr/src/main/java/mozilla/components/compose/cfr/CFRPopupShape.kt b/mobile/android/android-components/components/compose/cfr/src/main/java/mozilla/components/compose/cfr/CFRPopupShape.kt
new file mode 100644
index 0000000000..8606bdcebc
--- /dev/null
+++ b/mobile/android/android-components/components/compose/cfr/src/main/java/mozilla/components/compose/cfr/CFRPopupShape.kt
@@ -0,0 +1,272 @@
+/* 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 mozilla.components.compose.cfr
+
+import android.content.res.Configuration
+import androidx.compose.foundation.background
+import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.layout.height
+import androidx.compose.foundation.layout.width
+import androidx.compose.material.MaterialTheme
+import androidx.compose.material.Text
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.Alignment
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.geometry.Offset
+import androidx.compose.ui.geometry.Size
+import androidx.compose.ui.graphics.Brush
+import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.graphics.Outline
+import androidx.compose.ui.graphics.Path
+import androidx.compose.ui.graphics.Shape
+import androidx.compose.ui.tooling.preview.Preview
+import androidx.compose.ui.unit.Density
+import androidx.compose.ui.unit.Dp
+import androidx.compose.ui.unit.LayoutDirection
+import androidx.compose.ui.unit.dp
+import mozilla.components.compose.cfr.CFRPopup.IndicatorDirection.DOWN
+import mozilla.components.compose.cfr.CFRPopup.IndicatorDirection.UP
+import kotlin.math.roundToInt
+
+/**
+ * How wide the base of the indicator should be in relation with the indicator's height.
+ */
+private const val INDICATOR_BASE_TO_HEIGHT_RATIO = 2f
+
+/**
+ * A [Shape] describing a popup with an indicator triangle shown above or below the popup.
+ *
+ * @param indicatorDirection The direction the indicator arrow is pointing to.
+ * @param indicatorArrowStartOffset Distance between the popup start and the indicator arrow start
+ * @param indicatorArrowHeight Height of the indicator triangle. This influences the base length.
+ * @param cornerRadius The radius of the popup's corners.
+ * If [indicatorArrowStartOffset] is `0` then the top-start corner will not be rounded.
+ */
+class CFRPopupShape(
+ private val indicatorDirection: CFRPopup.IndicatorDirection,
+ private val indicatorArrowStartOffset: Dp,
+ private val indicatorArrowHeight: Dp,
+ private val cornerRadius: Dp,
+) : Shape {
+ @Suppress("LongMethod")
+ override fun createOutline(
+ size: Size,
+ layoutDirection: LayoutDirection,
+ density: Density,
+ ): Outline {
+ val indicatorArrowStartOffsetPx = indicatorArrowStartOffset.value * density.density
+ val indicatorArrowHeightPx = indicatorArrowHeight.value * density.density
+ val indicatorArrowBasePx =
+ getIndicatorBaseWidthForHeight((indicatorArrowHeight.value * density.density).roundToInt())
+ val cornerRadiusPx = cornerRadius.value * density.density
+ val indicatorCornerRadiusPx = cornerRadiusPx.coerceAtMost(indicatorArrowStartOffsetPx)
+
+ // All outlines are drawn in a LTR space but with accounting for the LTR direction.
+ return when (indicatorDirection) {
+ CFRPopup.IndicatorDirection.UP -> {
+ Outline.Generic(
+ path = Path().apply {
+ reset()
+
+ lineTo(0f, size.height - cornerRadiusPx)
+ quadraticBezierTo(
+ 0f,
+ size.height,
+ cornerRadiusPx,
+ size.height,
+ )
+
+ lineTo(size.width - cornerRadiusPx, size.height)
+ quadraticBezierTo(
+ size.width,
+ size.height,
+ size.width,
+ size.height - cornerRadiusPx,
+ )
+
+ if (layoutDirection == LayoutDirection.Ltr) {
+ lineTo(size.width, cornerRadiusPx + indicatorArrowHeightPx)
+ quadraticBezierTo(
+ size.width,
+ indicatorArrowHeightPx,
+ size.width - cornerRadiusPx,
+ indicatorArrowHeightPx,
+ )
+
+ lineTo(indicatorArrowStartOffsetPx + indicatorArrowBasePx, indicatorArrowHeightPx)
+ lineTo(indicatorArrowStartOffsetPx + indicatorArrowBasePx / 2, 0f)
+ lineTo(indicatorArrowStartOffsetPx, indicatorArrowHeightPx)
+
+ lineTo(indicatorCornerRadiusPx, indicatorArrowHeightPx)
+ quadraticBezierTo(
+ 0f,
+ indicatorArrowHeightPx,
+ 0f,
+ indicatorArrowHeightPx + indicatorCornerRadiusPx,
+ )
+ } else {
+ lineTo(size.width, indicatorCornerRadiusPx + indicatorArrowHeightPx)
+ quadraticBezierTo(
+ size.width,
+ indicatorArrowHeightPx,
+ size.width - indicatorCornerRadiusPx,
+ indicatorArrowHeightPx,
+ )
+
+ val indicatorEnd = size.width - indicatorArrowStartOffsetPx
+ lineTo(indicatorEnd, indicatorArrowHeightPx)
+ lineTo(indicatorEnd - indicatorArrowBasePx / 2, 0f)
+ lineTo(indicatorEnd - indicatorArrowBasePx, indicatorArrowHeightPx)
+
+ lineTo(cornerRadiusPx, indicatorArrowHeightPx)
+ quadraticBezierTo(
+ 0f,
+ indicatorArrowHeightPx,
+ 0f,
+ indicatorArrowHeightPx + cornerRadiusPx,
+ )
+ }
+
+ close()
+ },
+ )
+ }
+ CFRPopup.IndicatorDirection.DOWN -> {
+ val messageBodyHeightPx = size.height - indicatorArrowHeightPx
+
+ Outline.Generic(
+ path = Path().apply {
+ reset()
+
+ if (layoutDirection == LayoutDirection.Ltr) {
+ lineTo(0f, messageBodyHeightPx - indicatorCornerRadiusPx)
+ quadraticBezierTo(
+ 0f,
+ size.height - indicatorArrowHeightPx,
+ indicatorCornerRadiusPx,
+ size.height - indicatorArrowHeightPx,
+ )
+
+ lineTo(indicatorArrowStartOffsetPx, messageBodyHeightPx)
+ lineTo(indicatorArrowStartOffsetPx + indicatorArrowBasePx / 2, size.height)
+ lineTo(indicatorArrowStartOffsetPx + indicatorArrowBasePx, messageBodyHeightPx)
+
+ lineTo(size.width - cornerRadiusPx, messageBodyHeightPx)
+ quadraticBezierTo(
+ size.width,
+ messageBodyHeightPx,
+ size.width,
+ messageBodyHeightPx - cornerRadiusPx,
+ )
+ } else {
+ lineTo(0f, messageBodyHeightPx - cornerRadiusPx)
+ quadraticBezierTo(
+ 0f,
+ messageBodyHeightPx,
+ cornerRadiusPx,
+ messageBodyHeightPx,
+ )
+
+ val indicatorStartPx = size.width - indicatorArrowStartOffsetPx - indicatorArrowBasePx
+ lineTo(indicatorStartPx, messageBodyHeightPx)
+ lineTo(indicatorStartPx + indicatorArrowBasePx / 2, size.height)
+ lineTo(indicatorStartPx + indicatorArrowBasePx, messageBodyHeightPx)
+
+ lineTo(size.width - indicatorCornerRadiusPx, messageBodyHeightPx)
+ quadraticBezierTo(
+ size.width,
+ messageBodyHeightPx,
+ size.width,
+ messageBodyHeightPx - indicatorCornerRadiusPx,
+ )
+ }
+
+ lineTo(size.width, cornerRadiusPx)
+ quadraticBezierTo(
+ size.width,
+ 0f,
+ size.width - cornerRadiusPx,
+ 0f,
+ )
+
+ lineTo(cornerRadiusPx, 0f)
+ quadraticBezierTo(
+ 0f,
+ 0f,
+ 0f,
+ cornerRadiusPx,
+ )
+
+ close()
+ },
+ )
+ }
+ }
+ }
+
+ companion object {
+ /**
+ * This [Shape]'s arrow indicator will have an automatic width depending on the set height.
+ * This method allows knowing what the base width will be before instantiating the class.
+ */
+ fun getIndicatorBaseWidthForHeight(height: Int): Int {
+ return (height * INDICATOR_BASE_TO_HEIGHT_RATIO).roundToInt()
+ }
+ }
+}
+
+@Composable
+@Preview(locale = "en", name = "LTR")
+@Preview(locale = "ar", name = "RTL")
+@Preview(uiMode = Configuration.UI_MODE_NIGHT_YES, name = "Dark theme")
+@Preview(uiMode = Configuration.UI_MODE_NIGHT_NO, name = "Light theme")
+private fun CFRPopupBelowShapePreview() {
+ Box(
+ modifier = Modifier
+ .height(100.dp)
+ .width(200.dp)
+ .background(
+ shape = CFRPopupShape(UP, 10.dp, 10.dp, 10.dp),
+ brush = Brush.linearGradient(
+ colors = listOf(Color.Cyan, Color.Blue),
+ end = Offset(0f, Float.POSITIVE_INFINITY),
+ start = Offset(Float.POSITIVE_INFINITY, 0f),
+ ),
+ ),
+ contentAlignment = Alignment.Center,
+ ) {
+ Text(
+ text = "This is just a test",
+ color = MaterialTheme.colors.onPrimary,
+ )
+ }
+}
+
+@Composable
+@Preview(locale = "en", name = "LTR")
+@Preview(locale = "ar", name = "RTL")
+@Preview(uiMode = Configuration.UI_MODE_NIGHT_YES, name = "Dark theme")
+@Preview(uiMode = Configuration.UI_MODE_NIGHT_NO, name = "Light theme")
+private fun CFRPopupAboveShapePreview() {
+ Box(
+ modifier = Modifier
+ .height(100.dp)
+ .width(200.dp)
+ .background(
+ shape = CFRPopupShape(DOWN, 10.dp, 10.dp, 10.dp),
+ brush = Brush.linearGradient(
+ colors = listOf(Color.Cyan, Color.Blue),
+ end = Offset(0f, Float.POSITIVE_INFINITY),
+ start = Offset(Float.POSITIVE_INFINITY, 0f),
+ ),
+ ),
+ contentAlignment = Alignment.Center,
+ ) {
+ Text(
+ text = "This is just a test",
+ color = MaterialTheme.colors.onPrimary,
+ )
+ }
+}
diff --git a/mobile/android/android-components/components/compose/cfr/src/main/java/mozilla/components/compose/cfr/helper/DisplayOrientationListener.kt b/mobile/android/android-components/components/compose/cfr/src/main/java/mozilla/components/compose/cfr/helper/DisplayOrientationListener.kt
new file mode 100644
index 0000000000..4a44ac6127
--- /dev/null
+++ b/mobile/android/android-components/components/compose/cfr/src/main/java/mozilla/components/compose/cfr/helper/DisplayOrientationListener.kt
@@ -0,0 +1,65 @@
+/* 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 mozilla.components.compose.cfr.helper
+
+import android.content.Context
+import android.hardware.display.DisplayManager
+import android.hardware.display.DisplayManager.DisplayListener
+import android.os.Build
+import androidx.annotation.VisibleForTesting
+
+/**
+ * Inform when the rotation of the screen changes.
+ * Since this is using a [DisplayManager] listener it's important to call [start] and [stop]
+ * at the appropriate moments to register and unregister said listener.
+ *
+ * @param context Android context needed to interact with the [DisplayManager]
+ * @param onDisplayRotationChanged Listener for when the display rotation changes.
+ * This will be called when the display changes to any of the four main orientations:
+ * [PORTRAIT, LANDSCAPE, REVERSE_PORTRAIT, REVERSE_LANDSCAPE].
+ * No updates will be triggered if the "Auto-rotate" functionality is disabled for the device.
+ */
+internal class DisplayOrientationListener(
+ private val context: Context,
+ val onDisplayRotationChanged: () -> Unit,
+) : DisplayListener {
+ private val displayManager = context.getSystemService(Context.DISPLAY_SERVICE) as DisplayManager
+
+ @VisibleForTesting
+ internal var currentOrientation = getCurrentOrientation()
+
+ /**
+ * Start listening for display orientation changes.
+ * It's important to also call [stop] when done listening to prevent leaking the listener.
+ */
+ fun start() {
+ displayManager.registerDisplayListener(this, null)
+ }
+
+ /**
+ * Stop listening for display orientation changes and cleanup the current [DisplayManager] listener.
+ */
+ fun stop() {
+ displayManager.unregisterDisplayListener(this)
+ }
+
+ override fun onDisplayAdded(displayId: Int) = Unit
+
+ override fun onDisplayRemoved(displayId: Int) = Unit
+
+ override fun onDisplayChanged(displayId: Int) {
+ val newOrientation = getCurrentOrientation(displayId)
+
+ if (newOrientation != this.currentOrientation) {
+ this.currentOrientation = newOrientation
+ onDisplayRotationChanged()
+ }
+ }
+
+ private fun getCurrentOrientation(displayId: Int = 0): Int = when (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
+ true -> context.resources.configuration.orientation
+ false -> displayManager.getDisplay(displayId)?.rotation ?: currentOrientation
+ }
+}
diff --git a/mobile/android/android-components/components/compose/cfr/src/main/java/mozilla/components/compose/cfr/helper/ViewDetachedListener.kt b/mobile/android/android-components/components/compose/cfr/src/main/java/mozilla/components/compose/cfr/helper/ViewDetachedListener.kt
new file mode 100644
index 0000000000..da6782604a
--- /dev/null
+++ b/mobile/android/android-components/components/compose/cfr/src/main/java/mozilla/components/compose/cfr/helper/ViewDetachedListener.kt
@@ -0,0 +1,19 @@
+/* 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 mozilla.components.compose.cfr.helper
+
+import android.view.View
+
+/**
+ * Simpler [View.OnAttachStateChangeListener] only informing about
+ * [View.OnAttachStateChangeListener.onViewDetachedFromWindow].
+ */
+internal class ViewDetachedListener(val onDismiss: () -> Unit) : View.OnAttachStateChangeListener {
+ override fun onViewAttachedToWindow(v: View) = Unit
+
+ override fun onViewDetachedFromWindow(v: View) {
+ onDismiss()
+ }
+}
diff --git a/mobile/android/android-components/components/compose/cfr/src/main/res/values-am/strings.xml b/mobile/android/android-components/components/compose/cfr/src/main/res/values-am/strings.xml
new file mode 100644
index 0000000000..c97e99ec94
--- /dev/null
+++ b/mobile/android/android-components/components/compose/cfr/src/main/res/values-am/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description (not visible, for screen readers etc.): Description for the close button of a Contextual Feature Recommendation Popup. -->
+ <string name="mozac_cfr_dismiss_button_content_description">አሰናብት</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/cfr/src/main/res/values-ast/strings.xml b/mobile/android/android-components/components/compose/cfr/src/main/res/values-ast/strings.xml
new file mode 100644
index 0000000000..0676ead800
--- /dev/null
+++ b/mobile/android/android-components/components/compose/cfr/src/main/res/values-ast/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description (not visible, for screen readers etc.): Description for the close button of a Contextual Feature Recommendation Popup. -->
+ <string name="mozac_cfr_dismiss_button_content_description">Escartar</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/cfr/src/main/res/values-azb/strings.xml b/mobile/android/android-components/components/compose/cfr/src/main/res/values-azb/strings.xml
new file mode 100644
index 0000000000..77a2c88eb2
--- /dev/null
+++ b/mobile/android/android-components/components/compose/cfr/src/main/res/values-azb/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description (not visible, for screen readers etc.): Description for the close button of a Contextual Feature Recommendation Popup. -->
+ <string name="mozac_cfr_dismiss_button_content_description">باغلا</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/cfr/src/main/res/values-be/strings.xml b/mobile/android/android-components/components/compose/cfr/src/main/res/values-be/strings.xml
new file mode 100644
index 0000000000..19d6f18471
--- /dev/null
+++ b/mobile/android/android-components/components/compose/cfr/src/main/res/values-be/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description (not visible, for screen readers etc.): Description for the close button of a Contextual Feature Recommendation Popup. -->
+ <string name="mozac_cfr_dismiss_button_content_description">Адхіліць</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/cfr/src/main/res/values-bg/strings.xml b/mobile/android/android-components/components/compose/cfr/src/main/res/values-bg/strings.xml
new file mode 100644
index 0000000000..12463e5dda
--- /dev/null
+++ b/mobile/android/android-components/components/compose/cfr/src/main/res/values-bg/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description (not visible, for screen readers etc.): Description for the close button of a Contextual Feature Recommendation Popup. -->
+ <string name="mozac_cfr_dismiss_button_content_description">Прекратяване</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/cfr/src/main/res/values-br/strings.xml b/mobile/android/android-components/components/compose/cfr/src/main/res/values-br/strings.xml
new file mode 100644
index 0000000000..6b257c25c7
--- /dev/null
+++ b/mobile/android/android-components/components/compose/cfr/src/main/res/values-br/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description (not visible, for screen readers etc.): Description for the close button of a Contextual Feature Recommendation Popup. -->
+ <string name="mozac_cfr_dismiss_button_content_description">Argas</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/cfr/src/main/res/values-bs/strings.xml b/mobile/android/android-components/components/compose/cfr/src/main/res/values-bs/strings.xml
new file mode 100644
index 0000000000..d8b54cb34b
--- /dev/null
+++ b/mobile/android/android-components/components/compose/cfr/src/main/res/values-bs/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description (not visible, for screen readers etc.): Description for the close button of a Contextual Feature Recommendation Popup. -->
+ <string name="mozac_cfr_dismiss_button_content_description">Odbaci</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/cfr/src/main/res/values-ca/strings.xml b/mobile/android/android-components/components/compose/cfr/src/main/res/values-ca/strings.xml
new file mode 100644
index 0000000000..c5e24af615
--- /dev/null
+++ b/mobile/android/android-components/components/compose/cfr/src/main/res/values-ca/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description (not visible, for screen readers etc.): Description for the close button of a Contextual Feature Recommendation Popup. -->
+ <string name="mozac_cfr_dismiss_button_content_description">Descarta</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/cfr/src/main/res/values-cak/strings.xml b/mobile/android/android-components/components/compose/cfr/src/main/res/values-cak/strings.xml
new file mode 100644
index 0000000000..3152b578ba
--- /dev/null
+++ b/mobile/android/android-components/components/compose/cfr/src/main/res/values-cak/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description (not visible, for screen readers etc.): Description for the close button of a Contextual Feature Recommendation Popup. -->
+ <string name="mozac_cfr_dismiss_button_content_description">Tichup ruwäch</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/cfr/src/main/res/values-ckb/strings.xml b/mobile/android/android-components/components/compose/cfr/src/main/res/values-ckb/strings.xml
new file mode 100644
index 0000000000..437dd527f5
--- /dev/null
+++ b/mobile/android/android-components/components/compose/cfr/src/main/res/values-ckb/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description (not visible, for screen readers etc.): Description for the close button of a Contextual Feature Recommendation Popup. -->
+ <string name="mozac_cfr_dismiss_button_content_description">پشتگوێخستن</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/cfr/src/main/res/values-co/strings.xml b/mobile/android/android-components/components/compose/cfr/src/main/res/values-co/strings.xml
new file mode 100644
index 0000000000..6ac10d7f41
--- /dev/null
+++ b/mobile/android/android-components/components/compose/cfr/src/main/res/values-co/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description (not visible, for screen readers etc.): Description for the close button of a Contextual Feature Recommendation Popup. -->
+ <string name="mozac_cfr_dismiss_button_content_description">Ricusà</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/cfr/src/main/res/values-cs/strings.xml b/mobile/android/android-components/components/compose/cfr/src/main/res/values-cs/strings.xml
new file mode 100644
index 0000000000..7931a04581
--- /dev/null
+++ b/mobile/android/android-components/components/compose/cfr/src/main/res/values-cs/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description (not visible, for screen readers etc.): Description for the close button of a Contextual Feature Recommendation Popup. -->
+ <string name="mozac_cfr_dismiss_button_content_description">Zavřít</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/cfr/src/main/res/values-cy/strings.xml b/mobile/android/android-components/components/compose/cfr/src/main/res/values-cy/strings.xml
new file mode 100644
index 0000000000..cc82da5e42
--- /dev/null
+++ b/mobile/android/android-components/components/compose/cfr/src/main/res/values-cy/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description (not visible, for screen readers etc.): Description for the close button of a Contextual Feature Recommendation Popup. -->
+ <string name="mozac_cfr_dismiss_button_content_description">Cau</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/cfr/src/main/res/values-da/strings.xml b/mobile/android/android-components/components/compose/cfr/src/main/res/values-da/strings.xml
new file mode 100644
index 0000000000..d03d570df3
--- /dev/null
+++ b/mobile/android/android-components/components/compose/cfr/src/main/res/values-da/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description (not visible, for screen readers etc.): Description for the close button of a Contextual Feature Recommendation Popup. -->
+ <string name="mozac_cfr_dismiss_button_content_description">Afvis</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/cfr/src/main/res/values-de/strings.xml b/mobile/android/android-components/components/compose/cfr/src/main/res/values-de/strings.xml
new file mode 100644
index 0000000000..fc26b597f7
--- /dev/null
+++ b/mobile/android/android-components/components/compose/cfr/src/main/res/values-de/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description (not visible, for screen readers etc.): Description for the close button of a Contextual Feature Recommendation Popup. -->
+ <string name="mozac_cfr_dismiss_button_content_description">Schließen</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/cfr/src/main/res/values-dsb/strings.xml b/mobile/android/android-components/components/compose/cfr/src/main/res/values-dsb/strings.xml
new file mode 100644
index 0000000000..2c84c274e2
--- /dev/null
+++ b/mobile/android/android-components/components/compose/cfr/src/main/res/values-dsb/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description (not visible, for screen readers etc.): Description for the close button of a Contextual Feature Recommendation Popup. -->
+ <string name="mozac_cfr_dismiss_button_content_description">Zachyśiś</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/cfr/src/main/res/values-el/strings.xml b/mobile/android/android-components/components/compose/cfr/src/main/res/values-el/strings.xml
new file mode 100644
index 0000000000..5a3bba4948
--- /dev/null
+++ b/mobile/android/android-components/components/compose/cfr/src/main/res/values-el/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description (not visible, for screen readers etc.): Description for the close button of a Contextual Feature Recommendation Popup. -->
+ <string name="mozac_cfr_dismiss_button_content_description">Απόρριψη</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/cfr/src/main/res/values-en-rCA/strings.xml b/mobile/android/android-components/components/compose/cfr/src/main/res/values-en-rCA/strings.xml
new file mode 100644
index 0000000000..d3515657b4
--- /dev/null
+++ b/mobile/android/android-components/components/compose/cfr/src/main/res/values-en-rCA/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description (not visible, for screen readers etc.): Description for the close button of a Contextual Feature Recommendation Popup. -->
+ <string name="mozac_cfr_dismiss_button_content_description">Dismiss</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/cfr/src/main/res/values-en-rGB/strings.xml b/mobile/android/android-components/components/compose/cfr/src/main/res/values-en-rGB/strings.xml
new file mode 100644
index 0000000000..d3515657b4
--- /dev/null
+++ b/mobile/android/android-components/components/compose/cfr/src/main/res/values-en-rGB/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description (not visible, for screen readers etc.): Description for the close button of a Contextual Feature Recommendation Popup. -->
+ <string name="mozac_cfr_dismiss_button_content_description">Dismiss</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/cfr/src/main/res/values-eo/strings.xml b/mobile/android/android-components/components/compose/cfr/src/main/res/values-eo/strings.xml
new file mode 100644
index 0000000000..af51005a75
--- /dev/null
+++ b/mobile/android/android-components/components/compose/cfr/src/main/res/values-eo/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description (not visible, for screen readers etc.): Description for the close button of a Contextual Feature Recommendation Popup. -->
+ <string name="mozac_cfr_dismiss_button_content_description">Ignori</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/cfr/src/main/res/values-es-rAR/strings.xml b/mobile/android/android-components/components/compose/cfr/src/main/res/values-es-rAR/strings.xml
new file mode 100644
index 0000000000..f14c6e05a9
--- /dev/null
+++ b/mobile/android/android-components/components/compose/cfr/src/main/res/values-es-rAR/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description (not visible, for screen readers etc.): Description for the close button of a Contextual Feature Recommendation Popup. -->
+ <string name="mozac_cfr_dismiss_button_content_description">Descartar</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/cfr/src/main/res/values-es-rCL/strings.xml b/mobile/android/android-components/components/compose/cfr/src/main/res/values-es-rCL/strings.xml
new file mode 100644
index 0000000000..e4a97a05b3
--- /dev/null
+++ b/mobile/android/android-components/components/compose/cfr/src/main/res/values-es-rCL/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description (not visible, for screen readers etc.): Description for the close button of a Contextual Feature Recommendation Popup. -->
+ <string name="mozac_cfr_dismiss_button_content_description">Ocultar</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/cfr/src/main/res/values-es-rES/strings.xml b/mobile/android/android-components/components/compose/cfr/src/main/res/values-es-rES/strings.xml
new file mode 100644
index 0000000000..f14c6e05a9
--- /dev/null
+++ b/mobile/android/android-components/components/compose/cfr/src/main/res/values-es-rES/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description (not visible, for screen readers etc.): Description for the close button of a Contextual Feature Recommendation Popup. -->
+ <string name="mozac_cfr_dismiss_button_content_description">Descartar</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/cfr/src/main/res/values-es-rMX/strings.xml b/mobile/android/android-components/components/compose/cfr/src/main/res/values-es-rMX/strings.xml
new file mode 100644
index 0000000000..f14c6e05a9
--- /dev/null
+++ b/mobile/android/android-components/components/compose/cfr/src/main/res/values-es-rMX/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description (not visible, for screen readers etc.): Description for the close button of a Contextual Feature Recommendation Popup. -->
+ <string name="mozac_cfr_dismiss_button_content_description">Descartar</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/cfr/src/main/res/values-es/strings.xml b/mobile/android/android-components/components/compose/cfr/src/main/res/values-es/strings.xml
new file mode 100644
index 0000000000..f14c6e05a9
--- /dev/null
+++ b/mobile/android/android-components/components/compose/cfr/src/main/res/values-es/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description (not visible, for screen readers etc.): Description for the close button of a Contextual Feature Recommendation Popup. -->
+ <string name="mozac_cfr_dismiss_button_content_description">Descartar</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/cfr/src/main/res/values-et/strings.xml b/mobile/android/android-components/components/compose/cfr/src/main/res/values-et/strings.xml
new file mode 100644
index 0000000000..e6ef08c0b2
--- /dev/null
+++ b/mobile/android/android-components/components/compose/cfr/src/main/res/values-et/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description (not visible, for screen readers etc.): Description for the close button of a Contextual Feature Recommendation Popup. -->
+ <string name="mozac_cfr_dismiss_button_content_description">Peida</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/cfr/src/main/res/values-eu/strings.xml b/mobile/android/android-components/components/compose/cfr/src/main/res/values-eu/strings.xml
new file mode 100644
index 0000000000..6002549de1
--- /dev/null
+++ b/mobile/android/android-components/components/compose/cfr/src/main/res/values-eu/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description (not visible, for screen readers etc.): Description for the close button of a Contextual Feature Recommendation Popup. -->
+ <string name="mozac_cfr_dismiss_button_content_description">Baztertu</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/cfr/src/main/res/values-fa/strings.xml b/mobile/android/android-components/components/compose/cfr/src/main/res/values-fa/strings.xml
new file mode 100644
index 0000000000..7d50c5d847
--- /dev/null
+++ b/mobile/android/android-components/components/compose/cfr/src/main/res/values-fa/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description (not visible, for screen readers etc.): Description for the close button of a Contextual Feature Recommendation Popup. -->
+ <string name="mozac_cfr_dismiss_button_content_description">رد کردن</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/cfr/src/main/res/values-fi/strings.xml b/mobile/android/android-components/components/compose/cfr/src/main/res/values-fi/strings.xml
new file mode 100644
index 0000000000..dae33bc1fd
--- /dev/null
+++ b/mobile/android/android-components/components/compose/cfr/src/main/res/values-fi/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description (not visible, for screen readers etc.): Description for the close button of a Contextual Feature Recommendation Popup. -->
+ <string name="mozac_cfr_dismiss_button_content_description">Hylkää</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/cfr/src/main/res/values-fr/strings.xml b/mobile/android/android-components/components/compose/cfr/src/main/res/values-fr/strings.xml
new file mode 100644
index 0000000000..68a4823ca3
--- /dev/null
+++ b/mobile/android/android-components/components/compose/cfr/src/main/res/values-fr/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description (not visible, for screen readers etc.): Description for the close button of a Contextual Feature Recommendation Popup. -->
+ <string name="mozac_cfr_dismiss_button_content_description">Fermer</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/cfr/src/main/res/values-fur/strings.xml b/mobile/android/android-components/components/compose/cfr/src/main/res/values-fur/strings.xml
new file mode 100644
index 0000000000..4a414e4c5b
--- /dev/null
+++ b/mobile/android/android-components/components/compose/cfr/src/main/res/values-fur/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description (not visible, for screen readers etc.): Description for the close button of a Contextual Feature Recommendation Popup. -->
+ <string name="mozac_cfr_dismiss_button_content_description">Siere</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/cfr/src/main/res/values-fy-rNL/strings.xml b/mobile/android/android-components/components/compose/cfr/src/main/res/values-fy-rNL/strings.xml
new file mode 100644
index 0000000000..105ba034c4
--- /dev/null
+++ b/mobile/android/android-components/components/compose/cfr/src/main/res/values-fy-rNL/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description (not visible, for screen readers etc.): Description for the close button of a Contextual Feature Recommendation Popup. -->
+ <string name="mozac_cfr_dismiss_button_content_description">Slute</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/cfr/src/main/res/values-gd/strings.xml b/mobile/android/android-components/components/compose/cfr/src/main/res/values-gd/strings.xml
new file mode 100644
index 0000000000..13c3244a40
--- /dev/null
+++ b/mobile/android/android-components/components/compose/cfr/src/main/res/values-gd/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description (not visible, for screen readers etc.): Description for the close button of a Contextual Feature Recommendation Popup. -->
+ <string name="mozac_cfr_dismiss_button_content_description">Leig seachad</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/cfr/src/main/res/values-gl/strings.xml b/mobile/android/android-components/components/compose/cfr/src/main/res/values-gl/strings.xml
new file mode 100644
index 0000000000..fdc1c7e79f
--- /dev/null
+++ b/mobile/android/android-components/components/compose/cfr/src/main/res/values-gl/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description (not visible, for screen readers etc.): Description for the close button of a Contextual Feature Recommendation Popup. -->
+ <string name="mozac_cfr_dismiss_button_content_description">Rexeitar</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/cfr/src/main/res/values-gn/strings.xml b/mobile/android/android-components/components/compose/cfr/src/main/res/values-gn/strings.xml
new file mode 100644
index 0000000000..9615457637
--- /dev/null
+++ b/mobile/android/android-components/components/compose/cfr/src/main/res/values-gn/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description (not visible, for screen readers etc.): Description for the close button of a Contextual Feature Recommendation Popup. -->
+ <string name="mozac_cfr_dismiss_button_content_description">Mboyke</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/cfr/src/main/res/values-hr/strings.xml b/mobile/android/android-components/components/compose/cfr/src/main/res/values-hr/strings.xml
new file mode 100644
index 0000000000..d8b54cb34b
--- /dev/null
+++ b/mobile/android/android-components/components/compose/cfr/src/main/res/values-hr/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description (not visible, for screen readers etc.): Description for the close button of a Contextual Feature Recommendation Popup. -->
+ <string name="mozac_cfr_dismiss_button_content_description">Odbaci</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/cfr/src/main/res/values-hsb/strings.xml b/mobile/android/android-components/components/compose/cfr/src/main/res/values-hsb/strings.xml
new file mode 100644
index 0000000000..d4b638b5be
--- /dev/null
+++ b/mobile/android/android-components/components/compose/cfr/src/main/res/values-hsb/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description (not visible, for screen readers etc.): Description for the close button of a Contextual Feature Recommendation Popup. -->
+ <string name="mozac_cfr_dismiss_button_content_description">Zaćisnyć</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/cfr/src/main/res/values-hu/strings.xml b/mobile/android/android-components/components/compose/cfr/src/main/res/values-hu/strings.xml
new file mode 100644
index 0000000000..00bc0d7781
--- /dev/null
+++ b/mobile/android/android-components/components/compose/cfr/src/main/res/values-hu/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description (not visible, for screen readers etc.): Description for the close button of a Contextual Feature Recommendation Popup. -->
+ <string name="mozac_cfr_dismiss_button_content_description">Eltüntetés</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/cfr/src/main/res/values-hy-rAM/strings.xml b/mobile/android/android-components/components/compose/cfr/src/main/res/values-hy-rAM/strings.xml
new file mode 100644
index 0000000000..6a33629dd2
--- /dev/null
+++ b/mobile/android/android-components/components/compose/cfr/src/main/res/values-hy-rAM/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description (not visible, for screen readers etc.): Description for the close button of a Contextual Feature Recommendation Popup. -->
+ <string name="mozac_cfr_dismiss_button_content_description">Բաց թողնել</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/cfr/src/main/res/values-ia/strings.xml b/mobile/android/android-components/components/compose/cfr/src/main/res/values-ia/strings.xml
new file mode 100644
index 0000000000..716e14b9a7
--- /dev/null
+++ b/mobile/android/android-components/components/compose/cfr/src/main/res/values-ia/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description (not visible, for screen readers etc.): Description for the close button of a Contextual Feature Recommendation Popup. -->
+ <string name="mozac_cfr_dismiss_button_content_description">Dimitter</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/cfr/src/main/res/values-in/strings.xml b/mobile/android/android-components/components/compose/cfr/src/main/res/values-in/strings.xml
new file mode 100644
index 0000000000..a1d014b221
--- /dev/null
+++ b/mobile/android/android-components/components/compose/cfr/src/main/res/values-in/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description (not visible, for screen readers etc.): Description for the close button of a Contextual Feature Recommendation Popup. -->
+ <string name="mozac_cfr_dismiss_button_content_description">Tutup</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/cfr/src/main/res/values-is/strings.xml b/mobile/android/android-components/components/compose/cfr/src/main/res/values-is/strings.xml
new file mode 100644
index 0000000000..6ef45a90ca
--- /dev/null
+++ b/mobile/android/android-components/components/compose/cfr/src/main/res/values-is/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description (not visible, for screen readers etc.): Description for the close button of a Contextual Feature Recommendation Popup. -->
+ <string name="mozac_cfr_dismiss_button_content_description">Hafna</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/cfr/src/main/res/values-it/strings.xml b/mobile/android/android-components/components/compose/cfr/src/main/res/values-it/strings.xml
new file mode 100644
index 0000000000..07debd3b5c
--- /dev/null
+++ b/mobile/android/android-components/components/compose/cfr/src/main/res/values-it/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description (not visible, for screen readers etc.): Description for the close button of a Contextual Feature Recommendation Popup. -->
+ <string name="mozac_cfr_dismiss_button_content_description">Chiudi</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/cfr/src/main/res/values-iw/strings.xml b/mobile/android/android-components/components/compose/cfr/src/main/res/values-iw/strings.xml
new file mode 100644
index 0000000000..d7c5324959
--- /dev/null
+++ b/mobile/android/android-components/components/compose/cfr/src/main/res/values-iw/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description (not visible, for screen readers etc.): Description for the close button of a Contextual Feature Recommendation Popup. -->
+ <string name="mozac_cfr_dismiss_button_content_description">סגירה</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/cfr/src/main/res/values-ja/strings.xml b/mobile/android/android-components/components/compose/cfr/src/main/res/values-ja/strings.xml
new file mode 100644
index 0000000000..a1efc5c03d
--- /dev/null
+++ b/mobile/android/android-components/components/compose/cfr/src/main/res/values-ja/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description (not visible, for screen readers etc.): Description for the close button of a Contextual Feature Recommendation Popup. -->
+ <string name="mozac_cfr_dismiss_button_content_description">閉じる</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/cfr/src/main/res/values-ka/strings.xml b/mobile/android/android-components/components/compose/cfr/src/main/res/values-ka/strings.xml
new file mode 100644
index 0000000000..49bea70e48
--- /dev/null
+++ b/mobile/android/android-components/components/compose/cfr/src/main/res/values-ka/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description (not visible, for screen readers etc.): Description for the close button of a Contextual Feature Recommendation Popup. -->
+ <string name="mozac_cfr_dismiss_button_content_description">არიდება</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/cfr/src/main/res/values-kaa/strings.xml b/mobile/android/android-components/components/compose/cfr/src/main/res/values-kaa/strings.xml
new file mode 100644
index 0000000000..927fa4b2d3
--- /dev/null
+++ b/mobile/android/android-components/components/compose/cfr/src/main/res/values-kaa/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description (not visible, for screen readers etc.): Description for the close button of a Contextual Feature Recommendation Popup. -->
+ <string name="mozac_cfr_dismiss_button_content_description">Jabıw</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/cfr/src/main/res/values-kab/strings.xml b/mobile/android/android-components/components/compose/cfr/src/main/res/values-kab/strings.xml
new file mode 100644
index 0000000000..05b7c36c7a
--- /dev/null
+++ b/mobile/android/android-components/components/compose/cfr/src/main/res/values-kab/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description (not visible, for screen readers etc.): Description for the close button of a Contextual Feature Recommendation Popup. -->
+ <string name="mozac_cfr_dismiss_button_content_description">Zgel</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/cfr/src/main/res/values-kk/strings.xml b/mobile/android/android-components/components/compose/cfr/src/main/res/values-kk/strings.xml
new file mode 100644
index 0000000000..1e137a1fb1
--- /dev/null
+++ b/mobile/android/android-components/components/compose/cfr/src/main/res/values-kk/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description (not visible, for screen readers etc.): Description for the close button of a Contextual Feature Recommendation Popup. -->
+ <string name="mozac_cfr_dismiss_button_content_description">Тайдыру</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/cfr/src/main/res/values-kmr/strings.xml b/mobile/android/android-components/components/compose/cfr/src/main/res/values-kmr/strings.xml
new file mode 100644
index 0000000000..0a59a2e76f
--- /dev/null
+++ b/mobile/android/android-components/components/compose/cfr/src/main/res/values-kmr/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description (not visible, for screen readers etc.): Description for the close button of a Contextual Feature Recommendation Popup. -->
+ <string name="mozac_cfr_dismiss_button_content_description">Bigire</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/cfr/src/main/res/values-ko/strings.xml b/mobile/android/android-components/components/compose/cfr/src/main/res/values-ko/strings.xml
new file mode 100644
index 0000000000..a8f2e61c9b
--- /dev/null
+++ b/mobile/android/android-components/components/compose/cfr/src/main/res/values-ko/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description (not visible, for screen readers etc.): Description for the close button of a Contextual Feature Recommendation Popup. -->
+ <string name="mozac_cfr_dismiss_button_content_description">닫기</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/cfr/src/main/res/values-lo/strings.xml b/mobile/android/android-components/components/compose/cfr/src/main/res/values-lo/strings.xml
new file mode 100644
index 0000000000..1200deb331
--- /dev/null
+++ b/mobile/android/android-components/components/compose/cfr/src/main/res/values-lo/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description (not visible, for screen readers etc.): Description for the close button of a Contextual Feature Recommendation Popup. -->
+ <string name="mozac_cfr_dismiss_button_content_description">ປິດ</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/cfr/src/main/res/values-lt/strings.xml b/mobile/android/android-components/components/compose/cfr/src/main/res/values-lt/strings.xml
new file mode 100644
index 0000000000..d2d923b1b9
--- /dev/null
+++ b/mobile/android/android-components/components/compose/cfr/src/main/res/values-lt/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description (not visible, for screen readers etc.): Description for the close button of a Contextual Feature Recommendation Popup. -->
+ <string name="mozac_cfr_dismiss_button_content_description">Paslėpti</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/cfr/src/main/res/values-nb-rNO/strings.xml b/mobile/android/android-components/components/compose/cfr/src/main/res/values-nb-rNO/strings.xml
new file mode 100644
index 0000000000..a403088daf
--- /dev/null
+++ b/mobile/android/android-components/components/compose/cfr/src/main/res/values-nb-rNO/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description (not visible, for screen readers etc.): Description for the close button of a Contextual Feature Recommendation Popup. -->
+ <string name="mozac_cfr_dismiss_button_content_description">Ignorer</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/cfr/src/main/res/values-nl/strings.xml b/mobile/android/android-components/components/compose/cfr/src/main/res/values-nl/strings.xml
new file mode 100644
index 0000000000..db4b674192
--- /dev/null
+++ b/mobile/android/android-components/components/compose/cfr/src/main/res/values-nl/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description (not visible, for screen readers etc.): Description for the close button of a Contextual Feature Recommendation Popup. -->
+ <string name="mozac_cfr_dismiss_button_content_description">Sluiten</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/cfr/src/main/res/values-nn-rNO/strings.xml b/mobile/android/android-components/components/compose/cfr/src/main/res/values-nn-rNO/strings.xml
new file mode 100644
index 0000000000..a403088daf
--- /dev/null
+++ b/mobile/android/android-components/components/compose/cfr/src/main/res/values-nn-rNO/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description (not visible, for screen readers etc.): Description for the close button of a Contextual Feature Recommendation Popup. -->
+ <string name="mozac_cfr_dismiss_button_content_description">Ignorer</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/cfr/src/main/res/values-oc/strings.xml b/mobile/android/android-components/components/compose/cfr/src/main/res/values-oc/strings.xml
new file mode 100644
index 0000000000..7726a050b9
--- /dev/null
+++ b/mobile/android/android-components/components/compose/cfr/src/main/res/values-oc/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description (not visible, for screen readers etc.): Description for the close button of a Contextual Feature Recommendation Popup. -->
+ <string name="mozac_cfr_dismiss_button_content_description">Ignorar</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/cfr/src/main/res/values-pa-rIN/strings.xml b/mobile/android/android-components/components/compose/cfr/src/main/res/values-pa-rIN/strings.xml
new file mode 100644
index 0000000000..495a1e811e
--- /dev/null
+++ b/mobile/android/android-components/components/compose/cfr/src/main/res/values-pa-rIN/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description (not visible, for screen readers etc.): Description for the close button of a Contextual Feature Recommendation Popup. -->
+ <string name="mozac_cfr_dismiss_button_content_description">ਖਾਰਜ ਕਰੋ</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/cfr/src/main/res/values-pa-rPK/strings.xml b/mobile/android/android-components/components/compose/cfr/src/main/res/values-pa-rPK/strings.xml
new file mode 100644
index 0000000000..27ee637bfd
--- /dev/null
+++ b/mobile/android/android-components/components/compose/cfr/src/main/res/values-pa-rPK/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description (not visible, for screen readers etc.): Description for the close button of a Contextual Feature Recommendation Popup. -->
+ <string name="mozac_cfr_dismiss_button_content_description">بند کرو</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/cfr/src/main/res/values-pl/strings.xml b/mobile/android/android-components/components/compose/cfr/src/main/res/values-pl/strings.xml
new file mode 100644
index 0000000000..6fb5777d89
--- /dev/null
+++ b/mobile/android/android-components/components/compose/cfr/src/main/res/values-pl/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description (not visible, for screen readers etc.): Description for the close button of a Contextual Feature Recommendation Popup. -->
+ <string name="mozac_cfr_dismiss_button_content_description">Zamknij</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/cfr/src/main/res/values-pt-rBR/strings.xml b/mobile/android/android-components/components/compose/cfr/src/main/res/values-pt-rBR/strings.xml
new file mode 100644
index 0000000000..f14c6e05a9
--- /dev/null
+++ b/mobile/android/android-components/components/compose/cfr/src/main/res/values-pt-rBR/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description (not visible, for screen readers etc.): Description for the close button of a Contextual Feature Recommendation Popup. -->
+ <string name="mozac_cfr_dismiss_button_content_description">Descartar</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/cfr/src/main/res/values-pt-rPT/strings.xml b/mobile/android/android-components/components/compose/cfr/src/main/res/values-pt-rPT/strings.xml
new file mode 100644
index 0000000000..da76c02be9
--- /dev/null
+++ b/mobile/android/android-components/components/compose/cfr/src/main/res/values-pt-rPT/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description (not visible, for screen readers etc.): Description for the close button of a Contextual Feature Recommendation Popup. -->
+ <string name="mozac_cfr_dismiss_button_content_description">Dispensar</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/cfr/src/main/res/values-rm/strings.xml b/mobile/android/android-components/components/compose/cfr/src/main/res/values-rm/strings.xml
new file mode 100644
index 0000000000..12c3220442
--- /dev/null
+++ b/mobile/android/android-components/components/compose/cfr/src/main/res/values-rm/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description (not visible, for screen readers etc.): Description for the close button of a Contextual Feature Recommendation Popup. -->
+ <string name="mozac_cfr_dismiss_button_content_description">Serrar</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/cfr/src/main/res/values-ru/strings.xml b/mobile/android/android-components/components/compose/cfr/src/main/res/values-ru/strings.xml
new file mode 100644
index 0000000000..c9748091ec
--- /dev/null
+++ b/mobile/android/android-components/components/compose/cfr/src/main/res/values-ru/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description (not visible, for screen readers etc.): Description for the close button of a Contextual Feature Recommendation Popup. -->
+ <string name="mozac_cfr_dismiss_button_content_description">Скрыть</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/cfr/src/main/res/values-sat/strings.xml b/mobile/android/android-components/components/compose/cfr/src/main/res/values-sat/strings.xml
new file mode 100644
index 0000000000..e432bced8a
--- /dev/null
+++ b/mobile/android/android-components/components/compose/cfr/src/main/res/values-sat/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description (not visible, for screen readers etc.): Description for the close button of a Contextual Feature Recommendation Popup. -->
+ <string name="mozac_cfr_dismiss_button_content_description">ᱵᱚᱱᱫ</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/cfr/src/main/res/values-sc/strings.xml b/mobile/android/android-components/components/compose/cfr/src/main/res/values-sc/strings.xml
new file mode 100644
index 0000000000..2cf10b5097
--- /dev/null
+++ b/mobile/android/android-components/components/compose/cfr/src/main/res/values-sc/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description (not visible, for screen readers etc.): Description for the close button of a Contextual Feature Recommendation Popup. -->
+ <string name="mozac_cfr_dismiss_button_content_description">Iscarta</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/cfr/src/main/res/values-si/strings.xml b/mobile/android/android-components/components/compose/cfr/src/main/res/values-si/strings.xml
new file mode 100644
index 0000000000..692fe43d68
--- /dev/null
+++ b/mobile/android/android-components/components/compose/cfr/src/main/res/values-si/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description (not visible, for screen readers etc.): Description for the close button of a Contextual Feature Recommendation Popup. -->
+ <string name="mozac_cfr_dismiss_button_content_description">ඉවතලන්න</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/cfr/src/main/res/values-sk/strings.xml b/mobile/android/android-components/components/compose/cfr/src/main/res/values-sk/strings.xml
new file mode 100644
index 0000000000..335a45ecc7
--- /dev/null
+++ b/mobile/android/android-components/components/compose/cfr/src/main/res/values-sk/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description (not visible, for screen readers etc.): Description for the close button of a Contextual Feature Recommendation Popup. -->
+ <string name="mozac_cfr_dismiss_button_content_description">Zavrieť</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/cfr/src/main/res/values-skr/strings.xml b/mobile/android/android-components/components/compose/cfr/src/main/res/values-skr/strings.xml
new file mode 100644
index 0000000000..ed279b9081
--- /dev/null
+++ b/mobile/android/android-components/components/compose/cfr/src/main/res/values-skr/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description (not visible, for screen readers etc.): Description for the close button of a Contextual Feature Recommendation Popup. -->
+ <string name="mozac_cfr_dismiss_button_content_description">فارغ کرو</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/cfr/src/main/res/values-sl/strings.xml b/mobile/android/android-components/components/compose/cfr/src/main/res/values-sl/strings.xml
new file mode 100644
index 0000000000..b476df56f0
--- /dev/null
+++ b/mobile/android/android-components/components/compose/cfr/src/main/res/values-sl/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description (not visible, for screen readers etc.): Description for the close button of a Contextual Feature Recommendation Popup. -->
+ <string name="mozac_cfr_dismiss_button_content_description">Zapri</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/cfr/src/main/res/values-sq/strings.xml b/mobile/android/android-components/components/compose/cfr/src/main/res/values-sq/strings.xml
new file mode 100644
index 0000000000..23c71495b1
--- /dev/null
+++ b/mobile/android/android-components/components/compose/cfr/src/main/res/values-sq/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description (not visible, for screen readers etc.): Description for the close button of a Contextual Feature Recommendation Popup. -->
+ <string name="mozac_cfr_dismiss_button_content_description">Hidhe tej</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/cfr/src/main/res/values-sr/strings.xml b/mobile/android/android-components/components/compose/cfr/src/main/res/values-sr/strings.xml
new file mode 100644
index 0000000000..f535bf88e7
--- /dev/null
+++ b/mobile/android/android-components/components/compose/cfr/src/main/res/values-sr/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description (not visible, for screen readers etc.): Description for the close button of a Contextual Feature Recommendation Popup. -->
+ <string name="mozac_cfr_dismiss_button_content_description">Одбаци</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/cfr/src/main/res/values-su/strings.xml b/mobile/android/android-components/components/compose/cfr/src/main/res/values-su/strings.xml
new file mode 100644
index 0000000000..a1d014b221
--- /dev/null
+++ b/mobile/android/android-components/components/compose/cfr/src/main/res/values-su/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description (not visible, for screen readers etc.): Description for the close button of a Contextual Feature Recommendation Popup. -->
+ <string name="mozac_cfr_dismiss_button_content_description">Tutup</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/cfr/src/main/res/values-sv-rSE/strings.xml b/mobile/android/android-components/components/compose/cfr/src/main/res/values-sv-rSE/strings.xml
new file mode 100644
index 0000000000..87506c9962
--- /dev/null
+++ b/mobile/android/android-components/components/compose/cfr/src/main/res/values-sv-rSE/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description (not visible, for screen readers etc.): Description for the close button of a Contextual Feature Recommendation Popup. -->
+ <string name="mozac_cfr_dismiss_button_content_description">Ignorera</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/cfr/src/main/res/values-szl/strings.xml b/mobile/android/android-components/components/compose/cfr/src/main/res/values-szl/strings.xml
new file mode 100644
index 0000000000..ca2214b892
--- /dev/null
+++ b/mobile/android/android-components/components/compose/cfr/src/main/res/values-szl/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description (not visible, for screen readers etc.): Description for the close button of a Contextual Feature Recommendation Popup. -->
+ <string name="mozac_cfr_dismiss_button_content_description">Ôdkoż</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/cfr/src/main/res/values-tg/strings.xml b/mobile/android/android-components/components/compose/cfr/src/main/res/values-tg/strings.xml
new file mode 100644
index 0000000000..e77dfe593c
--- /dev/null
+++ b/mobile/android/android-components/components/compose/cfr/src/main/res/values-tg/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description (not visible, for screen readers etc.): Description for the close button of a Contextual Feature Recommendation Popup. -->
+ <string name="mozac_cfr_dismiss_button_content_description">Нодида гузарондан</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/cfr/src/main/res/values-th/strings.xml b/mobile/android/android-components/components/compose/cfr/src/main/res/values-th/strings.xml
new file mode 100644
index 0000000000..4ab6fc629d
--- /dev/null
+++ b/mobile/android/android-components/components/compose/cfr/src/main/res/values-th/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description (not visible, for screen readers etc.): Description for the close button of a Contextual Feature Recommendation Popup. -->
+ <string name="mozac_cfr_dismiss_button_content_description">ปิด</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/cfr/src/main/res/values-tr/strings.xml b/mobile/android/android-components/components/compose/cfr/src/main/res/values-tr/strings.xml
new file mode 100644
index 0000000000..76f55fe0e8
--- /dev/null
+++ b/mobile/android/android-components/components/compose/cfr/src/main/res/values-tr/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description (not visible, for screen readers etc.): Description for the close button of a Contextual Feature Recommendation Popup. -->
+ <string name="mozac_cfr_dismiss_button_content_description">Kapat</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/cfr/src/main/res/values-trs/strings.xml b/mobile/android/android-components/components/compose/cfr/src/main/res/values-trs/strings.xml
new file mode 100644
index 0000000000..b5bdf60de2
--- /dev/null
+++ b/mobile/android/android-components/components/compose/cfr/src/main/res/values-trs/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description (not visible, for screen readers etc.): Description for the close button of a Contextual Feature Recommendation Popup. -->
+ <string name="mozac_cfr_dismiss_button_content_description">Si gi\'hiaj guendô\'</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/cfr/src/main/res/values-tt/strings.xml b/mobile/android/android-components/components/compose/cfr/src/main/res/values-tt/strings.xml
new file mode 100644
index 0000000000..acdeb1ed5b
--- /dev/null
+++ b/mobile/android/android-components/components/compose/cfr/src/main/res/values-tt/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description (not visible, for screen readers etc.): Description for the close button of a Contextual Feature Recommendation Popup. -->
+ <string name="mozac_cfr_dismiss_button_content_description">Яшерү</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/cfr/src/main/res/values-ug/strings.xml b/mobile/android/android-components/components/compose/cfr/src/main/res/values-ug/strings.xml
new file mode 100644
index 0000000000..1eaac24e2a
--- /dev/null
+++ b/mobile/android/android-components/components/compose/cfr/src/main/res/values-ug/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description (not visible, for screen readers etc.): Description for the close button of a Contextual Feature Recommendation Popup. -->
+ <string name="mozac_cfr_dismiss_button_content_description">بولدىلا</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/cfr/src/main/res/values-uk/strings.xml b/mobile/android/android-components/components/compose/cfr/src/main/res/values-uk/strings.xml
new file mode 100644
index 0000000000..1d1f11dbbb
--- /dev/null
+++ b/mobile/android/android-components/components/compose/cfr/src/main/res/values-uk/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description (not visible, for screen readers etc.): Description for the close button of a Contextual Feature Recommendation Popup. -->
+ <string name="mozac_cfr_dismiss_button_content_description">Відхилити</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/cfr/src/main/res/values-uz/strings.xml b/mobile/android/android-components/components/compose/cfr/src/main/res/values-uz/strings.xml
new file mode 100644
index 0000000000..716312dfd9
--- /dev/null
+++ b/mobile/android/android-components/components/compose/cfr/src/main/res/values-uz/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description (not visible, for screen readers etc.): Description for the close button of a Contextual Feature Recommendation Popup. -->
+ <string name="mozac_cfr_dismiss_button_content_description">Rad qilish</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/cfr/src/main/res/values-vec/strings.xml b/mobile/android/android-components/components/compose/cfr/src/main/res/values-vec/strings.xml
new file mode 100644
index 0000000000..8c4ff51166
--- /dev/null
+++ b/mobile/android/android-components/components/compose/cfr/src/main/res/values-vec/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description (not visible, for screen readers etc.): Description for the close button of a Contextual Feature Recommendation Popup. -->
+ <string name="mozac_cfr_dismiss_button_content_description">Sara</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/cfr/src/main/res/values-vi/strings.xml b/mobile/android/android-components/components/compose/cfr/src/main/res/values-vi/strings.xml
new file mode 100644
index 0000000000..3d9e560fee
--- /dev/null
+++ b/mobile/android/android-components/components/compose/cfr/src/main/res/values-vi/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description (not visible, for screen readers etc.): Description for the close button of a Contextual Feature Recommendation Popup. -->
+ <string name="mozac_cfr_dismiss_button_content_description">Bỏ qua</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/cfr/src/main/res/values-zh-rCN/strings.xml b/mobile/android/android-components/components/compose/cfr/src/main/res/values-zh-rCN/strings.xml
new file mode 100644
index 0000000000..1c5ff52f06
--- /dev/null
+++ b/mobile/android/android-components/components/compose/cfr/src/main/res/values-zh-rCN/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description (not visible, for screen readers etc.): Description for the close button of a Contextual Feature Recommendation Popup. -->
+ <string name="mozac_cfr_dismiss_button_content_description">知道了</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/cfr/src/main/res/values-zh-rTW/strings.xml b/mobile/android/android-components/components/compose/cfr/src/main/res/values-zh-rTW/strings.xml
new file mode 100644
index 0000000000..9414216213
--- /dev/null
+++ b/mobile/android/android-components/components/compose/cfr/src/main/res/values-zh-rTW/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description (not visible, for screen readers etc.): Description for the close button of a Contextual Feature Recommendation Popup. -->
+ <string name="mozac_cfr_dismiss_button_content_description">知道了!</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/cfr/src/main/res/values/strings.xml b/mobile/android/android-components/components/compose/cfr/src/main/res/values/strings.xml
new file mode 100644
index 0000000000..86c00ee3c0
--- /dev/null
+++ b/mobile/android/android-components/components/compose/cfr/src/main/res/values/strings.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<!-- 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/. -->
+<resources>
+ <!-- Content description (not visible, for screen readers etc.): Description for the close button of a Contextual Feature Recommendation Popup. -->
+ <string name="mozac_cfr_dismiss_button_content_description">Dismiss</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/cfr/src/test/java/mozilla/components/compose/cfr/CFRPopupFullscreenLayoutTest.kt b/mobile/android/android-components/components/compose/cfr/src/test/java/mozilla/components/compose/cfr/CFRPopupFullscreenLayoutTest.kt
new file mode 100644
index 0000000000..a0259e0bc5
--- /dev/null
+++ b/mobile/android/android-components/components/compose/cfr/src/test/java/mozilla/components/compose/cfr/CFRPopupFullscreenLayoutTest.kt
@@ -0,0 +1,561 @@
+/* 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 mozilla.components.compose.cfr
+
+import android.content.Context
+import android.content.pm.ActivityInfo
+import android.graphics.PixelFormat
+import android.view.View
+import android.view.ViewManager
+import android.view.WindowManager
+import android.view.WindowManager.LayoutParams
+import androidx.compose.ui.unit.dp
+import androidx.lifecycle.findViewTreeLifecycleOwner
+import androidx.lifecycle.setViewTreeLifecycleOwner
+import androidx.savedstate.findViewTreeSavedStateRegistryOwner
+import androidx.savedstate.setViewTreeSavedStateRegistryOwner
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.test.advanceTimeBy
+import mozilla.components.compose.cfr.CFRPopup.PopupAlignment
+import mozilla.components.support.test.argumentCaptor
+import mozilla.components.support.test.eq
+import mozilla.components.support.test.mock
+import mozilla.components.support.test.robolectric.testContext
+import mozilla.components.support.test.rule.MainCoroutineRule
+import mozilla.components.support.test.rule.runTestOnMain
+import org.junit.Assert.assertEquals
+import org.junit.Assert.assertNotNull
+import org.junit.Assert.assertNull
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.Mockito.doReturn
+import org.mockito.Mockito.spy
+import org.mockito.Mockito.times
+import org.mockito.Mockito.verify
+
+@ExperimentalCoroutinesApi
+@RunWith(AndroidJUnit4::class)
+class CFRPopupFullscreenLayoutTest {
+ @get:Rule
+ val coroutinesTestRule = MainCoroutineRule()
+
+ @Test
+ fun `WHEN the popup is shown THEN setup lifecycle owners`() {
+ val anchor = View(testContext).apply {
+ setViewTreeLifecycleOwner(mock())
+ this.setViewTreeSavedStateRegistryOwner(mock())
+ }
+
+ val popupView = spy(
+ CFRPopupFullscreenLayout(
+ anchor = anchor,
+ properties = mock(),
+ onDismiss = mock(),
+ text = { },
+ action = { },
+ ),
+ )
+ popupView.show()
+
+ assertNotNull(popupView.findViewTreeLifecycleOwner())
+ assertEquals(
+ anchor.findViewTreeLifecycleOwner(),
+ popupView.findViewTreeLifecycleOwner(),
+ )
+ assertNotNull(popupView.findViewTreeSavedStateRegistryOwner())
+ assertEquals(
+ assertNotNull(anchor.findViewTreeSavedStateRegistryOwner()),
+ assertNotNull(popupView.findViewTreeSavedStateRegistryOwner()),
+ )
+ }
+
+ @Test
+ fun `WHEN the popup is dismissed THEN cleanup lifecycle owners and detach from window`() {
+ val context = spy(testContext)
+ val anchor = View(context).apply {
+ setViewTreeLifecycleOwner(mock())
+ this.setViewTreeSavedStateRegistryOwner(mock())
+ }
+ val windowManager = spy(context.getSystemService(Context.WINDOW_SERVICE) as WindowManager)
+ doReturn(windowManager).`when`(context).getSystemService(Context.WINDOW_SERVICE)
+ val popupView = CFRPopupFullscreenLayout(anchor, mock(), mock(), { }, { })
+ popupView.show()
+ assertNotNull(popupView.findViewTreeLifecycleOwner())
+ assertNotNull(popupView.findViewTreeSavedStateRegistryOwner())
+
+ popupView.dismiss()
+
+ assertNull(popupView.findViewTreeLifecycleOwner())
+ assertNull(popupView.findViewTreeSavedStateRegistryOwner())
+ verify(windowManager).removeViewImmediate(popupView)
+ }
+
+ @Test
+ fun `GIVEN a popup WHEN adding it to window THEN use translucent layout params`() {
+ val context = spy(testContext)
+ val anchor = View(context)
+ val windowManager = spy(context.getSystemService(Context.WINDOW_SERVICE))
+ doReturn(windowManager).`when`(context).getSystemService(Context.WINDOW_SERVICE)
+ val popupView = CFRPopupFullscreenLayout(anchor, mock(), mock(), { }, { })
+ val layoutParamsCaptor = argumentCaptor<LayoutParams>()
+
+ popupView.show()
+
+ verify(windowManager as ViewManager).addView(eq(popupView), layoutParamsCaptor.capture())
+ assertEquals(LayoutParams.TYPE_APPLICATION_PANEL, layoutParamsCaptor.value.type)
+ assertEquals(anchor.applicationWindowToken, layoutParamsCaptor.value.token)
+ assertEquals(LayoutParams.MATCH_PARENT, layoutParamsCaptor.value.width)
+ assertEquals(LayoutParams.MATCH_PARENT, layoutParamsCaptor.value.height)
+ assertEquals(PixelFormat.TRANSLUCENT, layoutParamsCaptor.value.format)
+ assertEquals(
+ LayoutParams.FLAG_LAYOUT_IN_SCREEN or LayoutParams.FLAG_HARDWARE_ACCELERATED,
+ layoutParamsCaptor.value.flags,
+ )
+ }
+
+ @Test
+ fun `WHEN creating layout params THEN get fullscreen translucent layout params`() {
+ val anchor = View(testContext)
+ val popupView = CFRPopupFullscreenLayout(anchor, mock(), mock(), { }, { })
+
+ val result = popupView.createLayoutParams()
+
+ assertEquals(LayoutParams.TYPE_APPLICATION_PANEL, result.type)
+ assertEquals(anchor.applicationWindowToken, result.token)
+ assertEquals(LayoutParams.MATCH_PARENT, result.width)
+ assertEquals(LayoutParams.MATCH_PARENT, result.height)
+ assertEquals(PixelFormat.TRANSLUCENT, result.format)
+ assertEquals(
+ LayoutParams.FLAG_LAYOUT_IN_SCREEN or LayoutParams.FLAG_HARDWARE_ACCELERATED,
+ result.flags,
+ )
+ }
+
+ @Test
+ fun `GIVEN LTR and INDICATOR_CENTERED_IN_ANCHOR WHEN computing popup bounds THEN return the right X coordinates`() {
+ val anchor = View(testContext)
+ val properties = CFRPopupProperties(
+ popupWidth = 200.dp,
+ popupAlignment = PopupAlignment.INDICATOR_CENTERED_IN_ANCHOR,
+ indicatorArrowStartOffset = 0.dp,
+ )
+ val popupView = CFRPopupFullscreenLayout(anchor, properties, mock(), { }, { })
+
+ val result = popupView.computePopupHorizontalBounds(
+ anchorMiddleXCoord = Pixels(200),
+ arrowIndicatorWidth = Pixels(20),
+ screenWidth = Pixels(1000),
+ layoutDirection = View.LAYOUT_DIRECTION_LTR,
+ )
+
+ assertEquals(190, result.startCoord.value)
+ assertEquals(400, result.endCoord.value)
+ }
+
+ @Test
+ fun `GIVEN LTR and INDICATOR_CENTERED_IN_ANCHOR WHEN computing popup bounds THEN account for the provided indicator offset`() {
+ val anchor = View(testContext)
+ val properties = CFRPopupProperties(
+ popupWidth = 200.dp,
+ popupAlignment = PopupAlignment.INDICATOR_CENTERED_IN_ANCHOR,
+ indicatorArrowStartOffset = 50.dp,
+ )
+ val popupView = CFRPopupFullscreenLayout(anchor, properties, mock(), { }, { })
+
+ val result = popupView.computePopupHorizontalBounds(
+ anchorMiddleXCoord = Pixels(200),
+ arrowIndicatorWidth = Pixels(20),
+ screenWidth = Pixels(1000),
+ layoutDirection = View.LAYOUT_DIRECTION_LTR,
+ )
+
+ // The popup should be translated to the start to ensure the offset to the indicator is respected.
+ assertEquals(140, result.startCoord.value)
+ assertEquals(350, result.endCoord.value)
+ }
+
+ @Test
+ fun `GIVEN LTR and INDICATOR_CENTERED_IN_ANCHOR WHEN computing popup bounds and the popup doesn't fit THEN return the right X coordinates`() {
+ val anchor = View(testContext)
+ val properties = CFRPopupProperties(
+ popupWidth = 900.dp,
+ popupAlignment = PopupAlignment.INDICATOR_CENTERED_IN_ANCHOR,
+ indicatorArrowStartOffset = 0.dp,
+ )
+ val popupView = CFRPopupFullscreenLayout(anchor, properties, mock(), { }, { })
+
+ val result = popupView.computePopupHorizontalBounds(
+ anchorMiddleXCoord = Pixels(200),
+ arrowIndicatorWidth = Pixels(20),
+ screenWidth = Pixels(1000),
+ layoutDirection = View.LAYOUT_DIRECTION_LTR,
+ )
+
+ // The popup should be translated to the start to ensure it fits the screen.
+ assertEquals(90, result.startCoord.value)
+ assertEquals(1000, result.endCoord.value)
+ }
+
+ @Test
+ fun `GIVEN RTL and INDICATOR_CENTERED_IN_ANCHOR WHEN computing popup bounds THEN return the right X coordinates`() {
+ val anchor = View(testContext)
+ val properties = CFRPopupProperties(
+ popupWidth = 200.dp,
+ popupAlignment = PopupAlignment.INDICATOR_CENTERED_IN_ANCHOR,
+ indicatorArrowStartOffset = 0.dp,
+ )
+ val popupView = CFRPopupFullscreenLayout(anchor, properties, mock(), { }, { })
+
+ val result = popupView.computePopupHorizontalBounds(
+ anchorMiddleXCoord = Pixels(800),
+ arrowIndicatorWidth = Pixels(20),
+ screenWidth = Pixels(1000),
+ layoutDirection = View.LAYOUT_DIRECTION_RTL,
+ )
+
+ assertEquals(810, result.startCoord.value)
+ assertEquals(600, result.endCoord.value)
+ }
+
+ @Test
+ fun `GIVEN RTL and INDICATOR_CENTERED_IN_ANCHOR WHEN computing popup bounds THEN account for the provided indicator offset`() {
+ val anchor = View(testContext)
+ val properties = CFRPopupProperties(
+ popupWidth = 200.dp,
+ popupAlignment = PopupAlignment.INDICATOR_CENTERED_IN_ANCHOR,
+ indicatorArrowStartOffset = 50.dp,
+ )
+ val popupView = CFRPopupFullscreenLayout(anchor, properties, mock(), { }, { })
+
+ val result = popupView.computePopupHorizontalBounds(
+ anchorMiddleXCoord = Pixels(800),
+ arrowIndicatorWidth = Pixels(20),
+ screenWidth = Pixels(1000),
+ layoutDirection = View.LAYOUT_DIRECTION_RTL,
+ )
+
+ // The popup should be translated to the start to ensure the offset to the indicator is respected.
+ assertEquals(860, result.startCoord.value)
+ assertEquals(650, result.endCoord.value)
+ }
+
+ @Test
+ fun `GIVEN RTL and INDICATOR_CENTERED_IN_ANCHOR WHEN computing popup bounds and the popup doesn't fit THEN return the right X coordinates`() {
+ val anchor = View(testContext)
+ val properties = CFRPopupProperties(
+ popupWidth = 900.dp,
+ popupAlignment = PopupAlignment.INDICATOR_CENTERED_IN_ANCHOR,
+ indicatorArrowStartOffset = 0.dp,
+ )
+ val popupView = CFRPopupFullscreenLayout(anchor, properties, mock(), { }, { })
+
+ val result = popupView.computePopupHorizontalBounds(
+ anchorMiddleXCoord = Pixels(800),
+ arrowIndicatorWidth = Pixels(20),
+ screenWidth = Pixels(1000),
+ layoutDirection = View.LAYOUT_DIRECTION_RTL,
+ )
+
+ // The popup should be translated to the start to ensure it fits the screen.
+ assertEquals(910, result.startCoord.value)
+ assertEquals(0, result.endCoord.value)
+ }
+
+ @Test
+ fun `GIVEN LTR and BODY_TO_ANCHOR_START WHEN computing popup bounds THEN return the right X coordinates`() {
+ val anchor = spy(View(testContext))
+ doReturn(400).`when`(anchor).width
+ doReturn(200f).`when`(anchor).x
+ val properties = CFRPopupProperties(
+ popupWidth = 300.dp,
+ popupAlignment = PopupAlignment.BODY_TO_ANCHOR_START,
+ indicatorArrowStartOffset = 0.dp,
+ )
+ val popupView = CFRPopupFullscreenLayout(anchor, properties, mock(), { }, { })
+
+ val result = popupView.computePopupHorizontalBounds(
+ anchorMiddleXCoord = Pixels(300),
+ arrowIndicatorWidth = Pixels(20),
+ screenWidth = Pixels(1000),
+ layoutDirection = View.LAYOUT_DIRECTION_LTR,
+ )
+
+ assertEquals(200, result.startCoord.value)
+ assertEquals(510, result.endCoord.value)
+ }
+
+ @Test
+ fun `GIVEN LTR and BODY_TO_ANCHOR_START WHEN computing popup bounds THEN return the right X coordinates and don't account for the provided indicator offset`() {
+ val anchor = spy(View(testContext))
+ doReturn(400).`when`(anchor).width
+ doReturn(200f).`when`(anchor).x
+ val properties = CFRPopupProperties(
+ popupWidth = 300.dp,
+ popupAlignment = PopupAlignment.BODY_TO_ANCHOR_START,
+ indicatorArrowStartOffset = 50.dp,
+ )
+ val popupView = CFRPopupFullscreenLayout(anchor, properties, mock(), { }, { })
+
+ val result = popupView.computePopupHorizontalBounds(
+ anchorMiddleXCoord = Pixels(300),
+ arrowIndicatorWidth = Pixels(20),
+ screenWidth = Pixels(1000),
+ layoutDirection = View.LAYOUT_DIRECTION_LTR,
+ )
+
+ assertEquals(200, result.startCoord.value)
+ assertEquals(510, result.endCoord.value)
+ }
+
+ @Test
+ fun `GIVEN RTL and BODY_TO_ANCHOR_START WHEN computing popup bounds THEN return the right X coordinates`() {
+ val anchor = spy(View(testContext))
+ doReturn(400).`when`(anchor).width
+ doReturn(200f).`when`(anchor).x
+ val properties = CFRPopupProperties(
+ popupWidth = 200.dp,
+ popupAlignment = PopupAlignment.BODY_TO_ANCHOR_START,
+ indicatorArrowStartOffset = 0.dp,
+ )
+ val popupView = CFRPopupFullscreenLayout(anchor, properties, mock(), { }, { })
+
+ val result = popupView.computePopupHorizontalBounds(
+ anchorMiddleXCoord = Pixels(300),
+ arrowIndicatorWidth = Pixels(20),
+ screenWidth = Pixels(1000),
+ layoutDirection = View.LAYOUT_DIRECTION_RTL,
+ )
+
+ assertEquals(600, result.startCoord.value)
+ assertEquals(390, result.endCoord.value)
+ }
+
+ @Test
+ fun `GIVEN RTL and BODY_TO_ANCHOR_START WHEN computing popup bounds THEN return the right X coordinates and don't account for the provided indicator offset`() {
+ val anchor = spy(View(testContext))
+ doReturn(400).`when`(anchor).width
+ doReturn(200f).`when`(anchor).x
+ val properties = CFRPopupProperties(
+ popupWidth = 200.dp,
+ popupAlignment = PopupAlignment.BODY_TO_ANCHOR_START,
+ indicatorArrowStartOffset = 50.dp,
+ )
+ val popupView = CFRPopupFullscreenLayout(anchor, properties, mock(), { }, { })
+
+ val result = popupView.computePopupHorizontalBounds(
+ anchorMiddleXCoord = Pixels(300),
+ arrowIndicatorWidth = Pixels(20),
+ screenWidth = Pixels(1000),
+ layoutDirection = View.LAYOUT_DIRECTION_RTL,
+ )
+
+ assertEquals(600, result.startCoord.value)
+ assertEquals(390, result.endCoord.value)
+ }
+
+ @Test
+ fun `GIVEN LTR and BODY_TO_ANCHOR_CENTER WHEN computing popup bounds THEN return the right X coordinates`() {
+ val anchor = spy(View(testContext))
+ doReturn(600).`when`(anchor).width
+ doReturn(200f).`when`(anchor).x
+ val properties = CFRPopupProperties(
+ popupWidth = 400.dp,
+ popupAlignment = PopupAlignment.BODY_TO_ANCHOR_CENTER,
+ indicatorArrowStartOffset = 0.dp,
+ )
+ val popupView = CFRPopupFullscreenLayout(anchor, properties, mock(), { }, { })
+
+ val result = popupView.computePopupHorizontalBounds(
+ anchorMiddleXCoord = Pixels(400),
+ arrowIndicatorWidth = Pixels(20),
+ screenWidth = Pixels(1000),
+ layoutDirection = View.LAYOUT_DIRECTION_LTR,
+ )
+
+ assertEquals(300, result.startCoord.value)
+ assertEquals(710, result.endCoord.value)
+ }
+
+ @Test
+ fun `GIVEN LTR and BODY_TO_ANCHOR_CENTER WHEN computing popup bounds THEN return the right X coordinates and don't account for the provided indicator offset`() {
+ val anchor = spy(View(testContext))
+ doReturn(600).`when`(anchor).width
+ doReturn(200f).`when`(anchor).x
+ val properties = CFRPopupProperties(
+ popupWidth = 400.dp,
+ popupAlignment = PopupAlignment.BODY_TO_ANCHOR_CENTER,
+ indicatorArrowStartOffset = 50.dp,
+ )
+ val popupView = CFRPopupFullscreenLayout(anchor, properties, mock(), { }, { })
+
+ val result = popupView.computePopupHorizontalBounds(
+ anchorMiddleXCoord = Pixels(400),
+ arrowIndicatorWidth = Pixels(20),
+ screenWidth = Pixels(1000),
+ layoutDirection = View.LAYOUT_DIRECTION_LTR,
+ )
+
+ assertEquals(300, result.startCoord.value)
+ assertEquals(710, result.endCoord.value)
+ }
+
+ @Test
+ fun `GIVEN RTL and BODY_TO_ANCHOR_CENTER WHEN computing popup bounds THEN return the right X coordinates`() {
+ val anchor = spy(View(testContext))
+ doReturn(600).`when`(anchor).width
+ doReturn(200f).`when`(anchor).x
+ val properties = CFRPopupProperties(
+ popupWidth = 400.dp,
+ popupAlignment = PopupAlignment.BODY_TO_ANCHOR_CENTER,
+ indicatorArrowStartOffset = 0.dp,
+ )
+ val popupView = CFRPopupFullscreenLayout(anchor, properties, mock(), { }, { })
+
+ val result = popupView.computePopupHorizontalBounds(
+ anchorMiddleXCoord = Pixels(300),
+ arrowIndicatorWidth = Pixels(20),
+ screenWidth = Pixels(1000),
+ layoutDirection = View.LAYOUT_DIRECTION_RTL,
+ )
+
+ assertEquals(700, result.startCoord.value)
+ assertEquals(290, result.endCoord.value)
+ }
+
+ @Test
+ fun `GIVEN RTL and BODY_TO_ANCHOR_CENTER WHEN computing popup bounds THEN return the right X coordinates and don't account for the provided indicator offset`() {
+ val anchor = spy(View(testContext))
+ doReturn(600).`when`(anchor).width
+ doReturn(200f).`when`(anchor).x
+ val properties = CFRPopupProperties(
+ popupWidth = 400.dp,
+ popupAlignment = PopupAlignment.BODY_TO_ANCHOR_CENTER,
+ indicatorArrowStartOffset = 50.dp,
+ )
+ val popupView = CFRPopupFullscreenLayout(anchor, properties, mock(), { }, { })
+
+ val result = popupView.computePopupHorizontalBounds(
+ anchorMiddleXCoord = Pixels(300),
+ arrowIndicatorWidth = Pixels(20),
+ screenWidth = Pixels(1000),
+ layoutDirection = View.LAYOUT_DIRECTION_RTL,
+ )
+
+ assertEquals(700, result.startCoord.value)
+ assertEquals(290, result.endCoord.value)
+ }
+
+ @Test
+ fun `GIVEN LTR direction and popup is larger than viewport width WHEN computing popup bounds for CENTERED_IN_SCREEN alignment THEN return the correct horizontal bounds`() {
+ val anchor = spy(View(testContext))
+ doReturn(400).`when`(anchor).width
+ doReturn(200f).`when`(anchor).x
+ val properties = CFRPopupProperties(
+ popupWidth = 500.dp,
+ popupAlignment = PopupAlignment.BODY_CENTERED_IN_SCREEN,
+ )
+ val popupView = CFRPopupFullscreenLayout(anchor, properties, mock(), { }, { })
+
+ val result = popupView.computePopupHorizontalBounds(
+ anchorMiddleXCoord = Pixels(400),
+ arrowIndicatorWidth = Pixels(20),
+ screenWidth = Pixels(500),
+ layoutDirection = View.LAYOUT_DIRECTION_LTR,
+ )
+
+ assertEquals(16, result.startCoord.value)
+ // The screen width minus the viewport margin
+ assertEquals(484, result.endCoord.value)
+ }
+
+ @Test
+ fun `GIVEN LTR direction and popup fits inside the viewport WHEN computing popup bounds for CENTERED_IN_SCREEN alignment THEN the horizontal bounds are calculated for BODY_TO_ANCHOR_CENTER alignment`() {
+ val anchor = View(testContext)
+ val properties = CFRPopupProperties(
+ popupWidth = 400.dp,
+ popupAlignment = PopupAlignment.BODY_CENTERED_IN_SCREEN,
+ indicatorArrowStartOffset = 0.dp,
+ )
+ val popupView = CFRPopupFullscreenLayout(anchor, properties, mock(), { }, { })
+
+ val result = popupView.computePopupHorizontalBounds(
+ anchorMiddleXCoord = Pixels(200),
+ arrowIndicatorWidth = Pixels(20),
+ screenWidth = Pixels(1000),
+ layoutDirection = View.LAYOUT_DIRECTION_LTR,
+ )
+
+ assertEquals(190, result.startCoord.value)
+ assertEquals(600, result.endCoord.value)
+ }
+
+ @Test
+ fun `GIVEN RTL direction and popup is larger than viewport width WHEN computing popup bounds for CENTERED_IN_SCREEN alignment THEN return the correct horizontal bounds`() {
+ val anchor = spy(View(testContext))
+ doReturn(400).`when`(anchor).width
+ doReturn(200f).`when`(anchor).x
+ val properties = CFRPopupProperties(
+ popupWidth = 500.dp,
+ popupAlignment = PopupAlignment.BODY_CENTERED_IN_SCREEN,
+ )
+ val popupView = CFRPopupFullscreenLayout(anchor, properties, mock(), { }, { })
+
+ val result = popupView.computePopupHorizontalBounds(
+ anchorMiddleXCoord = Pixels(400),
+ arrowIndicatorWidth = Pixels(20),
+ screenWidth = Pixels(500),
+ layoutDirection = View.LAYOUT_DIRECTION_RTL,
+ )
+
+ // The screen width minus the viewport margin
+ assertEquals(484, result.startCoord.value)
+ assertEquals(16, result.endCoord.value)
+ }
+
+ @Test
+ fun `GIVEN RTL direction and popup fits inside the viewport WHEN computing popup bounds for CENTERED_IN_SCREEN alignment THEN the horizontal bounds are calculated for BODY_TO_ANCHOR_CENTER alignment`() {
+ val anchor = View(testContext)
+ val properties = CFRPopupProperties(
+ popupWidth = 400.dp,
+ popupAlignment = PopupAlignment.BODY_CENTERED_IN_SCREEN,
+ indicatorArrowStartOffset = 0.dp,
+ )
+ val popupView = CFRPopupFullscreenLayout(anchor, properties, mock(), { }, { })
+
+ val result = popupView.computePopupHorizontalBounds(
+ anchorMiddleXCoord = Pixels(700),
+ arrowIndicatorWidth = Pixels(20),
+ screenWidth = Pixels(1000),
+ layoutDirection = View.LAYOUT_DIRECTION_RTL,
+ )
+
+ assertEquals(710, result.startCoord.value)
+ assertEquals(300, result.endCoord.value)
+ }
+
+ @OptIn(ExperimentalCoroutinesApi::class)
+ @Test
+ fun `GIVEN there is a CFR Popup showing WHEN the orientation of the device changes THEN the CFR will be dismissed and shown again after a delay`() = runTestOnMain {
+ val context = spy(testContext)
+ val anchor = View(context).apply {
+ setViewTreeLifecycleOwner(mock())
+ this.setViewTreeSavedStateRegistryOwner(mock())
+ }
+ val popupView = spy(CFRPopupFullscreenLayout(anchor, mock(), mock(), { }, { }))
+ popupView.show()
+
+ testContext.resources.configuration.orientation = ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE
+ popupView.orientationChangeListener.onDisplayChanged(1)
+
+ advanceTimeBy(SHOW_AFTER_SCREEN_ORIENTATION_CHANGE_DELAY)
+ verify(popupView, times(1)).dismiss()
+ verify(popupView, times(1)).show()
+ // Test that show() is called the second time after exactly the expected delay.
+ advanceTimeBy(1)
+ verify(popupView, times(2)).show()
+ }
+}
diff --git a/mobile/android/android-components/components/compose/cfr/src/test/java/mozilla/components/compose/cfr/helper/DisplayOrientationListenerTest.kt b/mobile/android/android-components/components/compose/cfr/src/test/java/mozilla/components/compose/cfr/helper/DisplayOrientationListenerTest.kt
new file mode 100644
index 0000000000..5f8a0874e0
--- /dev/null
+++ b/mobile/android/android-components/components/compose/cfr/src/test/java/mozilla/components/compose/cfr/helper/DisplayOrientationListenerTest.kt
@@ -0,0 +1,136 @@
+/* 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 mozilla.components.compose.cfr.helper
+
+import android.content.Context
+import android.content.pm.ActivityInfo
+import android.content.res.Configuration
+import android.content.res.Resources
+import android.hardware.display.DisplayManager
+import android.os.Build
+import android.view.Display
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import mozilla.components.support.test.mock
+import org.junit.Assert.assertEquals
+import org.junit.Assert.assertFalse
+import org.junit.Assert.assertTrue
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.Mockito.doReturn
+import org.mockito.Mockito.verify
+import org.mockito.Mockito.verifyNoInteractions
+import org.robolectric.annotation.Config
+
+@RunWith(AndroidJUnit4::class)
+@Config(sdk = [Build.VERSION_CODES.N])
+class DisplayOrientationListenerTest {
+ private val context: Context = mock()
+ private val displayManager: DisplayManager = mock()
+
+ @Before
+ fun setup() {
+ doReturn(displayManager).`when`(context).getSystemService(Context.DISPLAY_SERVICE)
+
+ val display: Display = mock()
+ doReturn(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT).`when`(display).rotation
+ doReturn(display).`when`(displayManager).getDisplay(0)
+ }
+
+ @Test
+ fun `WHEN started THEN register it as a display listener`() {
+ val listener = DisplayOrientationListener(context) { }
+
+ listener.start()
+
+ verify(displayManager).registerDisplayListener(listener, null)
+ }
+
+ @Test
+ fun `WHEN stopped THEN unregister from being a display listener`() {
+ val listener = DisplayOrientationListener(context) { }
+
+ listener.stop()
+
+ verify(displayManager).unregisterDisplayListener(listener)
+ }
+
+ @Test
+ fun `WHEN a display is added THEN don't inform the client`() {
+ var hasRotationChanged = false
+ val listener = DisplayOrientationListener(context) { hasRotationChanged = true }
+
+ listener.onDisplayAdded(1)
+
+ assertFalse(hasRotationChanged)
+ }
+
+ @Test
+ fun `WHEN a display is removed THEN don't inform the client`() {
+ var hasRotationChanged = false
+ val listener = DisplayOrientationListener(context) { hasRotationChanged = true }
+
+ listener.onDisplayRemoved(1)
+
+ assertFalse(hasRotationChanged)
+ }
+
+ @Test
+ fun `GIVEN display is null WHEN a display is changed THEN don't inform the client`() {
+ val onDisplayRotationChanged = mock<() -> Unit>()
+ val listener = DisplayOrientationListener(context, onDisplayRotationChanged)
+ doReturn(null).`when`(displayManager).getDisplay(1)
+
+ listener.onDisplayChanged(1)
+
+ verifyNoInteractions(onDisplayRotationChanged)
+ }
+
+ @Test
+ fun `WHEN a display is changed but doesn't have a new rotation THEN don't inform the client`() {
+ var hasRotationChanged = false
+ val listener = DisplayOrientationListener(context) { hasRotationChanged = true }
+ val display: Display = mock()
+ doReturn(listener.currentOrientation).`when`(display).rotation
+ doReturn(display).`when`(displayManager).getDisplay(1)
+
+ listener.onDisplayChanged(1)
+
+ assertFalse(hasRotationChanged)
+ }
+
+ @Test
+ fun `GIVEN an old Android version WHEN a display is changed and has a new rotation THEN inform the client and remember the new rotation`() {
+ var hasRotationChanged = false
+ val listener = DisplayOrientationListener(context) { hasRotationChanged = true }
+ val display: Display = mock()
+ doReturn(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE).`when`(display).rotation
+ doReturn(display).`when`(displayManager).getDisplay(1)
+
+ listener.onDisplayChanged(1)
+
+ assertTrue(hasRotationChanged)
+ assertEquals(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE, listener.currentOrientation)
+ }
+
+ @Test
+ @Config(sdk = [Build.VERSION_CODES.S])
+ fun `GIVEN a new Android version WHEN a display is changed and has a new rotation THEN inform the client and remember the new rotation`() {
+ var hasRotationChanged = false
+ val config = Configuration().apply {
+ orientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT
+ }
+ val resources: Resources = mock()
+ doReturn(config).`when`(resources).configuration
+ doReturn(resources).`when`(context).resources
+ val listener = DisplayOrientationListener(context) { hasRotationChanged = true }
+
+ config.orientation = ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE
+ listener.onDisplayChanged(1)
+
+ assertTrue(hasRotationChanged)
+ assertEquals(ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE, listener.currentOrientation)
+ }
+}
diff --git a/mobile/android/android-components/components/compose/cfr/src/test/java/mozilla/components/compose/cfr/helper/ViewDetachedListenerTest.kt b/mobile/android/android-components/components/compose/cfr/src/test/java/mozilla/components/compose/cfr/helper/ViewDetachedListenerTest.kt
new file mode 100644
index 0000000000..bb6467f44c
--- /dev/null
+++ b/mobile/android/android-components/components/compose/cfr/src/test/java/mozilla/components/compose/cfr/helper/ViewDetachedListenerTest.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 mozilla.components.compose.cfr.helper
+
+import mozilla.components.support.test.mock
+import org.junit.Assert.assertFalse
+import org.junit.Assert.assertTrue
+import org.junit.Test
+
+class ViewDetachedListenerTest {
+ @Test
+ fun `WHEN the View is attached THEN don't inform the client`() {
+ var wasCallbackCalled = false
+ val listener = ViewDetachedListener { wasCallbackCalled = true }
+
+ listener.onViewAttachedToWindow(mock())
+
+ assertFalse(wasCallbackCalled)
+ }
+
+ @Test
+ fun `WHEN the View is detached THEN don't inform the client`() {
+ var wasCallbackCalled = false
+ val listener = ViewDetachedListener { wasCallbackCalled = true }
+
+ listener.onViewDetachedFromWindow(mock())
+
+ assertTrue(wasCallbackCalled)
+ }
+}
diff --git a/mobile/android/android-components/components/compose/cfr/src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker b/mobile/android/android-components/components/compose/cfr/src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker
new file mode 100644
index 0000000000..cf1c399ea8
--- /dev/null
+++ b/mobile/android/android-components/components/compose/cfr/src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker
@@ -0,0 +1,2 @@
+mock-maker-inline
+// This allows mocking final classes (classes are final by default in Kotlin)
diff --git a/mobile/android/android-components/components/compose/engine/README.md b/mobile/android/android-components/components/compose/engine/README.md
new file mode 100644
index 0000000000..4ea4cd1be2
--- /dev/null
+++ b/mobile/android/android-components/components/compose/engine/README.md
@@ -0,0 +1,19 @@
+# [Android Components](../../../README.md) > Compose > Engine
+
+A component for integrating a `concept-engine` implementation into Jetpack Compose UI.
+
+## Usage
+
+### Setting up the dependency
+
+Use Gradle to download the library from [maven.mozilla.org](https://maven.mozilla.org/) ([Setup repository](../../../README.md#maven-repository)):
+
+```Groovy
+implementation "org.mozilla.components:compose-engine:{latest-version}"
+```
+
+## License
+
+ 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/
diff --git a/mobile/android/android-components/components/compose/engine/build.gradle b/mobile/android/android-components/components/compose/engine/build.gradle
new file mode 100644
index 0000000000..5bbeb6d699
--- /dev/null
+++ b/mobile/android/android-components/components/compose/engine/build.gradle
@@ -0,0 +1,61 @@
+/* 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/. */
+
+apply plugin: 'com.android.library'
+apply plugin: 'kotlin-android'
+
+android {
+ defaultConfig {
+ minSdkVersion config.minSdkVersion
+ compileSdk config.compileSdkVersion
+ targetSdkVersion config.targetSdkVersion
+
+ testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
+ }
+
+ buildTypes {
+ release {
+ minifyEnabled false
+ proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
+ }
+ }
+
+ buildFeatures {
+ compose true
+ }
+
+ composeOptions {
+ kotlinCompilerExtensionVersion = Versions.compose_compiler
+ }
+
+ namespace 'mozilla.components.compose.engine'
+}
+
+dependencies {
+ implementation project(":browser-state")
+ implementation project(":concept-engine")
+ implementation project(":support-ktx")
+
+ implementation ComponentsDependencies.androidx_compose_ui
+ implementation ComponentsDependencies.androidx_compose_ui_tooling_preview
+ implementation ComponentsDependencies.androidx_compose_foundation
+ implementation ComponentsDependencies.androidx_compose_material
+
+ debugImplementation ComponentsDependencies.androidx_compose_ui_tooling
+
+ testImplementation project(':support-test')
+ testImplementation ComponentsDependencies.androidx_compose_ui_test
+ testImplementation ComponentsDependencies.androidx_test_core
+ testImplementation ComponentsDependencies.androidx_test_junit
+ testImplementation ComponentsDependencies.testing_robolectric
+
+ androidTestImplementation ComponentsDependencies.androidx_test_junit
+ androidTestImplementation ComponentsDependencies.androidx_compose_ui_test_manifest
+ androidTestImplementation ComponentsDependencies.androidx_compose_ui_test
+ androidTestImplementation ComponentsDependencies.testing_mockito
+}
+
+apply from: '../../../android-lint.gradle'
+apply from: '../../../publish.gradle'
+ext.configurePublish(config.componentsGroupId, archivesBaseName, project.ext.description)
diff --git a/mobile/android/android-components/components/compose/engine/proguard-rules.pro b/mobile/android/android-components/components/compose/engine/proguard-rules.pro
new file mode 100644
index 0000000000..f1b424510d
--- /dev/null
+++ b/mobile/android/android-components/components/compose/engine/proguard-rules.pro
@@ -0,0 +1,21 @@
+# Add project specific ProGuard rules here.
+# You can control the set of applied configuration files using the
+# proguardFiles setting in build.gradle.
+#
+# For more details, see
+# http://developer.android.com/guide/developing/tools/proguard.html
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+# public *;
+#}
+
+# Uncomment this to preserve the line number information for
+# debugging stack traces.
+#-keepattributes SourceFile,LineNumberTable
+
+# If you keep the line number information, uncomment this to
+# hide the original source file name.
+#-renamesourcefileattribute SourceFile
diff --git a/mobile/android/android-components/components/compose/engine/src/main/AndroidManifest.xml b/mobile/android/android-components/components/compose/engine/src/main/AndroidManifest.xml
new file mode 100644
index 0000000000..e16cda1d34
--- /dev/null
+++ b/mobile/android/android-components/components/compose/engine/src/main/AndroidManifest.xml
@@ -0,0 +1,4 @@
+<!-- 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/. -->
+<manifest />
diff --git a/mobile/android/android-components/components/compose/engine/src/main/java/mozilla/components/compose/engine/WebContent.kt b/mobile/android/android-components/components/compose/engine/src/main/java/mozilla/components/compose/engine/WebContent.kt
new file mode 100644
index 0000000000..0d2bfb02f1
--- /dev/null
+++ b/mobile/android/android-components/components/compose/engine/src/main/java/mozilla/components/compose/engine/WebContent.kt
@@ -0,0 +1,62 @@
+/* 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 mozilla.components.compose.engine
+
+import androidx.compose.foundation.layout.fillMaxSize
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.viewinterop.AndroidView
+import mozilla.components.browser.state.action.EngineAction
+import mozilla.components.browser.state.helper.Target
+import mozilla.components.browser.state.store.BrowserStore
+import mozilla.components.concept.engine.Engine
+import mozilla.components.concept.engine.EngineView
+
+/**
+ * Composes an [EngineView] obtained from the given [Engine] and renders the web content of the
+ * [target] from the [store] on it.
+ */
+@Composable
+fun WebContent(
+ engine: Engine,
+ store: BrowserStore,
+ target: Target,
+) {
+ val selectedTab = target.observeAsComposableStateFrom(
+ store = store,
+ observe = { tab ->
+ // Render if the tab itself changed or when the state of the linked engine session changes
+ arrayOf(
+ tab?.id,
+ tab?.engineState?.engineSession,
+ tab?.engineState?.crashed,
+ tab?.content?.firstContentfulPaint,
+ )
+ },
+ )
+
+ AndroidView(
+ modifier = Modifier.fillMaxSize(),
+ factory = { context -> engine.createView(context).asView() },
+ update = { view ->
+ val engineView = view as EngineView
+
+ val tab = selectedTab.value
+ if (tab == null) {
+ engineView.release()
+ } else {
+ val session = tab.engineState.engineSession
+ if (session == null) {
+ // This tab does not have an EngineSession that we can render yet. Let's dispatch an
+ // action to request creating one. Once one was created and linked to this session, this
+ // method will get invoked again.
+ store.dispatch(EngineAction.CreateEngineSessionAction(tab.id))
+ } else {
+ engineView.render(session)
+ }
+ }
+ },
+ )
+}
diff --git a/mobile/android/android-components/components/compose/engine/src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker b/mobile/android/android-components/components/compose/engine/src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker
new file mode 100644
index 0000000000..cf1c399ea8
--- /dev/null
+++ b/mobile/android/android-components/components/compose/engine/src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker
@@ -0,0 +1,2 @@
+mock-maker-inline
+// This allows mocking final classes (classes are final by default in Kotlin)
diff --git a/mobile/android/android-components/components/compose/engine/src/test/resources/robolectric.properties b/mobile/android/android-components/components/compose/engine/src/test/resources/robolectric.properties
new file mode 100644
index 0000000000..932b01b9eb
--- /dev/null
+++ b/mobile/android/android-components/components/compose/engine/src/test/resources/robolectric.properties
@@ -0,0 +1 @@
+sdk=28
diff --git a/mobile/android/android-components/components/compose/tabstray/README.md b/mobile/android/android-components/components/compose/tabstray/README.md
new file mode 100644
index 0000000000..6a70022ee0
--- /dev/null
+++ b/mobile/android/android-components/components/compose/tabstray/README.md
@@ -0,0 +1,19 @@
+# [Android Components](../../../README.md) > Compose > Tabs tray
+
+A customizable tabs tray using Jetpack Compose.
+
+## Usage
+
+### Setting up the dependency
+
+Use Gradle to download the library from [maven.mozilla.org](https://maven.mozilla.org/) ([Setup repository](../../../README.md#maven-repository)):
+
+```Groovy
+implementation "org.mozilla.components:compose-tabstray:{latest-version}"
+```
+
+## License
+
+ 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/
diff --git a/mobile/android/android-components/components/compose/tabstray/build.gradle b/mobile/android/android-components/components/compose/tabstray/build.gradle
new file mode 100644
index 0000000000..1b12b0ac53
--- /dev/null
+++ b/mobile/android/android-components/components/compose/tabstray/build.gradle
@@ -0,0 +1,58 @@
+/* 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/. */
+
+apply plugin: 'com.android.library'
+apply plugin: 'kotlin-android'
+
+android {
+ defaultConfig {
+ minSdkVersion config.minSdkVersion
+ compileSdk config.compileSdkVersion
+ targetSdkVersion config.targetSdkVersion
+ }
+
+ buildTypes {
+ release {
+ minifyEnabled false
+ proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
+ }
+ }
+
+ buildFeatures {
+ compose true
+ }
+
+ composeOptions {
+ kotlinCompilerExtensionVersion = Versions.compose_compiler
+ }
+
+ namespace 'mozilla.components.compose.browser.tabstray'
+}
+
+dependencies {
+ implementation project(":concept-tabstray")
+
+ implementation project(":browser-state")
+
+ implementation project(":ui-icons")
+
+ implementation project(":feature-tabs")
+
+ implementation ComponentsDependencies.androidx_compose_ui
+ implementation ComponentsDependencies.androidx_compose_ui_tooling_preview
+ implementation ComponentsDependencies.androidx_compose_foundation
+ implementation ComponentsDependencies.androidx_compose_material
+
+ debugImplementation ComponentsDependencies.androidx_compose_ui_tooling
+
+ testImplementation project(':support-test')
+ testImplementation ComponentsDependencies.androidx_compose_ui_test
+ testImplementation ComponentsDependencies.androidx_test_core
+ testImplementation ComponentsDependencies.androidx_test_junit
+ testImplementation ComponentsDependencies.testing_robolectric
+}
+
+apply from: '../../../android-lint.gradle'
+apply from: '../../../publish.gradle'
+ext.configurePublish(config.componentsGroupId, archivesBaseName, project.ext.description)
diff --git a/mobile/android/android-components/components/compose/tabstray/proguard-rules.pro b/mobile/android/android-components/components/compose/tabstray/proguard-rules.pro
new file mode 100644
index 0000000000..f1b424510d
--- /dev/null
+++ b/mobile/android/android-components/components/compose/tabstray/proguard-rules.pro
@@ -0,0 +1,21 @@
+# Add project specific ProGuard rules here.
+# You can control the set of applied configuration files using the
+# proguardFiles setting in build.gradle.
+#
+# For more details, see
+# http://developer.android.com/guide/developing/tools/proguard.html
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+# public *;
+#}
+
+# Uncomment this to preserve the line number information for
+# debugging stack traces.
+#-keepattributes SourceFile,LineNumberTable
+
+# If you keep the line number information, uncomment this to
+# hide the original source file name.
+#-renamesourcefileattribute SourceFile
diff --git a/mobile/android/android-components/components/compose/tabstray/src/main/AndroidManifest.xml b/mobile/android/android-components/components/compose/tabstray/src/main/AndroidManifest.xml
new file mode 100644
index 0000000000..e16cda1d34
--- /dev/null
+++ b/mobile/android/android-components/components/compose/tabstray/src/main/AndroidManifest.xml
@@ -0,0 +1,4 @@
+<!-- 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/. -->
+<manifest />
diff --git a/mobile/android/android-components/components/compose/tabstray/src/main/java/mozilla/components/compose/tabstray/Tab.kt b/mobile/android/android-components/components/compose/tabstray/src/main/java/mozilla/components/compose/tabstray/Tab.kt
new file mode 100644
index 0000000000..20801e0609
--- /dev/null
+++ b/mobile/android/android-components/components/compose/tabstray/src/main/java/mozilla/components/compose/tabstray/Tab.kt
@@ -0,0 +1,97 @@
+/* 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 mozilla.components.compose.tabstray
+
+import androidx.compose.foundation.background
+import androidx.compose.foundation.clickable
+import androidx.compose.foundation.layout.Arrangement
+import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.layout.Column
+import androidx.compose.foundation.layout.Row
+import androidx.compose.foundation.layout.fillMaxWidth
+import androidx.compose.foundation.layout.padding
+import androidx.compose.foundation.layout.requiredSize
+import androidx.compose.foundation.layout.size
+import androidx.compose.material.ContentAlpha
+import androidx.compose.material.Icon
+import androidx.compose.material.IconButton
+import androidx.compose.material.MaterialTheme
+import androidx.compose.material.Text
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.Alignment
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.res.painterResource
+import androidx.compose.ui.text.font.FontWeight
+import androidx.compose.ui.text.style.TextOverflow
+import androidx.compose.ui.unit.Dp
+import androidx.compose.ui.unit.dp
+import mozilla.components.browser.state.state.TabSessionState
+import mozilla.components.ui.icons.R
+
+/**
+ * Renders a single [TabSessionState] as a list item.
+ *
+ * @param tab The tab to render.
+ * @param selected Whether this tab is selected or not.
+ * @param onClick Gets invoked when the tab gets clicked.
+ * @param onClose Gets invoked when tab gets closed.
+ */
+@Composable
+fun Tab(
+ tab: TabSessionState,
+ selected: Boolean = false,
+ onClick: (String) -> Unit = {},
+ onClose: (String) -> Unit = {},
+) {
+ Box(
+ modifier = Modifier
+ .background(if (selected) Color(0xFFFF45A1FF.toInt()) else Color.Unspecified)
+ .size(width = Dp.Unspecified, height = 72.dp)
+ .fillMaxWidth()
+ .clickable { onClick.invoke(tab.id) }
+ .padding(8.dp),
+ ) {
+ Row(
+ modifier = Modifier.fillMaxWidth(),
+ horizontalArrangement = Arrangement.SpaceAround,
+ ) {
+ // BrowserThumbnail(tab)
+ Column(
+ modifier = Modifier
+ .weight(1f)
+ .align(Alignment.CenterVertically)
+ .padding(8.dp),
+ ) {
+ Text(
+ text = tab.content.title,
+ fontWeight = FontWeight.Bold,
+ overflow = TextOverflow.Ellipsis,
+ maxLines = 1,
+ color = Color.White,
+ )
+ Text(
+ text = tab.content.url,
+ style = MaterialTheme.typography.body2,
+ overflow = TextOverflow.Ellipsis,
+ maxLines = 1,
+ color = Color.White.copy(alpha = ContentAlpha.medium),
+ )
+ }
+ IconButton(
+ modifier = Modifier
+ .align(Alignment.CenterVertically)
+ .requiredSize(24.dp),
+ onClick = { onClose.invoke(tab.id) },
+ ) {
+ Icon(
+ painter = painterResource(R.drawable.mozac_ic_cross_24),
+ contentDescription = "close",
+ tint = Color.White,
+ )
+ }
+ }
+ }
+}
diff --git a/mobile/android/android-components/components/compose/tabstray/src/main/java/mozilla/components/compose/tabstray/TabCounterButton.kt b/mobile/android/android-components/components/compose/tabstray/src/main/java/mozilla/components/compose/tabstray/TabCounterButton.kt
new file mode 100644
index 0000000000..2f73136d7a
--- /dev/null
+++ b/mobile/android/android-components/components/compose/tabstray/src/main/java/mozilla/components/compose/tabstray/TabCounterButton.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 mozilla.components.compose.tabstray
+
+import androidx.compose.foundation.Image
+import androidx.compose.material.IconButton
+import androidx.compose.material.MaterialTheme
+import androidx.compose.material.Text
+import androidx.compose.material.contentColorFor
+import androidx.compose.material.primarySurface
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.graphics.ColorFilter
+import androidx.compose.ui.res.painterResource
+import androidx.compose.ui.res.stringResource
+import androidx.compose.ui.unit.sp
+import mozilla.components.browser.state.state.TabSessionState
+import mozilla.components.browser.state.store.BrowserStore
+import mozilla.components.compose.browser.tabstray.R
+import mozilla.components.lib.state.ext.observeAsComposableState
+
+private const val MAX_VISIBLE_TABS = 99
+private const val SO_MANY_TABS_OPEN = "∞"
+
+/**
+ * A button showing the count of tabs in the [store] using the provided [tabsFilter].
+ *
+ * @param store The store to observe.
+ * @param onClicked Gets invoked when the user clicks the button.
+ * @param tabsFilter Used for filtering the list of tabs.
+ */
+@Composable
+fun TabCounterButton(
+ store: BrowserStore,
+ onClicked: () -> Unit,
+ tabsFilter: (TabSessionState) -> Boolean = { true },
+) {
+ IconButton(
+ onClick = onClicked,
+ ) {
+ val backgroundColor = MaterialTheme.colors.primarySurface
+ val foregroundColor = contentColorFor(backgroundColor)
+ val tabs = store.observeAsComposableState { state -> state.tabs.filter(tabsFilter) }
+ val count = tabs.value?.size ?: 0
+
+ Image(
+ painter = painterResource(R.drawable.mozac_tabcounter_background),
+ contentDescription = createContentDescription(count),
+ colorFilter = ColorFilter.tint(foregroundColor),
+ )
+
+ Text(
+ createButtonText(count),
+ fontSize = 12.sp,
+ color = foregroundColor,
+ )
+ }
+}
+
+private fun createButtonText(count: Int): String {
+ return if (count > MAX_VISIBLE_TABS) {
+ SO_MANY_TABS_OPEN
+ } else {
+ count.toString()
+ }
+}
+
+@Composable
+private fun createContentDescription(count: Int): String {
+ return if (count == 1) {
+ stringResource(R.string.mozac_tab_counter_open_tab_tray_single)
+ } else {
+ String.format(
+ stringResource(R.string.mozac_tab_counter_open_tab_tray_plural),
+ count.toString(),
+ )
+ }
+}
diff --git a/mobile/android/android-components/components/compose/tabstray/src/main/java/mozilla/components/compose/tabstray/TabList.kt b/mobile/android/android-components/components/compose/tabstray/src/main/java/mozilla/components/compose/tabstray/TabList.kt
new file mode 100644
index 0000000000..e862854687
--- /dev/null
+++ b/mobile/android/android-components/components/compose/tabstray/src/main/java/mozilla/components/compose/tabstray/TabList.kt
@@ -0,0 +1,77 @@
+/* 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 mozilla.components.compose.tabstray
+
+import androidx.compose.foundation.background
+import androidx.compose.foundation.layout.fillMaxWidth
+import androidx.compose.foundation.lazy.LazyColumn
+import androidx.compose.foundation.lazy.items
+import androidx.compose.material.MaterialTheme
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.Modifier
+import mozilla.components.browser.state.state.TabSessionState
+import mozilla.components.browser.state.store.BrowserStore
+import mozilla.components.lib.state.ext.observeAsComposableState
+
+/**
+ * Renders a list of tabs from the given [store], using the provided [tabsFilter].
+ *
+ * @param store The store to observe.
+ * @param modifier The modifier to apply to this layout.
+ * @param tabsFilter Used to filter the list of tabs from the [store].
+ * @param onTabClosed Gets invoked when the user closes a tab.
+ * @param onTabSelected Gets invoked when the user selects a tab.
+ */
+@Composable
+fun TabList(
+ store: BrowserStore,
+ modifier: Modifier = Modifier,
+ tabsFilter: (TabSessionState) -> Boolean = { true },
+ onTabSelected: (TabSessionState) -> Unit = {},
+ onTabClosed: (TabSessionState) -> Unit = {},
+) {
+ val tabs = store.observeAsComposableState { state -> state.tabs.filter(tabsFilter) }
+ val selectedTabId = store.observeAsComposableState { state -> state.selectedTabId }
+ TabList(
+ tabs.value ?: emptyList(),
+ modifier,
+ selectedTabId.value,
+ onTabSelected,
+ onTabClosed,
+ )
+}
+
+/**
+ * Renders the given list of [tabs].
+ *
+ * @param tabs The list of tabs to render.
+ * @param selectedTabId the currently selected tab ID.
+ * @param modifier The modifier to apply to this layout.
+ * @param onTabClosed Gets invoked when the user closes a tab.
+ * @param onTabSelected Gets invoked when the user selects a tab.
+ */
+@Composable
+fun TabList(
+ tabs: List<TabSessionState>,
+ modifier: Modifier = Modifier,
+ selectedTabId: String? = null,
+ onTabSelected: (TabSessionState) -> Unit,
+ onTabClosed: (TabSessionState) -> Unit,
+) {
+ LazyColumn(
+ modifier = modifier
+ .fillMaxWidth()
+ .background(MaterialTheme.colors.surface),
+ ) {
+ items(tabs) { tab ->
+ Tab(
+ tab,
+ selected = selectedTabId == tab.id,
+ onClick = { onTabSelected(tab) },
+ onClose = { onTabClosed(tab) },
+ )
+ }
+ }
+}
diff --git a/mobile/android/android-components/components/compose/tabstray/src/main/res/drawable/mozac_tabcounter_background.xml b/mobile/android/android-components/components/compose/tabstray/src/main/res/drawable/mozac_tabcounter_background.xml
new file mode 100644
index 0000000000..489efcb568
--- /dev/null
+++ b/mobile/android/android-components/components/compose/tabstray/src/main/res/drawable/mozac_tabcounter_background.xml
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- This Source Code Form is subject to the terms of the Mozilla Public
+ - License, v. 2.0. If a copy of the MPL was not distributed with this
+ - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
+
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+<path
+ android:pathData="M4.5,4A2.5,2.5 0,0 0,2 6.5v11A2.5,2.5 0,0 0,4.5 20h15a2.5,2.5 0,0 0,2.5 -2.5v-11A2.5,2.5 0,0 0,19.5 4h-15zM20.5,17.7 L19.7,18.5L4.3,18.5l-0.8,-0.8L3.5,6.3l0.8,-0.8h15.4l0.8,0.8v11.4z"
+ android:strokeWidth="1"
+ android:fillColor="@color/mozac_ui_tabcounter_default_tint"/>
+</vector>
diff --git a/mobile/android/android-components/components/compose/tabstray/src/main/res/values-am/strings.xml b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-am/strings.xml
new file mode 100644
index 0000000000..5cb872a827
--- /dev/null
+++ b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-am/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Message announced to the user when tab tray is selected with 1 tab -->
+ <string name="mozac_tab_counter_open_tab_tray_single">1 ትር ክፈት። ትሮችን ለመቀየር መታ ያድርጉ።</string>
+ <!-- Message announced to the user when tab tray is selected with multiple tabs. %1$s is getting replaced with the number of open tabs. -->
+ <string name="mozac_tab_counter_open_tab_tray_plural">%1$s ትሮች ክፍት። ትሮችን ለመቀየር መታ ያድርጉ።</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/tabstray/src/main/res/values-ar/strings.xml b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-ar/strings.xml
new file mode 100644
index 0000000000..bbd8b69682
--- /dev/null
+++ b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-ar/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Message announced to the user when tab tray is selected with 1 tab -->
+ <string name="mozac_tab_counter_open_tab_tray_single">لسان واحد مفتوح. انقر لتبديل الألسنة.</string>
+ <!-- Message announced to the user when tab tray is selected with multiple tabs. %1$s is getting replaced with the number of open tabs. -->
+ <string name="mozac_tab_counter_open_tab_tray_plural">%1$s من الألسنة مفتوح. انقر لتبديل الألسنة.</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/tabstray/src/main/res/values-ast/strings.xml b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-ast/strings.xml
new file mode 100644
index 0000000000..966c990739
--- /dev/null
+++ b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-ast/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Message announced to the user when tab tray is selected with 1 tab -->
+ <string name="mozac_tab_counter_open_tab_tray_single">1 llingüeta abierta. Toca pa cambiar de llingüeta.</string>
+ <!-- Message announced to the user when tab tray is selected with multiple tabs. %1$s is getting replaced with the number of open tabs. -->
+ <string name="mozac_tab_counter_open_tab_tray_plural">%1$s llingüetes abiertes. Toca pa cambiar de llingüeta.</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/tabstray/src/main/res/values-azb/strings.xml b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-azb/strings.xml
new file mode 100644
index 0000000000..acc68b47f3
--- /dev/null
+++ b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-azb/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Message announced to the user when tab tray is selected with 1 tab -->
+ <string name="mozac_tab_counter_open_tab_tray_single">آچیق سئکمه. سئکمه‌لری دگیشدیرمک اوچون توخونون.</string>
+ <!-- Message announced to the user when tab tray is selected with multiple tabs. %1$s is getting replaced with the number of open tabs. -->
+ <string name="mozac_tab_counter_open_tab_tray_plural">%1$s آچیق سئکمه‌. دگیشدیرمک اوچون توخونون.</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/tabstray/src/main/res/values-be/strings.xml b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-be/strings.xml
new file mode 100644
index 0000000000..3a96d5f1ce
--- /dev/null
+++ b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-be/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Message announced to the user when tab tray is selected with 1 tab -->
+ <string name="mozac_tab_counter_open_tab_tray_single">1 адкрытая картка. Націсніце, каб пераключыць карткі.</string>
+ <!-- Message announced to the user when tab tray is selected with multiple tabs. %1$s is getting replaced with the number of open tabs. -->
+ <string name="mozac_tab_counter_open_tab_tray_plural">Адкрытых картак: %1$s. Націсніце, каб пераключыць карткі.</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/tabstray/src/main/res/values-bg/strings.xml b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-bg/strings.xml
new file mode 100644
index 0000000000..14638b0375
--- /dev/null
+++ b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-bg/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Message announced to the user when tab tray is selected with 1 tab -->
+ <string name="mozac_tab_counter_open_tab_tray_single">1 отворен раздел. Докоснете, за да превключите разделите.</string>
+ <!-- Message announced to the user when tab tray is selected with multiple tabs. %1$s is getting replaced with the number of open tabs. -->
+ <string name="mozac_tab_counter_open_tab_tray_plural">%1$s отворени раздела. Докоснете, за да превключите разделите.</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/tabstray/src/main/res/values-br/strings.xml b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-br/strings.xml
new file mode 100644
index 0000000000..9d8952f911
--- /dev/null
+++ b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-br/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Message announced to the user when tab tray is selected with 1 tab -->
+ <string name="mozac_tab_counter_open_tab_tray_single">1 ivinell digor. Pouezit evit cheñch ivinell.</string>
+ <!-- Message announced to the user when tab tray is selected with multiple tabs. %1$s is getting replaced with the number of open tabs. -->
+ <string name="mozac_tab_counter_open_tab_tray_plural">%1$s ivinell digor. Pouezit evit cheñch ivinell.</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/tabstray/src/main/res/values-bs/strings.xml b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-bs/strings.xml
new file mode 100644
index 0000000000..7d1b51b3f4
--- /dev/null
+++ b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-bs/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Message announced to the user when tab tray is selected with 1 tab -->
+ <string name="mozac_tab_counter_open_tab_tray_single">1 otvoren tab. Dodirnite za promjenu tabova.</string>
+ <!-- Message announced to the user when tab tray is selected with multiple tabs. %1$s is getting replaced with the number of open tabs. -->
+ <string name="mozac_tab_counter_open_tab_tray_plural">%1$s otvorenih tabova. Dodirnite za promjenu tabova.</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/tabstray/src/main/res/values-ca/strings.xml b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-ca/strings.xml
new file mode 100644
index 0000000000..5dbcca54f0
--- /dev/null
+++ b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-ca/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Message announced to the user when tab tray is selected with 1 tab -->
+ <string name="mozac_tab_counter_open_tab_tray_single">1 pestanya oberta. Toqueu per canviar de pestanya.</string>
+ <!-- Message announced to the user when tab tray is selected with multiple tabs. %1$s is getting replaced with the number of open tabs. -->
+ <string name="mozac_tab_counter_open_tab_tray_plural">%1$s pestanyes obertes. Toqueu per canviar de pestanya.</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/tabstray/src/main/res/values-cak/strings.xml b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-cak/strings.xml
new file mode 100644
index 0000000000..cb7c638e0c
--- /dev/null
+++ b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-cak/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Message announced to the user when tab tray is selected with 1 tab -->
+ <string name="mozac_tab_counter_open_tab_tray_single">1 ruwi\' jaqon. Tachapa\' richin nak\'ëx ruwi\'.</string>
+ <!-- Message announced to the user when tab tray is selected with multiple tabs. %1$s is getting replaced with the number of open tabs. -->
+ <string name="mozac_tab_counter_open_tab_tray_plural">%1$s ruwi\' ejaqon. Tachapa\' richin nak\'ëx ruwi\'.</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/tabstray/src/main/res/values-ceb/strings.xml b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-ceb/strings.xml
new file mode 100644
index 0000000000..26943c382c
--- /dev/null
+++ b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-ceb/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Message announced to the user when tab tray is selected with 1 tab -->
+ <string name="mozac_tab_counter_open_tab_tray_single">1 ang abli nga tab. i-Tap para mobalhin ug mga tab.</string>
+ <!-- Message announced to the user when tab tray is selected with multiple tabs. %1$s is getting replaced with the number of open tabs. -->
+ <string name="mozac_tab_counter_open_tab_tray_plural">%1$s ang abli nga mga tab. i-Tap para mobalhin ug mga tab.</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/tabstray/src/main/res/values-ckb/strings.xml b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-ckb/strings.xml
new file mode 100644
index 0000000000..7152d88845
--- /dev/null
+++ b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-ckb/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Message announced to the user when tab tray is selected with 1 tab -->
+ <string name="mozac_tab_counter_open_tab_tray_single">١ بازدەر کراوەیە. پەنجەدابگرە بۆ گۆڕینی بازدەرەکان.</string>
+ <!-- Message announced to the user when tab tray is selected with multiple tabs. %1$s is getting replaced with the number of open tabs. -->
+ <string name="mozac_tab_counter_open_tab_tray_plural">%1$s بازدەر کراوەیە. پەنجەدابگرە بۆ گۆڕینی بازدەرەکان.</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/tabstray/src/main/res/values-co/strings.xml b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-co/strings.xml
new file mode 100644
index 0000000000..4c1798bd68
--- /dev/null
+++ b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-co/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Message announced to the user when tab tray is selected with 1 tab -->
+ <string name="mozac_tab_counter_open_tab_tray_single">1 unghjetta aperta. Picchichjà per cambià d’unghjetta.</string>
+ <!-- Message announced to the user when tab tray is selected with multiple tabs. %1$s is getting replaced with the number of open tabs. -->
+ <string name="mozac_tab_counter_open_tab_tray_plural">%1$s unghjette aperte. Picchichjà per cambià d’unghjetta.</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/tabstray/src/main/res/values-cs/strings.xml b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-cs/strings.xml
new file mode 100644
index 0000000000..cb7c806931
--- /dev/null
+++ b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-cs/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Message announced to the user when tab tray is selected with 1 tab -->
+ <string name="mozac_tab_counter_open_tab_tray_single">Jeden otevřený panel. Klepnutím panely přepnete.</string>
+ <!-- Message announced to the user when tab tray is selected with multiple tabs. %1$s is getting replaced with the number of open tabs. -->
+ <string name="mozac_tab_counter_open_tab_tray_plural">%1$s otevřených panelů. Klepnutím přepnete panely.</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/tabstray/src/main/res/values-cy/strings.xml b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-cy/strings.xml
new file mode 100644
index 0000000000..77d02443e7
--- /dev/null
+++ b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-cy/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Message announced to the user when tab tray is selected with 1 tab -->
+ <string name="mozac_tab_counter_open_tab_tray_single">1 tab ar agor. Tapio i newid tabiau.</string>
+ <!-- Message announced to the user when tab tray is selected with multiple tabs. %1$s is getting replaced with the number of open tabs. -->
+ <string name="mozac_tab_counter_open_tab_tray_plural">%1$s tab ar agor. Tapio i newid tabiau.</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/tabstray/src/main/res/values-da/strings.xml b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-da/strings.xml
new file mode 100644
index 0000000000..ac794bbf47
--- /dev/null
+++ b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-da/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Message announced to the user when tab tray is selected with 1 tab -->
+ <string name="mozac_tab_counter_open_tab_tray_single">1 åbent faneblad. Tryk for at skifte faneblade.</string>
+ <!-- Message announced to the user when tab tray is selected with multiple tabs. %1$s is getting replaced with the number of open tabs. -->
+ <string name="mozac_tab_counter_open_tab_tray_plural">%1$s åbne faneblade. Tryk for at skifte faneblade.</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/tabstray/src/main/res/values-de/strings.xml b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-de/strings.xml
new file mode 100644
index 0000000000..704e927f0e
--- /dev/null
+++ b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-de/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Message announced to the user when tab tray is selected with 1 tab -->
+ <string name="mozac_tab_counter_open_tab_tray_single">1 offener Tab. Antippen, um Tabs zu wechseln.</string>
+ <!-- Message announced to the user when tab tray is selected with multiple tabs. %1$s is getting replaced with the number of open tabs. -->
+ <string name="mozac_tab_counter_open_tab_tray_plural">%1$s offene Tabs. Antippen, um Tabs zu wechseln.</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/tabstray/src/main/res/values-dsb/strings.xml b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-dsb/strings.xml
new file mode 100644
index 0000000000..afb4eb2be2
--- /dev/null
+++ b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-dsb/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Message announced to the user when tab tray is selected with 1 tab -->
+ <string name="mozac_tab_counter_open_tab_tray_single">1 wócynjony rejtarik. Pótusniśo, aby rejtariki pśešaltował.</string>
+ <!-- Message announced to the user when tab tray is selected with multiple tabs. %1$s is getting replaced with the number of open tabs. -->
+ <string name="mozac_tab_counter_open_tab_tray_plural">Wócynjone rejtariki: %1$s. Pótusniśo, aby rejtariki pśešaltował.</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/tabstray/src/main/res/values-el/strings.xml b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-el/strings.xml
new file mode 100644
index 0000000000..f25b3f5377
--- /dev/null
+++ b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-el/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Message announced to the user when tab tray is selected with 1 tab -->
+ <string name="mozac_tab_counter_open_tab_tray_single">1 ανοικτή καρτέλα. Πατήστε για εναλλαγή καρτελών.</string>
+ <!-- Message announced to the user when tab tray is selected with multiple tabs. %1$s is getting replaced with the number of open tabs. -->
+ <string name="mozac_tab_counter_open_tab_tray_plural">%1$s ανοικτές καρτέλες. Πατήστε για εναλλαγή καρτελών.</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/tabstray/src/main/res/values-en-rCA/strings.xml b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-en-rCA/strings.xml
new file mode 100644
index 0000000000..4ca62a8c45
--- /dev/null
+++ b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-en-rCA/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Message announced to the user when tab tray is selected with 1 tab -->
+ <string name="mozac_tab_counter_open_tab_tray_single">1 open tab. Tap to switch tabs.</string>
+ <!-- Message announced to the user when tab tray is selected with multiple tabs. %1$s is getting replaced with the number of open tabs. -->
+ <string name="mozac_tab_counter_open_tab_tray_plural">%1$s open tabs. Tap to switch tabs.</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/tabstray/src/main/res/values-en-rGB/strings.xml b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-en-rGB/strings.xml
new file mode 100644
index 0000000000..4ca62a8c45
--- /dev/null
+++ b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-en-rGB/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Message announced to the user when tab tray is selected with 1 tab -->
+ <string name="mozac_tab_counter_open_tab_tray_single">1 open tab. Tap to switch tabs.</string>
+ <!-- Message announced to the user when tab tray is selected with multiple tabs. %1$s is getting replaced with the number of open tabs. -->
+ <string name="mozac_tab_counter_open_tab_tray_plural">%1$s open tabs. Tap to switch tabs.</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/tabstray/src/main/res/values-eo/strings.xml b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-eo/strings.xml
new file mode 100644
index 0000000000..d013c4a3a5
--- /dev/null
+++ b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-eo/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Message announced to the user when tab tray is selected with 1 tab -->
+ <string name="mozac_tab_counter_open_tab_tray_single">1 malfermita langeto. Tuŝetu por ŝanĝi langeton.</string>
+ <!-- Message announced to the user when tab tray is selected with multiple tabs. %1$s is getting replaced with the number of open tabs. -->
+ <string name="mozac_tab_counter_open_tab_tray_plural">%1$s malfermitaj langetoj. Tuŝetu por ŝanĝi langeton.</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/tabstray/src/main/res/values-es-rAR/strings.xml b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-es-rAR/strings.xml
new file mode 100644
index 0000000000..6344a3e800
--- /dev/null
+++ b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-es-rAR/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Message announced to the user when tab tray is selected with 1 tab -->
+ <string name="mozac_tab_counter_open_tab_tray_single">1 pestaña abierta. Tocá para cambiar de pestaña.</string>
+ <!-- Message announced to the user when tab tray is selected with multiple tabs. %1$s is getting replaced with the number of open tabs. -->
+ <string name="mozac_tab_counter_open_tab_tray_plural">%1$s pestañas abiertas. Tocá para cambiar de pestaña.</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/tabstray/src/main/res/values-es-rCL/strings.xml b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-es-rCL/strings.xml
new file mode 100644
index 0000000000..1fc73bee57
--- /dev/null
+++ b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-es-rCL/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Message announced to the user when tab tray is selected with 1 tab -->
+ <string name="mozac_tab_counter_open_tab_tray_single">1 pestaña abierta. Toca para cambiar de pestaña.</string>
+ <!-- Message announced to the user when tab tray is selected with multiple tabs. %1$s is getting replaced with the number of open tabs. -->
+ <string name="mozac_tab_counter_open_tab_tray_plural">%1$s pestañas abiertas. Toca para cambiar de pestaña.</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/tabstray/src/main/res/values-es-rES/strings.xml b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-es-rES/strings.xml
new file mode 100644
index 0000000000..1fc73bee57
--- /dev/null
+++ b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-es-rES/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Message announced to the user when tab tray is selected with 1 tab -->
+ <string name="mozac_tab_counter_open_tab_tray_single">1 pestaña abierta. Toca para cambiar de pestaña.</string>
+ <!-- Message announced to the user when tab tray is selected with multiple tabs. %1$s is getting replaced with the number of open tabs. -->
+ <string name="mozac_tab_counter_open_tab_tray_plural">%1$s pestañas abiertas. Toca para cambiar de pestaña.</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/tabstray/src/main/res/values-es-rMX/strings.xml b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-es-rMX/strings.xml
new file mode 100644
index 0000000000..93340efa67
--- /dev/null
+++ b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-es-rMX/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Message announced to the user when tab tray is selected with 1 tab -->
+ <string name="mozac_tab_counter_open_tab_tray_single">1 pestaña abierta. Tocar para cambiar de pestaña.</string>
+ <!-- Message announced to the user when tab tray is selected with multiple tabs. %1$s is getting replaced with the number of open tabs. -->
+ <string name="mozac_tab_counter_open_tab_tray_plural">%1$s pestañas abiertas. Tocar para cambiar de pestaña.</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/tabstray/src/main/res/values-es/strings.xml b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-es/strings.xml
new file mode 100644
index 0000000000..1fc73bee57
--- /dev/null
+++ b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-es/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Message announced to the user when tab tray is selected with 1 tab -->
+ <string name="mozac_tab_counter_open_tab_tray_single">1 pestaña abierta. Toca para cambiar de pestaña.</string>
+ <!-- Message announced to the user when tab tray is selected with multiple tabs. %1$s is getting replaced with the number of open tabs. -->
+ <string name="mozac_tab_counter_open_tab_tray_plural">%1$s pestañas abiertas. Toca para cambiar de pestaña.</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/tabstray/src/main/res/values-et/strings.xml b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-et/strings.xml
new file mode 100644
index 0000000000..9bb9d80603
--- /dev/null
+++ b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-et/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Message announced to the user when tab tray is selected with 1 tab -->
+ <string name="mozac_tab_counter_open_tab_tray_single">1 avatud kaart. Kaartide vahetamiseks puuduta.</string>
+ <!-- Message announced to the user when tab tray is selected with multiple tabs. %1$s is getting replaced with the number of open tabs. -->
+ <string name="mozac_tab_counter_open_tab_tray_plural">%1$s avatud kaarti. Kaartide vahetamiseks puuduta.</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/tabstray/src/main/res/values-eu/strings.xml b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-eu/strings.xml
new file mode 100644
index 0000000000..52ef09e49b
--- /dev/null
+++ b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-eu/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Message announced to the user when tab tray is selected with 1 tab -->
+ <string name="mozac_tab_counter_open_tab_tray_single">Irekitako fitxa bat. Sakatu fitxaz aldatzeko.</string>
+ <!-- Message announced to the user when tab tray is selected with multiple tabs. %1$s is getting replaced with the number of open tabs. -->
+ <string name="mozac_tab_counter_open_tab_tray_plural">Irekitako %1$s fitxa. Sakatu fitxaz aldatzeko.</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/tabstray/src/main/res/values-fa/strings.xml b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-fa/strings.xml
new file mode 100644
index 0000000000..c28779d31a
--- /dev/null
+++ b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-fa/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Message announced to the user when tab tray is selected with 1 tab -->
+ <string name="mozac_tab_counter_open_tab_tray_single">1 زبانه باز. برای تغییر زبانه ها ضربه بزنید.</string>
+ <!-- Message announced to the user when tab tray is selected with multiple tabs. %1$s is getting replaced with the number of open tabs. -->
+ <string name="mozac_tab_counter_open_tab_tray_plural">%1$s زبانه‌های باز. برای تغییر زبانه‌ها ضربه بزنید.</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/tabstray/src/main/res/values-fi/strings.xml b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-fi/strings.xml
new file mode 100644
index 0000000000..9043061f21
--- /dev/null
+++ b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-fi/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Message announced to the user when tab tray is selected with 1 tab -->
+ <string name="mozac_tab_counter_open_tab_tray_single">1 avoin välilehti. Napauta vaihtaaksesi.</string>
+ <!-- Message announced to the user when tab tray is selected with multiple tabs. %1$s is getting replaced with the number of open tabs. -->
+ <string name="mozac_tab_counter_open_tab_tray_plural">%1$s avointa välilehteä. Napauta vaihtaaksesi.</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/tabstray/src/main/res/values-fr/strings.xml b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-fr/strings.xml
new file mode 100644
index 0000000000..5b0e434e7a
--- /dev/null
+++ b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-fr/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Message announced to the user when tab tray is selected with 1 tab -->
+ <string name="mozac_tab_counter_open_tab_tray_single">1 onglet ouvert. Appuyez pour changer d’onglet.</string>
+ <!-- Message announced to the user when tab tray is selected with multiple tabs. %1$s is getting replaced with the number of open tabs. -->
+ <string name="mozac_tab_counter_open_tab_tray_plural">%1$s onglets ouverts. Appuyez pour changer d’onglet.</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/tabstray/src/main/res/values-fur/strings.xml b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-fur/strings.xml
new file mode 100644
index 0000000000..66634fc877
--- /dev/null
+++ b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-fur/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Message announced to the user when tab tray is selected with 1 tab -->
+ <string name="mozac_tab_counter_open_tab_tray_single">1 schede vierte. Tocje par cambiâ schede.</string>
+ <!-- Message announced to the user when tab tray is selected with multiple tabs. %1$s is getting replaced with the number of open tabs. -->
+ <string name="mozac_tab_counter_open_tab_tray_plural">%1$s schedis viertis. Tocje par cambiâ schede.</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/tabstray/src/main/res/values-fy-rNL/strings.xml b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-fy-rNL/strings.xml
new file mode 100644
index 0000000000..f6662bab43
--- /dev/null
+++ b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-fy-rNL/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Message announced to the user when tab tray is selected with 1 tab -->
+ <string name="mozac_tab_counter_open_tab_tray_single">1 iepen ljepblêd. Tik om tusken ljepblêden te wikseljen.</string>
+ <!-- Message announced to the user when tab tray is selected with multiple tabs. %1$s is getting replaced with the number of open tabs. -->
+ <string name="mozac_tab_counter_open_tab_tray_plural">%1$s iepen ljepblêden. Tik om tusken ljepblêden te wikseljen.</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/tabstray/src/main/res/values-gd/strings.xml b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-gd/strings.xml
new file mode 100644
index 0000000000..c93c8ec7a6
--- /dev/null
+++ b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-gd/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Message announced to the user when tab tray is selected with 1 tab -->
+ <string name="mozac_tab_counter_open_tab_tray_single">Tha taba fosgailte. Thoir gnogag airson leum a ghearradh gu taba eile.</string>
+ <!-- Message announced to the user when tab tray is selected with multiple tabs. %1$s is getting replaced with the number of open tabs. -->
+ <string name="mozac_tab_counter_open_tab_tray_plural">Tha tabaichean (%1$s) fosgailte. Thoir gnogag airson leum a ghearradh gu taba eile.</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/tabstray/src/main/res/values-gl/strings.xml b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-gl/strings.xml
new file mode 100644
index 0000000000..3148297284
--- /dev/null
+++ b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-gl/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Message announced to the user when tab tray is selected with 1 tab -->
+ <string name="mozac_tab_counter_open_tab_tray_single">1 separador aberto. Toque para cambiar de separador.</string>
+ <!-- Message announced to the user when tab tray is selected with multiple tabs. %1$s is getting replaced with the number of open tabs. -->
+ <string name="mozac_tab_counter_open_tab_tray_plural">%1$s separadores abertos. Toque para cambiar de separador.</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/tabstray/src/main/res/values-gn/strings.xml b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-gn/strings.xml
new file mode 100644
index 0000000000..2716e6a454
--- /dev/null
+++ b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-gn/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Message announced to the user when tab tray is selected with 1 tab -->
+ <string name="mozac_tab_counter_open_tab_tray_single">1 tendayke mbojuruja. Eikutu emoambue hag̃ua tendayke.</string>
+ <!-- Message announced to the user when tab tray is selected with multiple tabs. %1$s is getting replaced with the number of open tabs. -->
+ <string name="mozac_tab_counter_open_tab_tray_plural">%1$s tendayke ijurujáva. Eikutu emoambue hag̃ua tendayke.</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/tabstray/src/main/res/values-hi-rIN/strings.xml b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-hi-rIN/strings.xml
new file mode 100644
index 0000000000..5700f3b171
--- /dev/null
+++ b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-hi-rIN/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Message announced to the user when tab tray is selected with 1 tab -->
+ <string name="mozac_tab_counter_open_tab_tray_single">1 खुले टैब। टैब स्विच करने के लिए टैप करें।</string>
+ <!-- Message announced to the user when tab tray is selected with multiple tabs. %1$s is getting replaced with the number of open tabs. -->
+ <string name="mozac_tab_counter_open_tab_tray_plural">%1$s खुले टैब। टैब स्विच करने के लिए टैप करें।</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/tabstray/src/main/res/values-hr/strings.xml b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-hr/strings.xml
new file mode 100644
index 0000000000..71af2cc3cd
--- /dev/null
+++ b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-hr/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Message announced to the user when tab tray is selected with 1 tab -->
+ <string name="mozac_tab_counter_open_tab_tray_single">1 otvorena kartica. Dodirni za prebacivanje kartica.</string>
+ <!-- Message announced to the user when tab tray is selected with multiple tabs. %1$s is getting replaced with the number of open tabs. -->
+ <string name="mozac_tab_counter_open_tab_tray_plural">%1$s otvorene kartice. Dodirni za prebacivanje kartica.</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/tabstray/src/main/res/values-hsb/strings.xml b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-hsb/strings.xml
new file mode 100644
index 0000000000..f1a123a29e
--- /dev/null
+++ b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-hsb/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Message announced to the user when tab tray is selected with 1 tab -->
+ <string name="mozac_tab_counter_open_tab_tray_single">1 wočinjeny rajtark. Podótkńće so, zo byšće rajtarki přepinał.</string>
+ <!-- Message announced to the user when tab tray is selected with multiple tabs. %1$s is getting replaced with the number of open tabs. -->
+ <string name="mozac_tab_counter_open_tab_tray_plural">Wočinjene rajtarki: %1$s. Podótkńće so, zo byšće rajtarki přepinał.</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/tabstray/src/main/res/values-hu/strings.xml b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-hu/strings.xml
new file mode 100644
index 0000000000..1d101ccdd3
--- /dev/null
+++ b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-hu/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Message announced to the user when tab tray is selected with 1 tab -->
+ <string name="mozac_tab_counter_open_tab_tray_single">1 nyitott lap. Koppintson a lapváltáshoz.</string>
+ <!-- Message announced to the user when tab tray is selected with multiple tabs. %1$s is getting replaced with the number of open tabs. -->
+ <string name="mozac_tab_counter_open_tab_tray_plural">%1$s nyitott lap. Koppintson a lapváltáshoz.</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/tabstray/src/main/res/values-hy-rAM/strings.xml b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-hy-rAM/strings.xml
new file mode 100644
index 0000000000..4dcf37a304
--- /dev/null
+++ b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-hy-rAM/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Message announced to the user when tab tray is selected with 1 tab -->
+ <string name="mozac_tab_counter_open_tab_tray_single">1 բաց ներդիր: Հպեք՝ ներդիրին անցնելու համար:</string>
+ <!-- Message announced to the user when tab tray is selected with multiple tabs. %1$s is getting replaced with the number of open tabs. -->
+ <string name="mozac_tab_counter_open_tab_tray_plural">%1$s բաց ներդիրներ: Հպեք՝ ներդիրին անցնելու համար:</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/tabstray/src/main/res/values-ia/strings.xml b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-ia/strings.xml
new file mode 100644
index 0000000000..978d967aab
--- /dev/null
+++ b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-ia/strings.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Message announced to the user when tab tray is selected with 1 tab -->
+ <string name="mozac_tab_counter_open_tab_tray_single">1 scheda aperte. Tocca pro cambiar de scheda.
+</string>
+ <!-- Message announced to the user when tab tray is selected with multiple tabs. %1$s is getting replaced with the number of open tabs. -->
+ <string name="mozac_tab_counter_open_tab_tray_plural">%1$s schedas aperte. Tocca pro cambiar de scheda.</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/tabstray/src/main/res/values-in/strings.xml b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-in/strings.xml
new file mode 100644
index 0000000000..bce1963ede
--- /dev/null
+++ b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-in/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Message announced to the user when tab tray is selected with 1 tab -->
+ <string name="mozac_tab_counter_open_tab_tray_single">1 tab terbuka. Ketuk untuk beralih tab.</string>
+ <!-- Message announced to the user when tab tray is selected with multiple tabs. %1$s is getting replaced with the number of open tabs. -->
+ <string name="mozac_tab_counter_open_tab_tray_plural">%1$s tab terbuka. Ketuk untuk beralih tab.</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/tabstray/src/main/res/values-is/strings.xml b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-is/strings.xml
new file mode 100644
index 0000000000..a66a6df882
--- /dev/null
+++ b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-is/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Message announced to the user when tab tray is selected with 1 tab -->
+ <string name="mozac_tab_counter_open_tab_tray_single">1 opinn flipi. Snertu til að skipta um flipa.</string>
+ <!-- Message announced to the user when tab tray is selected with multiple tabs. %1$s is getting replaced with the number of open tabs. -->
+ <string name="mozac_tab_counter_open_tab_tray_plural">%1$s opnir flipar. Snertu til að skipta um flipa.</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/tabstray/src/main/res/values-it/strings.xml b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-it/strings.xml
new file mode 100644
index 0000000000..140462654e
--- /dev/null
+++ b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-it/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Message announced to the user when tab tray is selected with 1 tab -->
+ <string name="mozac_tab_counter_open_tab_tray_single">Aperta 1 scheda. Tocca per passare alla scheda.</string>
+ <!-- Message announced to the user when tab tray is selected with multiple tabs. %1$s is getting replaced with the number of open tabs. -->
+ <string name="mozac_tab_counter_open_tab_tray_plural">Aperte %1$s schede. Tocca per passare alle schede.</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/tabstray/src/main/res/values-iw/strings.xml b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-iw/strings.xml
new file mode 100644
index 0000000000..4f1393a5e8
--- /dev/null
+++ b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-iw/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Message announced to the user when tab tray is selected with 1 tab -->
+ <string name="mozac_tab_counter_open_tab_tray_single">לשונית אחת פתוחה. יש להקיש כדי להחליף לשוניות.</string>
+ <!-- Message announced to the user when tab tray is selected with multiple tabs. %1$s is getting replaced with the number of open tabs. -->
+ <string name="mozac_tab_counter_open_tab_tray_plural">%1$s לשוניות פתוחות. יש להקיש כדי להחליף לשוניות.</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/tabstray/src/main/res/values-ja/strings.xml b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-ja/strings.xml
new file mode 100644
index 0000000000..c9d1a62ca7
--- /dev/null
+++ b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-ja/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Message announced to the user when tab tray is selected with 1 tab -->
+ <string name="mozac_tab_counter_open_tab_tray_single">開いているタブ 1 個。タップしてタブを切り替えます。</string>
+ <!-- Message announced to the user when tab tray is selected with multiple tabs. %1$s is getting replaced with the number of open tabs. -->
+ <string name="mozac_tab_counter_open_tab_tray_plural">開いているタブ %1$s 個。タップしてタブを切り替えます。</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/tabstray/src/main/res/values-ka/strings.xml b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-ka/strings.xml
new file mode 100644
index 0000000000..934c9fea2d
--- /dev/null
+++ b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-ka/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Message announced to the user when tab tray is selected with 1 tab -->
+ <string name="mozac_tab_counter_open_tab_tray_single">1 გახსნილი ჩანართი. შეეხეთ ჩანართების გადასართველად.</string>
+ <!-- Message announced to the user when tab tray is selected with multiple tabs. %1$s is getting replaced with the number of open tabs. -->
+ <string name="mozac_tab_counter_open_tab_tray_plural">%1$s გახსნილი ჩანართი. შეეხეთ ჩანართების გადასართველად.</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/tabstray/src/main/res/values-kaa/strings.xml b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-kaa/strings.xml
new file mode 100644
index 0000000000..44c0e17a69
--- /dev/null
+++ b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-kaa/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Message announced to the user when tab tray is selected with 1 tab -->
+ <string name="mozac_tab_counter_open_tab_tray_single">1 bet ashıq. Basqa betlerge ótiw ushın basıń.</string>
+ <!-- Message announced to the user when tab tray is selected with multiple tabs. %1$s is getting replaced with the number of open tabs. -->
+ <string name="mozac_tab_counter_open_tab_tray_plural">%1$s bet ashıq. Basqa betlerge ótiw ushın basıń.</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/tabstray/src/main/res/values-kab/strings.xml b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-kab/strings.xml
new file mode 100644
index 0000000000..8c487c45bb
--- /dev/null
+++ b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-kab/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Message announced to the user when tab tray is selected with 1 tab -->
+ <string name="mozac_tab_counter_open_tab_tray_single">1 yiccer i yeldin. Sit akken ad tettbeddileḍ accaren.</string>
+ <!-- Message announced to the user when tab tray is selected with multiple tabs. %1$s is getting replaced with the number of open tabs. -->
+ <string name="mozac_tab_counter_open_tab_tray_plural">%1$s waccaren yeldin. Sit akken ad tettbeddileḍ gar waccaren.</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/tabstray/src/main/res/values-kk/strings.xml b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-kk/strings.xml
new file mode 100644
index 0000000000..ac04517a9a
--- /dev/null
+++ b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-kk/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Message announced to the user when tab tray is selected with 1 tab -->
+ <string name="mozac_tab_counter_open_tab_tray_single">1 ашық бет. Беттерді ауыстыру үшін шертіңіз.</string>
+ <!-- Message announced to the user when tab tray is selected with multiple tabs. %1$s is getting replaced with the number of open tabs. -->
+ <string name="mozac_tab_counter_open_tab_tray_plural">%1$s ашық бет. Беттерді ауыстыру үшін шертіңіз.</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/tabstray/src/main/res/values-kmr/strings.xml b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-kmr/strings.xml
new file mode 100644
index 0000000000..822e18a09a
--- /dev/null
+++ b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-kmr/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Message announced to the user when tab tray is selected with 1 tab -->
+ <string name="mozac_tab_counter_open_tab_tray_single">1 hilpekîna vekirî. Ji bo hilpekînê biguherînî, bitikîne.</string>
+ <!-- Message announced to the user when tab tray is selected with multiple tabs. %1$s is getting replaced with the number of open tabs. -->
+ <string name="mozac_tab_counter_open_tab_tray_plural">%1$s hilpekînên vekirî. Ji bo hilpekînan biguherînî, bitikîne.</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/tabstray/src/main/res/values-ko/strings.xml b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-ko/strings.xml
new file mode 100644
index 0000000000..5f133435b1
--- /dev/null
+++ b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-ko/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Message announced to the user when tab tray is selected with 1 tab -->
+ <string name="mozac_tab_counter_open_tab_tray_single">열린 탭 1개. 탭을 전환하려면 누르세요.</string>
+ <!-- Message announced to the user when tab tray is selected with multiple tabs. %1$s is getting replaced with the number of open tabs. -->
+ <string name="mozac_tab_counter_open_tab_tray_plural">열린 탭 %1$s개. 탭을 전환하려면 누르세요.</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/tabstray/src/main/res/values-lo/strings.xml b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-lo/strings.xml
new file mode 100644
index 0000000000..0b4ad9c0bc
--- /dev/null
+++ b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-lo/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Message announced to the user when tab tray is selected with 1 tab -->
+ <string name="mozac_tab_counter_open_tab_tray_single">1 ແທັບທີ່ເປີດ. ແຕະເພື່ອປ່ຽນແທັບ.</string>
+ <!-- Message announced to the user when tab tray is selected with multiple tabs. %1$s is getting replaced with the number of open tabs. -->
+ <string name="mozac_tab_counter_open_tab_tray_plural">%1$s ແທັບທີ່ເປີດ. ແຕະເພື່ອປ່ຽນແທັບ.</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/tabstray/src/main/res/values-lt/strings.xml b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-lt/strings.xml
new file mode 100644
index 0000000000..e11a4df1f6
--- /dev/null
+++ b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-lt/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Message announced to the user when tab tray is selected with 1 tab -->
+ <string name="mozac_tab_counter_open_tab_tray_single">1 atverta kortelė. Bakstelėkite, norėdami pereiti tarp kortelių.</string>
+ <!-- Message announced to the user when tab tray is selected with multiple tabs. %1$s is getting replaced with the number of open tabs. -->
+ <string name="mozac_tab_counter_open_tab_tray_plural">%1$s atvertos kortelės. Bakstelėkite, norėdami pereiti tarp kortelių.</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/tabstray/src/main/res/values-mr/strings.xml b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-mr/strings.xml
new file mode 100644
index 0000000000..c5eb4b33bd
--- /dev/null
+++ b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-mr/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Message announced to the user when tab tray is selected with 1 tab -->
+ <string name="mozac_tab_counter_open_tab_tray_single">1 टॅब उघडी. टॅब स्विच करण्यासाठी टॅप करा.</string>
+ <!-- Message announced to the user when tab tray is selected with multiple tabs. %1$s is getting replaced with the number of open tabs. -->
+ <string name="mozac_tab_counter_open_tab_tray_plural">%1$s टॅब उघड्या. टॅब स्विच करण्यासाठी टॅप करा.</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/tabstray/src/main/res/values-my/strings.xml b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-my/strings.xml
new file mode 100644
index 0000000000..da0d02a362
--- /dev/null
+++ b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-my/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Message announced to the user when tab tray is selected with 1 tab -->
+ <string name="mozac_tab_counter_open_tab_tray_single">1 ဖွင်ထားသော တပ်ဘ်. တပ်ဘ်များပြောင်းလဲရန်နှိပ်ပါ။</string>
+ <!-- Message announced to the user when tab tray is selected with multiple tabs. %1$s is getting replaced with the number of open tabs. -->
+ <string name="mozac_tab_counter_open_tab_tray_plural">ဖွင့်ထားသော တက်ဗ်များ %1$s ခု။ တက်ဗ်များပြောင်းလဲရန်နှိပ်ပါ။</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/tabstray/src/main/res/values-nb-rNO/strings.xml b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-nb-rNO/strings.xml
new file mode 100644
index 0000000000..ce10fee7ea
--- /dev/null
+++ b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-nb-rNO/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Message announced to the user when tab tray is selected with 1 tab -->
+ <string name="mozac_tab_counter_open_tab_tray_single">1 åpen fane. Trykk for å bytte fane.</string>
+ <!-- Message announced to the user when tab tray is selected with multiple tabs. %1$s is getting replaced with the number of open tabs. -->
+ <string name="mozac_tab_counter_open_tab_tray_plural">%1$s åpne faner. Trykk for å bytte fane.</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/tabstray/src/main/res/values-ne-rNP/strings.xml b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-ne-rNP/strings.xml
new file mode 100644
index 0000000000..297d697276
--- /dev/null
+++ b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-ne-rNP/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Message announced to the user when tab tray is selected with 1 tab -->
+ <string name="mozac_tab_counter_open_tab_tray_single">1ट्याब खोल्नुहोस् । ट्याबहरु बिच स्वीच गर्नको लागि ट्याप गर्नुहोस् ।</string>
+ <!-- Message announced to the user when tab tray is selected with multiple tabs. %1$s is getting replaced with the number of open tabs. -->
+ <string name="mozac_tab_counter_open_tab_tray_plural">%1$s ट्याबहरु खोल्नुहोस्। ट्याबहरु बिच स्वीच गर्नको लागि ट्याप गर्नुहोस्।</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/tabstray/src/main/res/values-nl/strings.xml b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-nl/strings.xml
new file mode 100644
index 0000000000..02eb5b97e8
--- /dev/null
+++ b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-nl/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Message announced to the user when tab tray is selected with 1 tab -->
+ <string name="mozac_tab_counter_open_tab_tray_single">1 open tabblad. Tik om tussen tabbladen te wisselen.</string>
+ <!-- Message announced to the user when tab tray is selected with multiple tabs. %1$s is getting replaced with the number of open tabs. -->
+ <string name="mozac_tab_counter_open_tab_tray_plural">%1$s open tabbladen. Tik om tussen tabbladen te wisselen.</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/tabstray/src/main/res/values-nn-rNO/strings.xml b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-nn-rNO/strings.xml
new file mode 100644
index 0000000000..a743c17ac4
--- /dev/null
+++ b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-nn-rNO/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Message announced to the user when tab tray is selected with 1 tab -->
+ <string name="mozac_tab_counter_open_tab_tray_single">1 open fane. Trykk for å byte fane.</string>
+ <!-- Message announced to the user when tab tray is selected with multiple tabs. %1$s is getting replaced with the number of open tabs. -->
+ <string name="mozac_tab_counter_open_tab_tray_plural">%1$s opne faner. Trykk for å byte fane.</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/tabstray/src/main/res/values-oc/strings.xml b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-oc/strings.xml
new file mode 100644
index 0000000000..6e5eb1f335
--- /dev/null
+++ b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-oc/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Message announced to the user when tab tray is selected with 1 tab -->
+ <string name="mozac_tab_counter_open_tab_tray_single">1 onglet dobèrt. Tocatz per i bascular.</string>
+ <!-- Message announced to the user when tab tray is selected with multiple tabs. %1$s is getting replaced with the number of open tabs. -->
+ <string name="mozac_tab_counter_open_tab_tray_plural">%1$s onglets dobèrts. Tocatz per cambiar d’onglet.</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/tabstray/src/main/res/values-pa-rIN/strings.xml b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-pa-rIN/strings.xml
new file mode 100644
index 0000000000..b6941d927d
--- /dev/null
+++ b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-pa-rIN/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Message announced to the user when tab tray is selected with 1 tab -->
+ <string name="mozac_tab_counter_open_tab_tray_single">1 ਟੈਬ ਖੋਲ੍ਹੋ। ਟੈਬਾਂ ਬਦਲਣ ਲਈ ਛੂਹੋ।</string>
+ <!-- Message announced to the user when tab tray is selected with multiple tabs. %1$s is getting replaced with the number of open tabs. -->
+ <string name="mozac_tab_counter_open_tab_tray_plural">%1$s ਟੈਬਾਂ ਖੋਲ੍ਹੋ। ਟੈਬਾਂ ਬਦਲਣ ਲਈ ਛੂਹੋ।</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/tabstray/src/main/res/values-pa-rPK/strings.xml b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-pa-rPK/strings.xml
new file mode 100644
index 0000000000..fee2e99440
--- /dev/null
+++ b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-pa-rPK/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Message announced to the user when tab tray is selected with 1 tab -->
+ <string name="mozac_tab_counter_open_tab_tray_single">اک ٹیب کھُلھی اے۔ ہورناں ٹیب جاوݨ لئی اِتھے چھوہو۔</string>
+ <!-- Message announced to the user when tab tray is selected with multiple tabs. %1$s is getting replaced with the number of open tabs. -->
+ <string name="mozac_tab_counter_open_tab_tray_plural">%1$s ٹیباں کھُلھیاں ہن۔ ہورناں ٹیب جاوݨ لئی اِتھے چھوہو۔</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/tabstray/src/main/res/values-pl/strings.xml b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-pl/strings.xml
new file mode 100644
index 0000000000..95eff57834
--- /dev/null
+++ b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-pl/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Message announced to the user when tab tray is selected with 1 tab -->
+ <string name="mozac_tab_counter_open_tab_tray_single">Otwarte karty: 1. Stuknij, aby przełączyć karty.</string>
+ <!-- Message announced to the user when tab tray is selected with multiple tabs. %1$s is getting replaced with the number of open tabs. -->
+ <string name="mozac_tab_counter_open_tab_tray_plural">Otwarte karty: %1$s. Stuknij, aby przełączyć karty.</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/tabstray/src/main/res/values-pt-rBR/strings.xml b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-pt-rBR/strings.xml
new file mode 100644
index 0000000000..c26434a581
--- /dev/null
+++ b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-pt-rBR/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Message announced to the user when tab tray is selected with 1 tab -->
+ <string name="mozac_tab_counter_open_tab_tray_single">1 aba aberta. Toque para alternar abas.</string>
+ <!-- Message announced to the user when tab tray is selected with multiple tabs. %1$s is getting replaced with the number of open tabs. -->
+ <string name="mozac_tab_counter_open_tab_tray_plural">%1$s abas abertas. Toque para alternar abas.</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/tabstray/src/main/res/values-pt-rPT/strings.xml b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-pt-rPT/strings.xml
new file mode 100644
index 0000000000..b0481b37f4
--- /dev/null
+++ b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-pt-rPT/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Message announced to the user when tab tray is selected with 1 tab -->
+ <string name="mozac_tab_counter_open_tab_tray_single">1 separador aberto. Toque para mudar de separador.</string>
+ <!-- Message announced to the user when tab tray is selected with multiple tabs. %1$s is getting replaced with the number of open tabs. -->
+ <string name="mozac_tab_counter_open_tab_tray_plural">%1$s separadores abertos. Toque para mudar de separador.</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/tabstray/src/main/res/values-rm/strings.xml b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-rm/strings.xml
new file mode 100644
index 0000000000..1a085d3aa4
--- /dev/null
+++ b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-rm/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Message announced to the user when tab tray is selected with 1 tab -->
+ <string name="mozac_tab_counter_open_tab_tray_single">1 tab avert. Tutgar per midar tab.</string>
+ <!-- Message announced to the user when tab tray is selected with multiple tabs. %1$s is getting replaced with the number of open tabs. -->
+ <string name="mozac_tab_counter_open_tab_tray_plural">%1$s tabs averts. Tutgar per midar tab.</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/tabstray/src/main/res/values-ro/strings.xml b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-ro/strings.xml
new file mode 100644
index 0000000000..4e5f9a7a12
--- /dev/null
+++ b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-ro/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Message announced to the user when tab tray is selected with 1 tab -->
+ <string name="mozac_tab_counter_open_tab_tray_single">1 filă deschisă. Atinge pentru a comuta între file.</string>
+ <!-- Message announced to the user when tab tray is selected with multiple tabs. %1$s is getting replaced with the number of open tabs. -->
+ <string name="mozac_tab_counter_open_tab_tray_plural">%1$s file deschise. Atinge pentru a comuta între file.</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/tabstray/src/main/res/values-ru/strings.xml b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-ru/strings.xml
new file mode 100644
index 0000000000..084301cc50
--- /dev/null
+++ b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-ru/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Message announced to the user when tab tray is selected with 1 tab -->
+ <string name="mozac_tab_counter_open_tab_tray_single">1 открытая вкладка. Нажмите, чтобы переключить вкладки.</string>
+ <!-- Message announced to the user when tab tray is selected with multiple tabs. %1$s is getting replaced with the number of open tabs. -->
+ <string name="mozac_tab_counter_open_tab_tray_plural">Открытых вкладок: %1$s. Нажмите, чтобы переключить вкладки.</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/tabstray/src/main/res/values-sat/strings.xml b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-sat/strings.xml
new file mode 100644
index 0000000000..31dce75121
--- /dev/null
+++ b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-sat/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Message announced to the user when tab tray is selected with 1 tab -->
+ <string name="mozac_tab_counter_open_tab_tray_single">1 ᱴᱮᱵᱽ ᱠᱷᱩᱞᱟᱹᱭ ᱢᱮ ᱾ ᱴᱮᱵᱽ ᱵᱚᱫᱚᱞ ᱞᱟᱹᱜᱤᱫ ᱴᱤᱯᱟᱹᱣ ᱢᱮ ᱾</string>
+ <!-- Message announced to the user when tab tray is selected with multiple tabs. %1$s is getting replaced with the number of open tabs. -->
+ <string name="mozac_tab_counter_open_tab_tray_plural">%1$s ᱴᱮᱵᱽ ᱠᱚ ᱠᱷᱩᱞᱟᱹᱭ ᱢᱮ ᱾ ᱴᱮᱵᱽ ᱵᱚᱫᱚᱞ ᱞᱟᱹᱜᱤᱫ ᱴᱤᱯᱟᱹᱣ ᱢᱮ ᱾</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/tabstray/src/main/res/values-sc/strings.xml b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-sc/strings.xml
new file mode 100644
index 0000000000..aba35fe993
--- /dev/null
+++ b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-sc/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Message announced to the user when tab tray is selected with 1 tab -->
+ <string name="mozac_tab_counter_open_tab_tray_single">1 ischeda aberta. Toca pro cuncambiare ischedas.</string>
+ <!-- Message announced to the user when tab tray is selected with multiple tabs. %1$s is getting replaced with the number of open tabs. -->
+ <string name="mozac_tab_counter_open_tab_tray_plural">%1$s ischedas abertas. Toca pro cuncambiare ischedas.</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/tabstray/src/main/res/values-si/strings.xml b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-si/strings.xml
new file mode 100644
index 0000000000..fa81c6c72e
--- /dev/null
+++ b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-si/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Message announced to the user when tab tray is selected with 1 tab -->
+ <string name="mozac_tab_counter_open_tab_tray_single">විවෘත පටිති 1. මාරු වීමට ඔබන්න.</string>
+ <!-- Message announced to the user when tab tray is selected with multiple tabs. %1$s is getting replaced with the number of open tabs. -->
+ <string name="mozac_tab_counter_open_tab_tray_plural">විවෘත පටිති %1$s. මාරු වීමට ඔබන්න.</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/tabstray/src/main/res/values-sk/strings.xml b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-sk/strings.xml
new file mode 100644
index 0000000000..6d9c07e007
--- /dev/null
+++ b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-sk/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Message announced to the user when tab tray is selected with 1 tab -->
+ <string name="mozac_tab_counter_open_tab_tray_single">Počet otvorených kariet: 1. Ťuknutím prepnete karty.</string>
+ <!-- Message announced to the user when tab tray is selected with multiple tabs. %1$s is getting replaced with the number of open tabs. -->
+ <string name="mozac_tab_counter_open_tab_tray_plural">Počet otvorených kariet: %1$s. Ťuknutím prepnete karty.</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/tabstray/src/main/res/values-skr/strings.xml b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-skr/strings.xml
new file mode 100644
index 0000000000..259bf6e843
--- /dev/null
+++ b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-skr/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Message announced to the user when tab tray is selected with 1 tab -->
+ <string name="mozac_tab_counter_open_tab_tray_single">1 ٹیب کھولو۔ ٹیبز بدلن کیتے دباؤ۔</string>
+ <!-- Message announced to the user when tab tray is selected with multiple tabs. %1$s is getting replaced with the number of open tabs. -->
+ <string name="mozac_tab_counter_open_tab_tray_plural">%1$s ٹیبز کھولو۔ ٹیبز بدلن کیتے دباؤ۔</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/tabstray/src/main/res/values-sl/strings.xml b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-sl/strings.xml
new file mode 100644
index 0000000000..da63aabfe3
--- /dev/null
+++ b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-sl/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Message announced to the user when tab tray is selected with 1 tab -->
+ <string name="mozac_tab_counter_open_tab_tray_single">1 odprt zavihek. Tapnite za preklop zavihkov.</string>
+ <!-- Message announced to the user when tab tray is selected with multiple tabs. %1$s is getting replaced with the number of open tabs. -->
+ <string name="mozac_tab_counter_open_tab_tray_plural">Odprtih zavihkov: %1$s. Tapnite za preklop zavihkov.</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/tabstray/src/main/res/values-sq/strings.xml b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-sq/strings.xml
new file mode 100644
index 0000000000..ab5ac214b6
--- /dev/null
+++ b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-sq/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Message announced to the user when tab tray is selected with 1 tab -->
+ <string name="mozac_tab_counter_open_tab_tray_single">1 skedë e hapur. Prekeni që të ndërroni skeda.</string>
+ <!-- Message announced to the user when tab tray is selected with multiple tabs. %1$s is getting replaced with the number of open tabs. -->
+ <string name="mozac_tab_counter_open_tab_tray_plural">%1$s skeda të hapura. Prekeni që të ndërroni skeda.</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/tabstray/src/main/res/values-sr/strings.xml b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-sr/strings.xml
new file mode 100644
index 0000000000..c2b36f1e84
--- /dev/null
+++ b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-sr/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Message announced to the user when tab tray is selected with 1 tab -->
+ <string name="mozac_tab_counter_open_tab_tray_single">1 отворен језичак. Додирни за пребацивање.</string>
+ <!-- Message announced to the user when tab tray is selected with multiple tabs. %1$s is getting replaced with the number of open tabs. -->
+ <string name="mozac_tab_counter_open_tab_tray_plural">%1$s отоврених језичака. Додирни за пребацивање.</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/tabstray/src/main/res/values-su/strings.xml b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-su/strings.xml
new file mode 100644
index 0000000000..6ca8fedea8
--- /dev/null
+++ b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-su/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Message announced to the user when tab tray is selected with 1 tab -->
+ <string name="mozac_tab_counter_open_tab_tray_single">1 tab muka. Toél pikeun ngagilir tab.</string>
+ <!-- Message announced to the user when tab tray is selected with multiple tabs. %1$s is getting replaced with the number of open tabs. -->
+ <string name="mozac_tab_counter_open_tab_tray_plural">%1$s tab muka. Toél pikeun ngagilir tab.</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/tabstray/src/main/res/values-sv-rSE/strings.xml b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-sv-rSE/strings.xml
new file mode 100644
index 0000000000..4dccc57f82
--- /dev/null
+++ b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-sv-rSE/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Message announced to the user when tab tray is selected with 1 tab -->
+ <string name="mozac_tab_counter_open_tab_tray_single">1 öppen flik. Tryck för att växla mellan flikar.</string>
+ <!-- Message announced to the user when tab tray is selected with multiple tabs. %1$s is getting replaced with the number of open tabs. -->
+ <string name="mozac_tab_counter_open_tab_tray_plural">%1$s öppna flikar. Tryck för att växla mellan flikar.</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/tabstray/src/main/res/values-szl/strings.xml b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-szl/strings.xml
new file mode 100644
index 0000000000..d8a8f70ecd
--- /dev/null
+++ b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-szl/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Message announced to the user when tab tray is selected with 1 tab -->
+ <string name="mozac_tab_counter_open_tab_tray_single">1 ôtwarto karta. Tyknij, coby przełōnczyć karty.</string>
+ <!-- Message announced to the user when tab tray is selected with multiple tabs. %1$s is getting replaced with the number of open tabs. -->
+ <string name="mozac_tab_counter_open_tab_tray_plural">Ôtwarte karty: %1$s. Tyknij, coby je zmiynić.</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/tabstray/src/main/res/values-ta/strings.xml b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-ta/strings.xml
new file mode 100644
index 0000000000..dd73074d4e
--- /dev/null
+++ b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-ta/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Message announced to the user when tab tray is selected with 1 tab -->
+ <string name="mozac_tab_counter_open_tab_tray_single">1 திறந்த கீற்று. கீற்றுகளிடையே மாற தட்டு.</string>
+ <!-- Message announced to the user when tab tray is selected with multiple tabs. %1$s is getting replaced with the number of open tabs. -->
+ <string name="mozac_tab_counter_open_tab_tray_plural">%1$s திறந்த கீற்றுகள். கீற்றுகளிடையே மாற தட்டு.</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/tabstray/src/main/res/values-tg/strings.xml b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-tg/strings.xml
new file mode 100644
index 0000000000..ec5a7e0129
--- /dev/null
+++ b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-tg/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Message announced to the user when tab tray is selected with 1 tab -->
+ <string name="mozac_tab_counter_open_tab_tray_single">1 варақаи кушодашуда. Барои гузариш байни варақаҳо зарба занед.</string>
+ <!-- Message announced to the user when tab tray is selected with multiple tabs. %1$s is getting replaced with the number of open tabs. -->
+ <string name="mozac_tab_counter_open_tab_tray_plural">%1$s варақаи кушодашуда. Барои гузариш байни варақаҳо зарба занед.</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/tabstray/src/main/res/values-th/strings.xml b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-th/strings.xml
new file mode 100644
index 0000000000..8dd4edebd2
--- /dev/null
+++ b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-th/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Message announced to the user when tab tray is selected with 1 tab -->
+ <string name="mozac_tab_counter_open_tab_tray_single">1 แท็บที่เปิด แตะเพื่อสลับไปยังแท็บ</string>
+ <!-- Message announced to the user when tab tray is selected with multiple tabs. %1$s is getting replaced with the number of open tabs. -->
+ <string name="mozac_tab_counter_open_tab_tray_plural">%1$s แท็บที่เปิด แตะเพื่อสลับไปยังแท็บ</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/tabstray/src/main/res/values-tl/strings.xml b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-tl/strings.xml
new file mode 100644
index 0000000000..b90ceee0ac
--- /dev/null
+++ b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-tl/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Message announced to the user when tab tray is selected with 1 tab -->
+ <string name="mozac_tab_counter_open_tab_tray_single">1 open na tab. i-Tap para mag switch ng tabs.</string>
+ <!-- Message announced to the user when tab tray is selected with multiple tabs. %1$s is getting replaced with the number of open tabs. -->
+ <string name="mozac_tab_counter_open_tab_tray_plural">%1$s open na tabs. i-Tap para mag switch ng tabs.</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/tabstray/src/main/res/values-tr/strings.xml b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-tr/strings.xml
new file mode 100644
index 0000000000..6fd9d0a795
--- /dev/null
+++ b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-tr/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Message announced to the user when tab tray is selected with 1 tab -->
+ <string name="mozac_tab_counter_open_tab_tray_single">1 açık sekme. Sekme değiştirmek için dokunun.</string>
+ <!-- Message announced to the user when tab tray is selected with multiple tabs. %1$s is getting replaced with the number of open tabs. -->
+ <string name="mozac_tab_counter_open_tab_tray_plural">%1$s açık sekme. Sekme değiştirmek için dokunun.</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/tabstray/src/main/res/values-trs/strings.xml b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-trs/strings.xml
new file mode 100644
index 0000000000..73ab55b438
--- /dev/null
+++ b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-trs/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Message announced to the user when tab tray is selected with 1 tab -->
+ <string name="mozac_tab_counter_open_tab_tray_single">1 nā\'nïn rakïj ñanj. Gūru\'man ra\'a da\' nādūnāt rakïj ñanj.</string>
+ <!-- Message announced to the user when tab tray is selected with multiple tabs. %1$s is getting replaced with the number of open tabs. -->
+ <string name="mozac_tab_counter_open_tab_tray_plural">%1$s nā\'nïn nej rakïj ñanj. Gūru\'man ra\'a da\' nādūnāt nej rakïj ñanj.</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/tabstray/src/main/res/values-tt/strings.xml b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-tt/strings.xml
new file mode 100644
index 0000000000..cccb0f592c
--- /dev/null
+++ b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-tt/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Message announced to the user when tab tray is selected with 1 tab -->
+ <string name="mozac_tab_counter_open_tab_tray_single">1 ачык таб. Табларны алмаштыру өчен басыгыз.</string>
+ <!-- Message announced to the user when tab tray is selected with multiple tabs. %1$s is getting replaced with the number of open tabs. -->
+ <string name="mozac_tab_counter_open_tab_tray_plural">%1$s ачык таб. Табларны алмаштыру өчен басыгыз.</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/tabstray/src/main/res/values-ug/strings.xml b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-ug/strings.xml
new file mode 100644
index 0000000000..b06335ccd7
--- /dev/null
+++ b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-ug/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Message announced to the user when tab tray is selected with 1 tab -->
+ <string name="mozac_tab_counter_open_tab_tray_single">1 بەتكۈچ ئوچۇق. بەتكۈچنى ئالماشتۇرۇش ئۈچۈن چېكىڭ.</string>
+ <!-- Message announced to the user when tab tray is selected with multiple tabs. %1$s is getting replaced with the number of open tabs. -->
+ <string name="mozac_tab_counter_open_tab_tray_plural">%1$s بەتكۈچ ئوچۇق. بەتكۈچنى ئالماشتۇرۇش ئۈچۈن چېكىڭ.</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/tabstray/src/main/res/values-uk/strings.xml b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-uk/strings.xml
new file mode 100644
index 0000000000..7c4eac5634
--- /dev/null
+++ b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-uk/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Message announced to the user when tab tray is selected with 1 tab -->
+ <string name="mozac_tab_counter_open_tab_tray_single">1 відкрита вкладка. Торкніться, щоб перемкнути вкладки.</string>
+ <!-- Message announced to the user when tab tray is selected with multiple tabs. %1$s is getting replaced with the number of open tabs. -->
+ <string name="mozac_tab_counter_open_tab_tray_plural">%1$s відкритих вкладок. Торкніться, щоб перемкнути вкладки.</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/tabstray/src/main/res/values-ur/strings.xml b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-ur/strings.xml
new file mode 100644
index 0000000000..2aff9ce62a
--- /dev/null
+++ b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-ur/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Message announced to the user when tab tray is selected with 1 tab -->
+ <string name="mozac_tab_counter_open_tab_tray_single">1 کھلا ٹیب۔ ٹیبز بدلنے کے لئے دبائیں۔</string>
+ <!-- Message announced to the user when tab tray is selected with multiple tabs. %1$s is getting replaced with the number of open tabs. -->
+ <string name="mozac_tab_counter_open_tab_tray_plural">%1$s کھلے ٹیب۔ ٹیب بدلنے کے لئے دبائیں۔</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/tabstray/src/main/res/values-uz/strings.xml b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-uz/strings.xml
new file mode 100644
index 0000000000..27d543d25d
--- /dev/null
+++ b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-uz/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Message announced to the user when tab tray is selected with 1 tab -->
+ <string name="mozac_tab_counter_open_tab_tray_single">1 ta ochiq varaq. Boshqa varaqqa oʻtish uchun bosing.</string>
+ <!-- Message announced to the user when tab tray is selected with multiple tabs. %1$s is getting replaced with the number of open tabs. -->
+ <string name="mozac_tab_counter_open_tab_tray_plural">%1$s ta ochiq varaq. Boshqa varaqqa oʻtish uchun bosing.</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/tabstray/src/main/res/values-vec/strings.xml b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-vec/strings.xml
new file mode 100644
index 0000000000..df02a32682
--- /dev/null
+++ b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-vec/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Message announced to the user when tab tray is selected with 1 tab -->
+ <string name="mozac_tab_counter_open_tab_tray_single">Verta 1 scheda. Toca par pasare a ƚa scheda.</string>
+ <!-- Message announced to the user when tab tray is selected with multiple tabs. %1$s is getting replaced with the number of open tabs. -->
+ <string name="mozac_tab_counter_open_tab_tray_plural">Verte %1$s schede. Toca par pasare a ƚe schede.</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/tabstray/src/main/res/values-vi/strings.xml b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-vi/strings.xml
new file mode 100644
index 0000000000..b72a0a985d
--- /dev/null
+++ b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-vi/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Message announced to the user when tab tray is selected with 1 tab -->
+ <string name="mozac_tab_counter_open_tab_tray_single">1 thẻ đang mở. Chạm để chuyển thẻ.</string>
+ <!-- Message announced to the user when tab tray is selected with multiple tabs. %1$s is getting replaced with the number of open tabs. -->
+ <string name="mozac_tab_counter_open_tab_tray_plural">%1$s thẻ đang mở. Chạm để chuyển thẻ.</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/tabstray/src/main/res/values-yo/strings.xml b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-yo/strings.xml
new file mode 100644
index 0000000000..702c4c49ec
--- /dev/null
+++ b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-yo/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Message announced to the user when tab tray is selected with 1 tab -->
+ <string name="mozac_tab_counter_open_tab_tray_single">1 sí táàbù. Fọwọ́ kàn án láti tan táàbù.</string>
+ <!-- Message announced to the user when tab tray is selected with multiple tabs. %1$s is getting replaced with the number of open tabs. -->
+ <string name="mozac_tab_counter_open_tab_tray_plural">%1$s sí táàbù. Fọwọ́ kàn án láti tan táàbù.</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/tabstray/src/main/res/values-zh-rCN/strings.xml b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-zh-rCN/strings.xml
new file mode 100644
index 0000000000..56655683a4
--- /dev/null
+++ b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-zh-rCN/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Message announced to the user when tab tray is selected with 1 tab -->
+ <string name="mozac_tab_counter_open_tab_tray_single">打开了 1 个标签页,点按即可切换。</string>
+ <!-- Message announced to the user when tab tray is selected with multiple tabs. %1$s is getting replaced with the number of open tabs. -->
+ <string name="mozac_tab_counter_open_tab_tray_plural">打开了 %1$s 个标签页,点按即可切换。</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/tabstray/src/main/res/values-zh-rTW/strings.xml b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-zh-rTW/strings.xml
new file mode 100644
index 0000000000..69ffb4a021
--- /dev/null
+++ b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-zh-rTW/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Message announced to the user when tab tray is selected with 1 tab -->
+ <string name="mozac_tab_counter_open_tab_tray_single">開啟了 1 個分頁,點擊即可切換分頁。</string>
+ <!-- Message announced to the user when tab tray is selected with multiple tabs. %1$s is getting replaced with the number of open tabs. -->
+ <string name="mozac_tab_counter_open_tab_tray_plural">開啟了 %1$s 個分頁,點擊即可切換分頁。</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/tabstray/src/main/res/values/strings.xml b/mobile/android/android-components/components/compose/tabstray/src/main/res/values/strings.xml
new file mode 100644
index 0000000000..961847b251
--- /dev/null
+++ b/mobile/android/android-components/components/compose/tabstray/src/main/res/values/strings.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- This Source Code Form is subject to the terms of the Mozilla Public
+ - License, v. 2.0. If a copy of the MPL was not distributed with this
+ - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
+<resources>
+ <!-- Message announced to the user when tab tray is selected with 1 tab -->
+ <string name="mozac_tab_counter_open_tab_tray_single">1 open tab. Tap to switch tabs.</string>
+ <!-- Message announced to the user when tab tray is selected with multiple tabs. %1$s is getting replaced with the number of open tabs. -->
+ <string name="mozac_tab_counter_open_tab_tray_plural">%1$s open tabs. Tap to switch tabs.</string>
+</resources>
diff --git a/mobile/android/android-components/components/compose/tabstray/src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker b/mobile/android/android-components/components/compose/tabstray/src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker
new file mode 100644
index 0000000000..cf1c399ea8
--- /dev/null
+++ b/mobile/android/android-components/components/compose/tabstray/src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker
@@ -0,0 +1,2 @@
+mock-maker-inline
+// This allows mocking final classes (classes are final by default in Kotlin)
diff --git a/mobile/android/android-components/components/compose/tabstray/src/test/resources/robolectric.properties b/mobile/android/android-components/components/compose/tabstray/src/test/resources/robolectric.properties
new file mode 100644
index 0000000000..932b01b9eb
--- /dev/null
+++ b/mobile/android/android-components/components/compose/tabstray/src/test/resources/robolectric.properties
@@ -0,0 +1 @@
+sdk=28