summaryrefslogtreecommitdiffstats
path: root/mobile/android/android-components/components/feature/search/src
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-15 03:35:49 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-15 03:35:49 +0000
commitd8bbc7858622b6d9c278469aab701ca0b609cddf (patch)
treeeff41dc61d9f714852212739e6b3738b82a2af87 /mobile/android/android-components/components/feature/search/src
parentReleasing progress-linux version 125.0.3-1~progress7.99u1. (diff)
downloadfirefox-d8bbc7858622b6d9c278469aab701ca0b609cddf.tar.xz
firefox-d8bbc7858622b6d9c278469aab701ca0b609cddf.zip
Merging upstream version 126.0.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'mobile/android/android-components/components/feature/search/src')
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/AndroidManifest.xml4
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/assets/extensions/ads/adsTelemetry.js82
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/assets/extensions/ads/manifest.template.json219
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/assets/extensions/search/manifest.template.json220
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/assets/extensions/search/searchTelemetry.js61
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/assets/search/list.json923
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/assets/search/search_telemetry_v2.json657
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/amazon-au.xml12
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/amazon-ca.xml13
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/amazon-co-uk.xml13
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/amazon-de.xml13
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/amazon-es.xml13
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/amazon-fr.xml13
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/amazon-in.xml13
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/amazon-it.xml13
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/amazon-jp.xml31
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/amazon-nl.xml13
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/amazon-se.xml13
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/amazondotcom.xml13
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/azerdict.xml17
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/baidu.xml25
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/bing.xml24
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/ceneje.xml15
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/coccoc.xml21
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/daum-kr.xml21
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/ddg.xml23
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/ebay-at.xml19
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/ebay-au.xml19
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/ebay-befr.xml19
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/ebay-ca.xml19
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/ebay-ch.xml19
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/ebay-co-uk.xml19
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/ebay-de.xml19
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/ebay-es.xml19
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/ebay-fr.xml19
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/ebay-ie.xml19
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/ebay-it.xml19
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/ebay-nl.xml19
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/ebay-pl.xml18
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/ebay.xml19
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/ecosia.xml18
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/faclair-beag.xml13
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/google-b-1-m.xml17
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/google-b-m.xml17
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/google-com-nocodes.xml14
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/gulesider-mobile-NO.xml15
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/leo_ende_de.xml18
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/mapy-cz.xml14
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/mercadolibre-ar.xml14
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/mercadolibre-cl.xml14
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/mercadolibre-mx.xml14
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/odpiralni.xml15
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/pazaruvaj.xml14
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/prisjakt-sv-SE.xml14
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/qwant.xml18
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/rakuten.xml16
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/reddit.xml11
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/salidzinilv.xml18
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/seznam-cz.xml17
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/vatera.xml17
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-NN.xml18
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-NO.xml18
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-an.xml18
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-ar.xml18
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-as.xml18
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-ast.xml18
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-az.xml18
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-be.xml18
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-bg.xml18
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-bn.xml18
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-br.xml18
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-bs.xml18
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-ca.xml18
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-cy.xml18
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-cz.xml18
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-da.xml18
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-de.xml18
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-dsb.xml18
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-el.xml18
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-eo.xml18
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-es.xml18
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-et.xml18
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-eu.xml18
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-fa.xml18
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-fi.xml18
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-fr.xml18
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-fy-NL.xml18
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-ga-IE.xml18
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-gd.xml18
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-gl.xml18
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-gn.xml18
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-gu.xml18
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-he.xml18
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-hi.xml18
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-hr.xml18
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-hsb.xml18
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-hu.xml18
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-hy-AM.xml18
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-ia.xml18
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-id.xml18
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-is.xml18
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-it.xml18
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-ja.xml18
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-ka.xml18
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-kab.xml18
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-kk.xml18
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-km.xml18
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-kn.xml18
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-lij.xml18
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-lo.xml18
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-lt.xml18
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-ltg.xml18
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-lv.xml18
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-ml.xml18
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-mr.xml18
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-ms.xml18
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-my.xml18
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-ne.xml18
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-nl.xml18
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-oc.xml18
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-or.xml18
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-pa.xml18
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-pl.xml18
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-pt.xml18
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-rm.xml18
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-ro.xml18
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-ru.xml18
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-sk.xml18
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-sl.xml18
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-sq.xml18
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-sr.xml18
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-sv-SE.xml18
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-ta.xml18
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-te.xml18
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-th.xml18
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-tr.xml18
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-uk.xml18
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-ur.xml18
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-uz.xml18
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-vi.xml18
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-wo.xml18
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-zh-CN.xml18
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-zh-TW.xml19
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia.xml18
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wiktionary-kn.xml18
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wiktionary-oc.xml17
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wiktionary-or.xml17
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wiktionary-ta.xml17
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wiktionary-te.xml17
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/yahoo-jp-auctions.xml16
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/yahoo-jp.xml16
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/yandex-en.xml22
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/yandex-ru.xml21
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/yandex-tr.xml22
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/yandex.by.xml22
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/yandex.xml21
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/youtube.xml12
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/java/mozilla/components/feature/search/BrowserStoreSearchAdapter.kt41
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/java/mozilla/components/feature/search/SearchAdapter.kt21
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/java/mozilla/components/feature/search/SearchFeature.kt52
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/java/mozilla/components/feature/search/SearchUseCases.kt343
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/java/mozilla/components/feature/search/ext/BrowserStore.kt36
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/java/mozilla/components/feature/search/ext/SearchEngine.kt148
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/java/mozilla/components/feature/search/internal/SearchUrlBuilder.kt93
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/java/mozilla/components/feature/search/middleware/AdsTelemetryMiddleware.kt77
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/java/mozilla/components/feature/search/middleware/SearchMiddleware.kt397
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/java/mozilla/components/feature/search/region/RegionManager.kt126
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/java/mozilla/components/feature/search/region/RegionMiddleware.kt72
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/java/mozilla/components/feature/search/storage/BundledSearchEnginesStorage.kt278
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/java/mozilla/components/feature/search/storage/CustomSearchEnginesStorage.kt66
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/java/mozilla/components/feature/search/storage/SearchEngineReader.kt243
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/java/mozilla/components/feature/search/storage/SearchEngineWriter.kt115
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/java/mozilla/components/feature/search/storage/SearchMetadataStorage.kt103
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/java/mozilla/components/feature/search/suggestions/Parser.kt79
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/java/mozilla/components/feature/search/suggestions/SearchSuggestionClient.kt101
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/java/mozilla/components/feature/search/telemetry/BaseSearchTelemetry.kt132
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/java/mozilla/components/feature/search/telemetry/ExtensionInfo.kt18
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/java/mozilla/components/feature/search/telemetry/SearchProviderCookie.kt24
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/java/mozilla/components/feature/search/telemetry/SearchProviderModel.kt80
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/java/mozilla/components/feature/search/telemetry/SerpTelemetryRepository.kt170
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/java/mozilla/components/feature/search/telemetry/TrackKeyInfo.kt38
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/java/mozilla/components/feature/search/telemetry/Utils.kt116
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/java/mozilla/components/feature/search/telemetry/ads/AdsTelemetry.kt124
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/java/mozilla/components/feature/search/telemetry/incontent/InContentTelemetry.kt86
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/java/mozilla/components/feature/search/widget/AppSearchWidgetProvider.kt312
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/java/mozilla/components/feature/search/widget/BaseVoiceSearchActivity.kt134
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/res/drawable/mozac_rounded_search_widget_background.xml9
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/res/layout/mozac_search_widget_extra_small_v1.xml20
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/res/layout/mozac_search_widget_extra_small_v2.xml19
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/res/layout/mozac_search_widget_large.xml45
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/res/layout/mozac_search_widget_medium.xml45
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/res/layout/mozac_search_widget_small.xml27
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/res/layout/mozac_search_widget_small_no_mic.xml19
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/res/values-am/strings.xml12
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/res/values-ar/strings.xml12
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/res/values-ast/strings.xml12
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/res/values-azb/strings.xml12
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/res/values-be/strings.xml12
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/res/values-bg/strings.xml12
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/res/values-br/strings.xml12
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/res/values-bs/strings.xml12
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/res/values-ca/strings.xml12
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/res/values-cak/strings.xml12
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/res/values-ckb/strings.xml12
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/res/values-co/strings.xml12
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/res/values-cs/strings.xml12
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/res/values-cy/strings.xml12
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/res/values-da/strings.xml12
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/res/values-de/strings.xml12
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/res/values-dsb/strings.xml12
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/res/values-el/strings.xml12
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/res/values-en-rCA/strings.xml12
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/res/values-en-rGB/strings.xml12
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/res/values-eo/strings.xml12
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/res/values-es-rAR/strings.xml12
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/res/values-es-rCL/strings.xml12
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/res/values-es-rES/strings.xml12
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/res/values-es-rMX/strings.xml12
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/res/values-es/strings.xml12
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/res/values-et/strings.xml12
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/res/values-eu/strings.xml12
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/res/values-fa/strings.xml12
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/res/values-ff/strings.xml8
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/res/values-fi/strings.xml12
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/res/values-fr/strings.xml12
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/res/values-fur/strings.xml12
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/res/values-fy-rNL/strings.xml12
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/res/values-gd/strings.xml12
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/res/values-gl/strings.xml12
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/res/values-gn/strings.xml12
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/res/values-hr/strings.xml12
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/res/values-hsb/strings.xml12
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/res/values-hu/strings.xml12
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/res/values-hy-rAM/strings.xml12
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/res/values-ia/strings.xml12
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/res/values-in/strings.xml12
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/res/values-is/strings.xml12
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/res/values-it/strings.xml12
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/res/values-iw/strings.xml12
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/res/values-ja/strings.xml12
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/res/values-ka/strings.xml12
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/res/values-kaa/strings.xml12
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/res/values-kab/strings.xml12
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/res/values-kk/strings.xml12
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/res/values-kmr/strings.xml12
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/res/values-ko/strings.xml12
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/res/values-lo/strings.xml12
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/res/values-lt/strings.xml12
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/res/values-my/strings.xml12
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/res/values-nb-rNO/strings.xml12
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/res/values-night/colors.xml10
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/res/values-nl/strings.xml12
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/res/values-nn-rNO/strings.xml12
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/res/values-oc/strings.xml12
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/res/values-pa-rIN/strings.xml12
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/res/values-pa-rPK/strings.xml12
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/res/values-pl/strings.xml12
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/res/values-pt-rBR/strings.xml12
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/res/values-pt-rPT/strings.xml12
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/res/values-rm/strings.xml12
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/res/values-ru/strings.xml12
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/res/values-sat/strings.xml12
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/res/values-sc/strings.xml12
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/res/values-si/strings.xml12
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/res/values-sk/strings.xml12
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/res/values-skr/strings.xml12
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/res/values-sl/strings.xml12
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/res/values-sq/strings.xml12
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/res/values-sr/strings.xml12
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/res/values-su/strings.xml12
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/res/values-sv-rSE/strings.xml12
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/res/values-ta/strings.xml12
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/res/values-te/strings.xml7
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/res/values-tg/strings.xml12
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/res/values-th/strings.xml12
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/res/values-tl/strings.xml12
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/res/values-tr/strings.xml12
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/res/values-trs/strings.xml12
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/res/values-tt/strings.xml12
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/res/values-ug/strings.xml12
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/res/values-uk/strings.xml12
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/res/values-uz/strings.xml12
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/res/values-vi/strings.xml12
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/res/values-yo/strings.xml12
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/res/values-zh-rCN/strings.xml12
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/res/values-zh-rTW/strings.xml12
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/res/values/colors.xml9
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/res/values/dimens.xml7
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/res/values/strings.xml16
-rw-r--r--mobile/android/android-components/components/feature/search/src/test/java/mozilla/components/feature/search/BrowserStoreSeachAdapterTest.kt97
-rw-r--r--mobile/android/android-components/components/feature/search/src/test/java/mozilla/components/feature/search/SearchFeatureTest.kt134
-rw-r--r--mobile/android/android-components/components/feature/search/src/test/java/mozilla/components/feature/search/SearchUseCasesTest.kt663
-rw-r--r--mobile/android/android-components/components/feature/search/src/test/java/mozilla/components/feature/search/ext/BrowserStoreKtTest.kt117
-rw-r--r--mobile/android/android-components/components/feature/search/src/test/java/mozilla/components/feature/search/ext/SearchEngineKtTest.kt196
-rw-r--r--mobile/android/android-components/components/feature/search/src/test/java/mozilla/components/feature/search/middleware/AdsTelemetryMiddlewareTest.kt126
-rw-r--r--mobile/android/android-components/components/feature/search/src/test/java/mozilla/components/feature/search/middleware/SearchMiddlewareTest.kt1921
-rw-r--r--mobile/android/android-components/components/feature/search/src/test/java/mozilla/components/feature/search/region/RegionManagerTest.kt146
-rw-r--r--mobile/android/android-components/components/feature/search/src/test/java/mozilla/components/feature/search/region/RegionMiddlewareTest.kt153
-rw-r--r--mobile/android/android-components/components/feature/search/src/test/java/mozilla/components/feature/search/storage/BundledSearchEnginesStorageTest.kt196
-rw-r--r--mobile/android/android-components/components/feature/search/src/test/java/mozilla/components/feature/search/storage/CustomSearchEngineStorageTest.kt105
-rw-r--r--mobile/android/android-components/components/feature/search/src/test/java/mozilla/components/feature/search/storage/ParseSearchPluginsTest.kt106
-rw-r--r--mobile/android/android-components/components/feature/search/src/test/java/mozilla/components/feature/search/storage/SearchEngineReaderTest.kt84
-rw-r--r--mobile/android/android-components/components/feature/search/src/test/java/mozilla/components/feature/search/storage/SearchEngineWriterTest.kt212
-rw-r--r--mobile/android/android-components/components/feature/search/src/test/java/mozilla/components/feature/search/suggestions/ParserTest.kt149
-rw-r--r--mobile/android/android-components/components/feature/search/src/test/java/mozilla/components/feature/search/suggestions/SearchSuggestionClientTest.kt110
-rw-r--r--mobile/android/android-components/components/feature/search/src/test/java/mozilla/components/feature/search/telemetry/BaseSearchTelemetryTest.kt187
-rw-r--r--mobile/android/android-components/components/feature/search/src/test/java/mozilla/components/feature/search/telemetry/SearchProviderModelTest.kt40
-rw-r--r--mobile/android/android-components/components/feature/search/src/test/java/mozilla/components/feature/search/telemetry/SerpTelemetryRepositoryTest.kt92
-rw-r--r--mobile/android/android-components/components/feature/search/src/test/java/mozilla/components/feature/search/telemetry/ads/AdsTelemetryTest.kt271
-rw-r--r--mobile/android/android-components/components/feature/search/src/test/java/mozilla/components/feature/search/telemetry/incontent/InContentTelemetryTest.kt467
-rw-r--r--mobile/android/android-components/components/feature/search/src/test/java/mozilla/components/feature/search/widget/AppSearchWidgetProviderTest.kt159
-rw-r--r--mobile/android/android-components/components/feature/search/src/test/java/mozilla/components/feature/search/widget/BaseVoiceSearchActivityExtendedForTests.kt24
-rw-r--r--mobile/android/android-components/components/feature/search/src/test/java/mozilla/components/feature/search/widget/BaseVoiceSearchActivityTest.kt134
-rw-r--r--mobile/android/android-components/components/feature/search/src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker2
-rw-r--r--mobile/android/android-components/components/feature/search/src/test/resources/robolectric.properties1
315 files changed, 15647 insertions, 0 deletions
diff --git a/mobile/android/android-components/components/feature/search/src/main/AndroidManifest.xml b/mobile/android/android-components/components/feature/search/src/main/AndroidManifest.xml
new file mode 100644
index 0000000000..e16cda1d34
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/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/feature/search/src/main/assets/extensions/ads/adsTelemetry.js b/mobile/android/android-components/components/feature/search/src/main/assets/extensions/ads/adsTelemetry.js
new file mode 100644
index 0000000000..65bf306835
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/assets/extensions/ads/adsTelemetry.js
@@ -0,0 +1,82 @@
+/* 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/. */
+
+/**
+ * Send
+ * - current URL
+ * - cookies of this page
+ * - all links found in this page
+ * to the native application.
+ */
+function sendCurrentState() {
+ let message = {
+ 'url': document.location.href,
+ 'urls': getLinks(),
+ 'cookies': getCookies()
+ };
+ browser.runtime.sendNativeMessage("MozacBrowserAdsMessage", message);
+}
+
+/**
+ * Get all links in the current page.
+ *
+ * @return {Array<string>} containing all current links in the current page.
+ */
+function getLinks() {
+ let urls = [];
+
+ let anchors = document.getElementsByTagName("a");
+ for (let anchor of anchors) {
+ if (!anchor.href) {
+ continue;
+ }
+ urls.push(anchor.href);
+ }
+
+ return urls;
+}
+
+/**
+ * Get all cookies for the current document.
+ *
+ * @return {Array<{name: string, value: string}>} containing all cookies.
+ */
+function getCookies() {
+ let cookiesList = document.cookie.split("; ");
+ let result = [];
+
+ cookiesList.forEach(cookie => {
+ var [name, ...value] = cookie.split('=');
+ // For that special cases where the value contains '='.
+ value = value.join("=")
+
+ result.push({
+ "name" : name,
+ "value" : value
+ });
+ });
+
+ return result;
+}
+
+// Whenever a page is first accessed or when loaded from cache
+// send all needed data about the ads provider to the app.
+const events = ["pageshow", "load"];
+const eventLogger = event => {
+ switch (event.type) {
+ case "load":
+ sendCurrentState();
+ break;
+ case "pageshow":
+ if (event.persisted) {
+ sendCurrentState();
+ }
+ break;
+ default:
+ console.log('Event:', event.type);
+ }
+};
+events.forEach(eventName =>
+ window.addEventListener(eventName, eventLogger)
+);
diff --git a/mobile/android/android-components/components/feature/search/src/main/assets/extensions/ads/manifest.template.json b/mobile/android/android-components/components/feature/search/src/main/assets/extensions/ads/manifest.template.json
new file mode 100644
index 0000000000..219e41b554
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/assets/extensions/ads/manifest.template.json
@@ -0,0 +1,219 @@
+{
+ "manifest_version": 2,
+ "browser_specific_settings": {
+ "gecko": {
+ "id": "ads@mozac.org"
+ }
+ },
+ "name": "Mozilla Android Components - Ads Telemetry",
+ "version": "${version}",
+ "content_scripts": [
+ {
+ "matches": ["https://*/*"],
+ "include_globs": [
+ "https://www.google.com/search*",
+ "https://www.google.ad/search*",
+ "https://www.google.ae/search*",
+ "https://www.google.com.af/search*",
+ "https://www.google.com.ag/search*",
+ "https://www.google.com.ai/search*",
+ "https://www.google.al/search*",
+ "https://www.google.am/search*",
+ "https://www.google.co.ao/search*",
+ "https://www.google.com.ar/search*",
+ "https://www.google.as/search*",
+ "https://www.google.at/search*",
+ "https://www.google.com.au/search*",
+ "https://www.google.az/search*",
+ "https://www.google.ba/search*",
+ "https://www.google.com.bd/search*",
+ "https://www.google.be/search*",
+ "https://www.google.bf/search*",
+ "https://www.google.bg/search*",
+ "https://www.google.com.bh/search*",
+ "https://www.google.bi/search*",
+ "https://www.google.bj/search*",
+ "https://www.google.com.bn/search*",
+ "https://www.google.com.bo/search*",
+ "https://www.google.com.br/search*",
+ "https://www.google.bs/search*",
+ "https://www.google.bt/search*",
+ "https://www.google.co.bw/search*",
+ "https://www.google.by/search*",
+ "https://www.google.com.bz/search*",
+ "https://www.google.ca/search*",
+ "https://www.google.cd/search*",
+ "https://www.google.cf/search*",
+ "https://www.google.cg/search*",
+ "https://www.google.ch/search*",
+ "https://www.google.ci/search*",
+ "https://www.google.co.ck/search*",
+ "https://www.google.cl/search*",
+ "https://www.google.cm/search*",
+ "https://www.google.cn/search*",
+ "https://www.google.com.co/search*",
+ "https://www.google.co.cr/search*",
+ "https://www.google.com.cu/search*",
+ "https://www.google.cv/search*",
+ "https://www.google.com.cy/search*",
+ "https://www.google.cz/search*",
+ "https://www.google.de/search*",
+ "https://www.google.dj/search*",
+ "https://www.google.dk/search*",
+ "https://www.google.dm/search*",
+ "https://www.google.com.do/search*",
+ "https://www.google.dz/search*",
+ "https://www.google.com.ec/search*",
+ "https://www.google.ee/search*",
+ "https://www.google.com.eg/search*",
+ "https://www.google.es/search*",
+ "https://www.google.com.et/search*",
+ "https://www.google.fi/search*",
+ "https://www.google.com.fj/search*",
+ "https://www.google.fm/search*",
+ "https://www.google.fr/search*",
+ "https://www.google.ga/search*",
+ "https://www.google.ge/search*",
+ "https://www.google.gg/search*",
+ "https://www.google.com.gh/search*",
+ "https://www.google.com.gi/search*",
+ "https://www.google.gl/search*",
+ "https://www.google.gm/search*",
+ "https://www.google.gr/search*",
+ "https://www.google.com.gt/search*",
+ "https://www.google.gy/search*",
+ "https://www.google.com.hk/search*",
+ "https://www.google.hn/search*",
+ "https://www.google.hr/search*",
+ "https://www.google.ht/search*",
+ "https://www.google.hu/search*",
+ "https://www.google.co.id/search*",
+ "https://www.google.ie/search*",
+ "https://www.google.co.il/search*",
+ "https://www.google.im/search*",
+ "https://www.google.co.in/search*",
+ "https://www.google.iq/search*",
+ "https://www.google.is/search*",
+ "https://www.google.it/search*",
+ "https://www.google.je/search*",
+ "https://www.google.com.jm/search*",
+ "https://www.google.jo/search*",
+ "https://www.google.co.jp/search*",
+ "https://www.google.co.ke/search*",
+ "https://www.google.com.kh/search*",
+ "https://www.google.ki/search*",
+ "https://www.google.kg/search*",
+ "https://www.google.co.kr/search*",
+ "https://www.google.com.kw/search*",
+ "https://www.google.kz/search*",
+ "https://www.google.la/search*",
+ "https://www.google.com.lb/search*",
+ "https://www.google.li/search*",
+ "https://www.google.lk/search*",
+ "https://www.google.co.ls/search*",
+ "https://www.google.lt/search*",
+ "https://www.google.lu/search*",
+ "https://www.google.lv/search*",
+ "https://www.google.com.ly/search*",
+ "https://www.google.co.ma/search*",
+ "https://www.google.md/search*",
+ "https://www.google.me/search*",
+ "https://www.google.mg/search*",
+ "https://www.google.mk/search*",
+ "https://www.google.ml/search*",
+ "https://www.google.com.mm/search*",
+ "https://www.google.mn/search*",
+ "https://www.google.ms/search*",
+ "https://www.google.com.mt/search*",
+ "https://www.google.mu/search*",
+ "https://www.google.mv/search*",
+ "https://www.google.mw/search*",
+ "https://www.google.com.mx/search*",
+ "https://www.google.com.my/search*",
+ "https://www.google.co.mz/search*",
+ "https://www.google.com.na/search*",
+ "https://www.google.com.ng/search*",
+ "https://www.google.com.ni/search*",
+ "https://www.google.ne/search*",
+ "https://www.google.nl/search*",
+ "https://www.google.no/search*",
+ "https://www.google.com.np/search*",
+ "https://www.google.nr/search*",
+ "https://www.google.nu/search*",
+ "https://www.google.co.nz/search*",
+ "https://www.google.com.om/search*",
+ "https://www.google.com.pa/search*",
+ "https://www.google.com.pe/search*",
+ "https://www.google.com.pg/search*",
+ "https://www.google.com.ph/search*",
+ "https://www.google.com.pk/search*",
+ "https://www.google.pl/search*",
+ "https://www.google.pn/search*",
+ "https://www.google.com.pr/search*",
+ "https://www.google.ps/search*",
+ "https://www.google.pt/search*",
+ "https://www.google.com.py/search*",
+ "https://www.google.com.qa/search*",
+ "https://www.google.ro/search*",
+ "https://www.google.ru/search*",
+ "https://www.google.rw/search*",
+ "https://www.google.com.sa/search*",
+ "https://www.google.com.sb/search*",
+ "https://www.google.sc/search*",
+ "https://www.google.se/search*",
+ "https://www.google.com.sg/search*",
+ "https://www.google.sh/search*",
+ "https://www.google.si/search*",
+ "https://www.google.sk/search*",
+ "https://www.google.com.sl/search*",
+ "https://www.google.sn/search*",
+ "https://www.google.so/search*",
+ "https://www.google.sm/search*",
+ "https://www.google.sr/search*",
+ "https://www.google.st/search*",
+ "https://www.google.com.sv/search*",
+ "https://www.google.td/search*",
+ "https://www.google.tg/search*",
+ "https://www.google.co.th/search*",
+ "https://www.google.com.tj/search*",
+ "https://www.google.tl/search*",
+ "https://www.google.tm/search*",
+ "https://www.google.tn/search*",
+ "https://www.google.to/search*",
+ "https://www.google.com.tr/search*",
+ "https://www.google.tt/search*",
+ "https://www.google.com.tw/search*",
+ "https://www.google.co.tz/search*",
+ "https://www.google.com.ua/search*",
+ "https://www.google.co.ug/search*",
+ "https://www.google.co.uk/search*",
+ "https://www.google.com.uy/search*",
+ "https://www.google.co.uz/search*",
+ "https://www.google.com.vc/search*",
+ "https://www.google.co.ve/search*",
+ "https://www.google.vg/search*",
+ "https://www.google.co.vi/search*",
+ "https://www.google.com.vn/search*",
+ "https://www.google.vu/search*",
+ "https://www.google.ws/search*",
+ "https://www.google.rs/search*",
+ "https://www.google.co.za/search*",
+ "https://www.google.co.zm/search*",
+ "https://www.google.co.zw/search*",
+ "https://www.google.cat/search*",
+ "https://www.bing.com/search*",
+ "https://www.baidu.com/*",
+ "https://m.baidu.com/*",
+ "https://duckduckgo.com/*",
+ "https://www.ecosia.org/*"
+ ],
+ "js": ["adsTelemetry.js"],
+ "run_at": "document_end"
+ }
+ ],
+ "permissions": [
+ "geckoViewAddons",
+ "nativeMessaging",
+ "nativeMessagingFromContent"
+ ]
+}
diff --git a/mobile/android/android-components/components/feature/search/src/main/assets/extensions/search/manifest.template.json b/mobile/android/android-components/components/feature/search/src/main/assets/extensions/search/manifest.template.json
new file mode 100644
index 0000000000..ae9cf13dac
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/assets/extensions/search/manifest.template.json
@@ -0,0 +1,220 @@
+{
+ "manifest_version": 2,
+ "browser_specific_settings": {
+ "gecko": {
+ "id": "cookies@mozac.org"
+ }
+ },
+ "name": "Mozilla Android Components - Search Telemetry",
+ "version": "${version}",
+ "content_scripts": [
+ {
+ "matches": ["https://*/*"],
+ "include_globs": [
+ "https://www.google.com/search*",
+ "https://www.google.ad/search*",
+ "https://www.google.ae/search*",
+ "https://www.google.com.af/search*",
+ "https://www.google.com.ag/search*",
+ "https://www.google.com.ai/search*",
+ "https://www.google.al/search*",
+ "https://www.google.am/search*",
+ "https://www.google.co.ao/search*",
+ "https://www.google.com.ar/search*",
+ "https://www.google.as/search*",
+ "https://www.google.at/search*",
+ "https://www.google.com.au/search*",
+ "https://www.google.az/search*",
+ "https://www.google.ba/search*",
+ "https://www.google.com.bd/search*",
+ "https://www.google.be/search*",
+ "https://www.google.bf/search*",
+ "https://www.google.bg/search*",
+ "https://www.google.com.bh/search*",
+ "https://www.google.bi/search*",
+ "https://www.google.bj/search*",
+ "https://www.google.com.bn/search*",
+ "https://www.google.com.bo/search*",
+ "https://www.google.com.br/search*",
+ "https://www.google.bs/search*",
+ "https://www.google.bt/search*",
+ "https://www.google.co.bw/search*",
+ "https://www.google.by/search*",
+ "https://www.google.com.bz/search*",
+ "https://www.google.ca/search*",
+ "https://www.google.cd/search*",
+ "https://www.google.cf/search*",
+ "https://www.google.cg/search*",
+ "https://www.google.ch/search*",
+ "https://www.google.ci/search*",
+ "https://www.google.co.ck/search*",
+ "https://www.google.cl/search*",
+ "https://www.google.cm/search*",
+ "https://www.google.cn/search*",
+ "https://www.google.com.co/search*",
+ "https://www.google.co.cr/search*",
+ "https://www.google.com.cu/search*",
+ "https://www.google.cv/search*",
+ "https://www.google.com.cy/search*",
+ "https://www.google.cz/search*",
+ "https://www.google.de/search*",
+ "https://www.google.dj/search*",
+ "https://www.google.dk/search*",
+ "https://www.google.dm/search*",
+ "https://www.google.com.do/search*",
+ "https://www.google.dz/search*",
+ "https://www.google.com.ec/search*",
+ "https://www.google.ee/search*",
+ "https://www.google.com.eg/search*",
+ "https://www.google.es/search*",
+ "https://www.google.com.et/search*",
+ "https://www.google.fi/search*",
+ "https://www.google.com.fj/search*",
+ "https://www.google.fm/search*",
+ "https://www.google.fr/search*",
+ "https://www.google.ga/search*",
+ "https://www.google.ge/search*",
+ "https://www.google.gg/search*",
+ "https://www.google.com.gh/search*",
+ "https://www.google.com.gi/search*",
+ "https://www.google.gl/search*",
+ "https://www.google.gm/search*",
+ "https://www.google.gr/search*",
+ "https://www.google.com.gt/search*",
+ "https://www.google.gy/search*",
+ "https://www.google.com.hk/search*",
+ "https://www.google.hn/search*",
+ "https://www.google.hr/search*",
+ "https://www.google.ht/search*",
+ "https://www.google.hu/search*",
+ "https://www.google.co.id/search*",
+ "https://www.google.ie/search*",
+ "https://www.google.co.il/search*",
+ "https://www.google.im/search*",
+ "https://www.google.co.in/search*",
+ "https://www.google.iq/search*",
+ "https://www.google.is/search*",
+ "https://www.google.it/search*",
+ "https://www.google.je/search*",
+ "https://www.google.com.jm/search*",
+ "https://www.google.jo/search*",
+ "https://www.google.co.jp/search*",
+ "https://www.google.co.ke/search*",
+ "https://www.google.com.kh/search*",
+ "https://www.google.ki/search*",
+ "https://www.google.kg/search*",
+ "https://www.google.co.kr/search*",
+ "https://www.google.com.kw/search*",
+ "https://www.google.kz/search*",
+ "https://www.google.la/search*",
+ "https://www.google.com.lb/search*",
+ "https://www.google.li/search*",
+ "https://www.google.lk/search*",
+ "https://www.google.co.ls/search*",
+ "https://www.google.lt/search*",
+ "https://www.google.lu/search*",
+ "https://www.google.lv/search*",
+ "https://www.google.com.ly/search*",
+ "https://www.google.co.ma/search*",
+ "https://www.google.md/search*",
+ "https://www.google.me/search*",
+ "https://www.google.mg/search*",
+ "https://www.google.mk/search*",
+ "https://www.google.ml/search*",
+ "https://www.google.com.mm/search*",
+ "https://www.google.mn/search*",
+ "https://www.google.ms/search*",
+ "https://www.google.com.mt/search*",
+ "https://www.google.mu/search*",
+ "https://www.google.mv/search*",
+ "https://www.google.mw/search*",
+ "https://www.google.com.mx/search*",
+ "https://www.google.com.my/search*",
+ "https://www.google.co.mz/search*",
+ "https://www.google.com.na/search*",
+ "https://www.google.com.ng/search*",
+ "https://www.google.com.ni/search*",
+ "https://www.google.ne/search*",
+ "https://www.google.nl/search*",
+ "https://www.google.no/search*",
+ "https://www.google.com.np/search*",
+ "https://www.google.nr/search*",
+ "https://www.google.nu/search*",
+ "https://www.google.co.nz/search*",
+ "https://www.google.com.om/search*",
+ "https://www.google.com.pa/search*",
+ "https://www.google.com.pe/search*",
+ "https://www.google.com.pg/search*",
+ "https://www.google.com.ph/search*",
+ "https://www.google.com.pk/search*",
+ "https://www.google.pl/search*",
+ "https://www.google.pn/search*",
+ "https://www.google.com.pr/search*",
+ "https://www.google.ps/search*",
+ "https://www.google.pt/search*",
+ "https://www.google.com.py/search*",
+ "https://www.google.com.qa/search*",
+ "https://www.google.ro/search*",
+ "https://www.google.ru/search*",
+ "https://www.google.rw/search*",
+ "https://www.google.com.sa/search*",
+ "https://www.google.com.sb/search*",
+ "https://www.google.sc/search*",
+ "https://www.google.se/search*",
+ "https://www.google.com.sg/search*",
+ "https://www.google.sh/search*",
+ "https://www.google.si/search*",
+ "https://www.google.sk/search*",
+ "https://www.google.com.sl/search*",
+ "https://www.google.sn/search*",
+ "https://www.google.so/search*",
+ "https://www.google.sm/search*",
+ "https://www.google.sr/search*",
+ "https://www.google.st/search*",
+ "https://www.google.com.sv/search*",
+ "https://www.google.td/search*",
+ "https://www.google.tg/search*",
+ "https://www.google.co.th/search*",
+ "https://www.google.com.tj/search*",
+ "https://www.google.tl/search*",
+ "https://www.google.tm/search*",
+ "https://www.google.tn/search*",
+ "https://www.google.to/search*",
+ "https://www.google.com.tr/search*",
+ "https://www.google.tt/search*",
+ "https://www.google.com.tw/search*",
+ "https://www.google.co.tz/search*",
+ "https://www.google.com.ua/search*",
+ "https://www.google.co.ug/search*",
+ "https://www.google.co.uk/search*",
+ "https://www.google.com.uy/search*",
+ "https://www.google.co.uz/search*",
+ "https://www.google.com.vc/search*",
+ "https://www.google.co.ve/search*",
+ "https://www.google.vg/search*",
+ "https://www.google.co.vi/search*",
+ "https://www.google.com.vn/search*",
+ "https://www.google.vu/search*",
+ "https://www.google.ws/search*",
+ "https://www.google.rs/search*",
+ "https://www.google.co.za/search*",
+ "https://www.google.co.zm/search*",
+ "https://www.google.co.zw/search*",
+ "https://www.google.cat/search*",
+ "https://www.baidu.com/*",
+ "https://m.baidu.com/*",
+ "https://*search.yahoo.com/search*",
+ "https://www.bing.com/search*",
+ "https://duckduckgo.com/*",
+ "https://www.ecosia.org/*"
+ ],
+ "js": ["searchTelemetry.js"],
+ "run_at": "document_end"
+ }
+ ],
+ "permissions": [
+ "geckoViewAddons",
+ "nativeMessaging",
+ "nativeMessagingFromContent"
+ ]
+}
diff --git a/mobile/android/android-components/components/feature/search/src/main/assets/extensions/search/searchTelemetry.js b/mobile/android/android-components/components/feature/search/src/main/assets/extensions/search/searchTelemetry.js
new file mode 100644
index 0000000000..3199335fdf
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/assets/extensions/search/searchTelemetry.js
@@ -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/. */
+
+/**
+ * Send
+ * - current URL
+ * - cookies of this page
+ * to the native application.
+ */
+function sendCurrentState() {
+ let message = {
+ 'url': document.location.href,
+ 'cookies': getCookies()
+ };
+ browser.runtime.sendNativeMessage("MozacBrowserSearchMessage", message);
+}
+
+/**
+ * Get all cookies for the current document.
+ *
+ * @return {Array<{name: string, value: string}>} containing all cookies.
+ */
+function getCookies() {
+ let cookiesList = document.cookie.split("; ");
+ let result = [];
+
+ cookiesList.forEach(cookie => {
+ var [name, ...value] = cookie.split('=');
+ // For that special cases where the cookie value contains '='.
+ value = value.join("=");
+
+ result.push({
+ "name" : name,
+ "value" : value
+ });
+ });
+
+ return result;
+}
+
+// Whenever a page is first accessed or when loaded from cache
+// send all needed data about the search provider to the app.
+const events = ["pageshow", "load"];
+const eventLogger = event => {
+ switch (event.type) {
+ case "load":
+ sendCurrentState();
+ break;
+ case "pageshow":
+ if (event.persisted) {
+ sendCurrentState();
+ }
+ break;
+ default:
+ console.log('Event:', event.type);
+ }
+};
+events.forEach(eventName =>
+ window.addEventListener(eventName, eventLogger)
+);
diff --git a/mobile/android/android-components/components/feature/search/src/main/assets/search/list.json b/mobile/android/android-components/components/feature/search/src/main/assets/search/list.json
new file mode 100644
index 0000000000..b2bb3d4698
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/assets/search/list.json
@@ -0,0 +1,923 @@
+{
+ "default": {
+ "searchDefault": "Google",
+ "searchOrder": ["Google", "Bing"],
+ "visibleDefaultEngines": [
+ "google-b-m", "bing", "amazondotcom", "ddg", "wikipedia"
+ ]
+ },
+ "regionOverrides": {
+ "US": {
+ "google-b-m": "google-b-1-m"
+ }
+ },
+ "locales": {
+ "ach": {
+ "default": {
+ "visibleDefaultEngines": [
+ "google-b-m", "bing", "ddg", "wikipedia"
+ ]
+ }
+ },
+ "an": {
+ "default": {
+ "visibleDefaultEngines": [
+ "google-b-m", "bing", "ddg", "ebay-es","wikipedia-an"
+ ]
+ }
+ },
+ "ar": {
+ "default": {
+ "visibleDefaultEngines": [
+ "google-b-m", "bing", "amazondotcom", "ddg", "wikipedia-ar"
+ ]
+ }
+ },
+ "as": {
+ "default": {
+ "visibleDefaultEngines": [
+ "google-b-m", "bing", "amazon-in", "ddg", "wikipedia-as"
+ ]
+ }
+ },
+ "ast": {
+ "default": {
+ "visibleDefaultEngines": [
+ "google-b-m", "bing", "amazondotcom", "ddg", "ebay-es", "wikipedia-ast"
+ ]
+ }
+ },
+ "az": {
+ "default": {
+ "visibleDefaultEngines": [
+ "google-b-m", "bing", "amazondotcom", "ddg", "azerdict", "wikipedia-az"
+ ]
+ }
+ },
+ "be": {
+ "default": {
+ "visibleDefaultEngines": [
+ "google-b-m", "bing", "ddg", "wikipedia-be"
+ ]
+ },
+ "BY": {
+ "visibleDefaultEngines": [
+ "google-com-nocodes", "bing", "ddg", "wikipedia-be"
+ ]
+ },
+ "KZ": {
+ "visibleDefaultEngines": [
+ "google-com-nocodes", "bing", "ddg", "wikipedia-be"
+ ]
+ },
+ "RU": {
+ "visibleDefaultEngines": [
+ "google-com-nocodes", "bing", "ddg", "wikipedia-be"
+ ]
+ },
+ "TR": {
+ "visibleDefaultEngines": [
+ "google-com-nocodes", "bing", "ddg", "wikipedia-be"
+ ]
+ }
+ },
+ "bg": {
+ "default": {
+ "visibleDefaultEngines": [
+ "google-b-m", "bing", "ddg", "pazaruvaj", "wikipedia-bg"
+ ]
+ }
+ },
+ "bn": {
+ "default": {
+ "visibleDefaultEngines": [
+ "google-b-m", "bing", "ddg", "wikipedia-bn"
+ ]
+ }
+ },
+ "bn-BD": {
+ "default": {
+ "visibleDefaultEngines": [
+ "google-b-m", "bing", "ddg", "wikipedia-bn"
+ ]
+ }
+ },
+ "bn-IN": {
+ "default": {
+ "visibleDefaultEngines": [
+ "google-b-m", "bing", "amazondotcom", "ddg", "wikipedia-bn"
+ ]
+ }
+ },
+ "br": {
+ "default": {
+ "visibleDefaultEngines": [
+ "google-b-m", "bing", "ddg", "wikipedia-br"
+ ]
+ }
+ },
+ "bs": {
+ "default": {
+ "visibleDefaultEngines": [
+ "google-b-m", "bing", "ddg", "wikipedia-bs"
+ ]
+ }
+ },
+ "ca": {
+ "default": {
+ "visibleDefaultEngines": [
+ "google-b-m", "bing", "ddg", "ebay-es", "wikipedia-ca"
+ ]
+ }
+ },
+ "cak": {
+ "default": {
+ "visibleDefaultEngines": [
+ "google-b-m", "bing", "amazondotcom", "ddg", "wikipedia-es"
+ ]
+ }
+ },
+ "cs": {
+ "default": {
+ "visibleDefaultEngines": [
+ "google-b-m", "bing", "ddg", "mapy-cz", "seznam-cz", "wikipedia-cz"
+ ]
+ }
+ },
+ "cy": {
+ "default": {
+ "visibleDefaultEngines": [
+ "google-b-m", "bing", "amazon-co-uk", "ddg", "ebay-co-uk", "wikipedia-cy"
+ ]
+ }
+ },
+ "da": {
+ "default": {
+ "visibleDefaultEngines": [
+ "google-b-m", "amazon-co-uk", "bing", "ddg", "wikipedia-da"
+ ]
+ }
+ },
+ "de": {
+ "default": {
+ "visibleDefaultEngines": [
+ "google-b-m", "bing", "amazon-de", "ddg", "ecosia", "qwant", "wikipedia-de", "ebay-de"
+ ]
+ }
+ },
+ "de-AT": {
+ "default": {
+ "visibleDefaultEngines": [
+ "google-b-m", "bing", "amazon-de", "ddg", "ecosia", "qwant", "wikipedia-de", "ebay-at"
+ ]
+ }
+ },
+ "dsb": {
+ "default": {
+ "visibleDefaultEngines": [
+ "google-b-m", "bing", "amazon-de", "ddg", "wikipedia-dsb", "ebay-de"
+ ]
+ }
+ },
+ "el": {
+ "default": {
+ "visibleDefaultEngines": [
+ "google-b-m", "bing", "ddg", "wikipedia-el"
+ ]
+ }
+ },
+ "en-AU": {
+ "default": {
+ "visibleDefaultEngines": [
+ "google-b-m", "bing", "amazon-au", "ddg", "wikipedia", "ebay-au"
+ ]
+ }
+ },
+ "en-CA": {
+ "default": {
+ "visibleDefaultEngines": [
+ "google-b-m", "bing", "amazon-ca", "ddg", "wikipedia", "ebay-ca"
+ ]
+ }
+ },
+ "en-IE": {
+ "default": {
+ "visibleDefaultEngines": [
+ "google-b-m", "bing", "amazon-co-uk", "ddg", "qwant", "wikipedia", "ebay-ie"
+ ]
+ }
+ },
+ "en-GB": {
+ "default": {
+ "visibleDefaultEngines": [
+ "google-b-m", "bing", "amazon-co-uk", "ddg", "qwant", "wikipedia", "ebay-co-uk"
+ ]
+ },
+ "BY": {
+ "visibleDefaultEngines": [
+ "google-com-nocodes", "bing", "amazon-co-uk", "ddg", "qwant", "wikipedia"
+ ]
+ },
+ "KZ": {
+ "visibleDefaultEngines": [
+ "google-com-nocodes", "bing", "amazon-co-uk", "ddg", "qwant", "wikipedia"
+ ]
+ },
+ "RU": {
+ "visibleDefaultEngines": [
+ "google-com-nocodes", "bing", "amazon-co-uk", "ddg", "qwant", "wikipedia"
+ ]
+ },
+ "TR": {
+ "visibleDefaultEngines": [
+ "google-com-nocodes", "bing", "amazon-co-uk", "ddg", "qwant", "wikipedia"
+ ]
+ }
+ },
+ "en-US": {
+ "default": {
+ "visibleDefaultEngines": [
+ "google-b-m", "bing", "amazondotcom", "ddg", "ebay", "wikipedia"
+ ]
+ },
+ "BY": {
+ "visibleDefaultEngines": [
+ "google-com-nocodes", "bing", "amazondotcom", "ddg", "wikipedia"
+ ]
+ },
+ "KZ": {
+ "visibleDefaultEngines": [
+ "google-com-nocodes", "bing", "amazondotcom", "ddg", "wikipedia"
+ ]
+ },
+ "RU": {
+ "visibleDefaultEngines": [
+ "google-com-nocodes", "bing", "amazondotcom", "ddg", "wikipedia"
+ ]
+ },
+ "TR": {
+ "visibleDefaultEngines": [
+ "google-com-nocodes", "bing", "amazondotcom", "ddg", "wikipedia"
+ ]
+ }
+ },
+ "en-ZA": {
+ "default": {
+ "visibleDefaultEngines": [
+ "google-b-m", "ddg", "wikipedia"
+ ]
+ }
+ },
+ "eo": {
+ "default": {
+ "visibleDefaultEngines": [
+ "google-b-m", "bing", "ddg", "wikipedia-eo"
+ ]
+ }
+ },
+ "es-AR": {
+ "default": {
+ "visibleDefaultEngines": [
+ "google-b-m", "ddg", "mercadolibre-ar", "wikipedia-es"
+ ]
+ }
+ },
+ "es-CL": {
+ "default": {
+ "visibleDefaultEngines": [
+ "google-b-m", "bing", "ddg", "mercadolibre-cl", "wikipedia-es"
+ ]
+ }
+ },
+ "es-ES": {
+ "default": {
+ "visibleDefaultEngines": [
+ "google-b-m", "bing", "ddg", "wikipedia-es", "amazon-es", "ebay-es"
+ ]
+ }
+ },
+ "es-MX": {
+ "default": {
+ "visibleDefaultEngines": [
+ "google-b-m", "bing", "amazondotcom", "ddg", "mercadolibre-mx", "wikipedia-es"
+ ]
+ }
+ },
+ "et": {
+ "default": {
+ "visibleDefaultEngines": [
+ "google-b-m", "amazon-co-uk", "ddg", "wikipedia-et"
+ ]
+ }
+ },
+ "eu": {
+ "default": {
+ "visibleDefaultEngines": [
+ "google-b-m", "bing", "ddg", "ebay-es", "wikipedia-eu"
+ ]
+ }
+ },
+ "fa": {
+ "default": {
+ "visibleDefaultEngines": [
+ "google-b-m", "bing", "ddg", "wikipedia-fa"
+ ]
+ }
+ },
+ "ff": {
+ "default": {
+ "visibleDefaultEngines": [
+ "google-b-m", "bing", "amazon-fr", "ddg", "wikipedia-fr"
+ ]
+ }
+ },
+ "fi": {
+ "default": {
+ "visibleDefaultEngines": [
+ "google-b-m", "amazondotcom", "bing", "ddg", "wikipedia-fi"
+ ]
+ }
+ },
+ "fr-BE": {
+ "default": {
+ "visibleDefaultEngines": [
+ "google-b-m", "bing", "ddg", "qwant", "wikipedia-fr", "ebay-befr"
+ ]
+ }
+ },
+ "fr-CA": {
+ "default": {
+ "visibleDefaultEngines": [
+ "google-b-m", "bing", "amazon-ca", "ddg", "wikipedia-fr", "ebay-ca"
+ ]
+ }
+ },
+ "fr-FR": {
+ "default": {
+ "visibleDefaultEngines": [
+ "google-b-m", "bing", "ddg", "qwant", "wikipedia-fr", "amazon-fr", "ebay-fr"
+ ]
+ }
+ },
+ "fr": {
+ "default": {
+ "visibleDefaultEngines": [
+ "google-b-m", "bing", "ddg", "ebay-fr", "qwant", "wikipedia-fr"
+ ]
+ }
+ },
+ "fy-NL": {
+ "default": {
+ "visibleDefaultEngines": [
+ "google-b-m", "bing", "ddg", "ebay-nl", "wikipedia-fy-NL"
+ ]
+ }
+ },
+ "ga-IE": {
+ "default": {
+ "visibleDefaultEngines": [
+ "google-b-m", "amazon-co-uk", "ddg", "ebay-ie", "wikipedia-ga-IE"
+ ]
+ }
+ },
+ "gd": {
+ "default": {
+ "visibleDefaultEngines": [
+ "google-b-m", "bing", "ddg", "ebay-co-uk", "faclair-beag", "wikipedia-gd"
+ ]
+ }
+ },
+ "gl": {
+ "default": {
+ "visibleDefaultEngines": [
+ "google-b-m", "bing", "amazondotcom", "ddg", "ebay-es", "wikipedia-gl"
+ ]
+ }
+ },
+ "gn": {
+ "default": {
+ "visibleDefaultEngines": [
+ "google-b-m", "bing", "amazondotcom", "ddg", "wikipedia-gn"
+ ]
+ }
+ },
+ "gu-IN": {
+ "default": {
+ "visibleDefaultEngines": [
+ "google-b-m", "bing", "amazon-in", "ddg", "wikipedia-gu"
+ ]
+ }
+ },
+ "he": {
+ "default": {
+ "visibleDefaultEngines": [
+ "google-b-m", "bing", "amazondotcom", "ddg", "wikipedia-he"
+ ]
+ }
+ },
+ "hi-IN": {
+ "default": {
+ "visibleDefaultEngines": [
+ "google-b-m", "bing", "amazon-in", "ddg", "wikipedia-hi"
+ ]
+ }
+ },
+ "hr": {
+ "default": {
+ "visibleDefaultEngines": [
+ "google-b-m", "bing", "amazon-co-uk", "ddg", "wikipedia-hr"
+ ]
+ }
+ },
+ "hsb": {
+ "default": {
+ "visibleDefaultEngines": [
+ "google-b-m", "bing", "amazon-de", "ddg", "wikipedia-hsb", "ebay-de"
+ ]
+ }
+ },
+ "hu": {
+ "default": {
+ "visibleDefaultEngines": [
+ "google-b-m", "ddg", "vatera", "wikipedia-hu"
+ ]
+ }
+ },
+ "hy-AM": {
+ "default": {
+ "visibleDefaultEngines": [
+ "google-b-m", "bing", "amazondotcom", "ddg", "wikipedia-hy-AM"
+ ]
+ }
+ },
+ "ia": {
+ "default": {
+ "visibleDefaultEngines": [
+ "google-b-m", "bing", "amazondotcom", "ddg", "wikipedia-ia"
+ ]
+ }
+ },
+ "id": {
+ "default": {
+ "visibleDefaultEngines": [
+ "google-b-m", "bing", "ddg", "wikipedia-id"
+ ]
+ }
+ },
+ "is": {
+ "default": {
+ "visibleDefaultEngines": [
+ "google-b-m", "bing", "amazondotcom", "ddg", "wikipedia-is"
+ ]
+ }
+ },
+ "it": {
+ "default": {
+ "visibleDefaultEngines": [
+ "google-b-m", "bing", "ddg", "wikipedia-it", "amazon-it", "ebay-it"
+ ]
+ }
+ },
+ "ja": {
+ "default": {
+ "visibleDefaultEngines": [
+ "google-b-m", "amazon-jp", "bing", "ddg", "rakuten", "wikipedia-ja", "yahoo-jp", "yahoo-jp-auctions"
+ ]
+ }
+ },
+ "ka": {
+ "default": {
+ "visibleDefaultEngines": [
+ "google-b-m", "bing", "amazondotcom", "ddg", "wikipedia-ka"
+ ]
+ }
+ },
+ "kab": {
+ "default": {
+ "visibleDefaultEngines": [
+ "google-b-m", "bing", "ddg", "wikipedia-kab"
+ ]
+ }
+ },
+ "kk": {
+ "default": {
+ "visibleDefaultEngines": [
+ "google-b-m", "bing", "ddg", "wikipedia-kk"
+ ]
+ },
+ "KZ": {
+ "visibleDefaultEngines": [
+ "google-com-nocodes", "bing", "ddg", "wikipedia-kk"
+ ]
+ },
+ "BY": {
+ "visibleDefaultEngines": [
+ "google-com-nocodes", "bing", "ddg", "wikipedia-kk"
+ ]
+ },
+ "RU": {
+ "visibleDefaultEngines": [
+ "google-com-nocodes", "bing", "ddg", "wikipedia-kk"
+ ]
+ },
+ "TR": {
+ "visibleDefaultEngines": [
+ "google-com-nocodes", "bing", "ddg", "wikipedia-kk"
+ ]
+ }
+ },
+ "km": {
+ "default": {
+ "visibleDefaultEngines": [
+ "google-b-m", "bing", "amazondotcom", "ddg", "wikipedia-km"
+ ]
+ }
+ },
+ "kn": {
+ "default": {
+ "visibleDefaultEngines": [
+ "google-b-m", "bing", "amazon-in", "ddg", "wikipedia-kn", "wiktionary-kn"
+ ]
+ }
+ },
+ "ko": {
+ "default": {
+ "visibleDefaultEngines": [
+ "google-b-m", "ddg", "daum-kr"
+ ]
+ }
+ },
+ "lij": {
+ "default": {
+ "visibleDefaultEngines": [
+ "google-b-m", "bing", "amazon-it", "ddg", "wikipedia-lij", "ebay-it"
+ ]
+ }
+ },
+ "lo": {
+ "default": {
+ "visibleDefaultEngines": [
+ "google-b-m", "bing", "ddg", "wikipedia-lo"
+ ]
+ }
+ },
+ "lt": {
+ "default": {
+ "visibleDefaultEngines": [
+ "google-b-m", "bing", "ddg", "wikipedia-lt"
+ ]
+ }
+ },
+ "ltg": {
+ "default": {
+ "visibleDefaultEngines": [
+ "google-b-m", "bing", "amazon-co-uk", "wikipedia-ltg"
+ ]
+ }
+ },
+ "lv": {
+ "default": {
+ "visibleDefaultEngines": [
+ "google-b-m", "ddg", "salidzinilv", "wikipedia-lv"
+ ]
+ }
+ },
+ "mai": {
+ "default": {
+ "visibleDefaultEngines": [
+ "google-b-m", "bing", "amazon-in", "ddg", "wikipedia-hi"
+ ]
+ }
+ },
+ "meh": {
+ "default": {
+ "visibleDefaultEngines": [
+ "google-b-m", "bing", "amazondotcom", "ddg", "wikipedia-es"
+ ]
+ }
+ },
+ "mix": {
+ "default": {
+ "visibleDefaultEngines": [
+ "google-b-m", "bing", "amazondotcom", "ddg", "wikipedia-es"
+ ]
+ }
+ },
+ "ml": {
+ "default": {
+ "visibleDefaultEngines": [
+ "google-b-m", "bing", "ddg", "wikipedia-ml"
+ ]
+ }
+ },
+ "mr": {
+ "default": {
+ "visibleDefaultEngines": [
+ "google-b-m", "bing", "amazon-in", "ddg", "wikipedia-mr"
+ ]
+ }
+ },
+ "ms": {
+ "default": {
+ "visibleDefaultEngines": [
+ "google-b-m", "bing", "amazondotcom", "ddg", "wikipedia-ms"
+ ]
+ }
+ },
+ "my": {
+ "default": {
+ "visibleDefaultEngines": [
+ "google-b-m", "bing", "amazondotcom", "ddg", "wikipedia-my"
+ ]
+ }
+ },
+ "nb-NO": {
+ "default": {
+ "visibleDefaultEngines": [
+ "google-b-m", "bing", "ddg", "gulesider-mobile-NO", "wikipedia-NO"
+ ]
+ }
+ },
+ "ne-NP": {
+ "default": {
+ "visibleDefaultEngines": [
+ "google-b-m", "bing", "ddg", "wikipedia-ne"
+ ]
+ }
+ },
+ "nl-NL": {
+ "default": {
+ "visibleDefaultEngines": [
+ "google-b-m", "bing", "ddg", "wikipedia-nl", "amazon-nl", "ebay-nl"
+ ]
+ }
+ },
+ "nl": {
+ "default": {
+ "visibleDefaultEngines": [
+ "google-b-m", "bing", "ddg", "ebay-nl", "wikipedia-nl"
+ ]
+ }
+ },
+ "nn-NO": {
+ "default": {
+ "visibleDefaultEngines": [
+ "google-b-m", "bing", "ddg", "gulesider-mobile-NO", "wikipedia-NN"
+ ]
+ }
+ },
+ "oc": {
+ "default": {
+ "visibleDefaultEngines": [
+ "google-b-m", "bing", "ddg", "wikipedia-oc", "wiktionary-oc"
+ ]
+ }
+ },
+ "or": {
+ "default": {
+ "visibleDefaultEngines": [
+ "google-b-m", "bing", "amazon-in", "ddg", "wikipedia-or", "wiktionary-or"
+ ]
+ }
+ },
+ "pa-IN": {
+ "default": {
+ "visibleDefaultEngines": [
+ "google-b-m", "bing", "ddg", "wikipedia-pa"
+ ]
+ }
+ },
+ "pl": {
+ "default": {
+ "visibleDefaultEngines": [
+ "google-b-m", "bing", "ddg", "wikipedia-pl", "ebay-pl"
+ ]
+ }
+ },
+ "pt-BR": {
+ "default": {
+ "visibleDefaultEngines": [
+ "google-b-m", "bing", "ddg", "wikipedia-pt"
+ ]
+ }
+ },
+ "pt-PT": {
+ "default": {
+ "visibleDefaultEngines": [
+ "google-b-m", "ddg", "wikipedia-pt"
+ ]
+ }
+ },
+ "rm": {
+ "default": {
+ "visibleDefaultEngines": [
+ "google-b-m", "bing", "ddg", "ebay-ch", "leo_ende_de", "wikipedia-rm"
+ ]
+ }
+ },
+ "ro": {
+ "default": {
+ "visibleDefaultEngines": [
+ "google-b-m", "bing", "ddg", "wikipedia-ro"
+ ]
+ }
+ },
+ "ru": {
+ "default": {
+ "visibleDefaultEngines": [
+ "google-b-m", "ddg", "wikipedia-ru"
+ ]
+ },
+ "RU": {
+ "visibleDefaultEngines": [
+ "google-com-nocodes", "ddg", "wikipedia-ru"
+ ]
+ },
+ "BY": {
+ "visibleDefaultEngines": [
+ "google-com-nocodes", "ddg", "wikipedia-ru"
+ ]
+ },
+ "KZ": {
+ "visibleDefaultEngines": [
+ "google-com-nocodes", "ddg", "wikipedia-ru"
+ ]
+ },
+ "TR": {
+ "visibleDefaultEngines": [
+ "google-com-nocodes", "ddg", "wikipedia-ru"
+ ]
+ }
+ },
+ "sk": {
+ "default": {
+ "visibleDefaultEngines": [
+ "google-b-m", "ddg", "wikipedia-sk"
+ ]
+ }
+ },
+ "sl": {
+ "default": {
+ "visibleDefaultEngines": [
+ "google-b-m", "ddg", "ceneje", "odpiralni", "wikipedia-sl"
+ ]
+ }
+ },
+ "son": {
+ "default": {
+ "visibleDefaultEngines": [
+ "google-b-m", "ddg", "bing", "amazon-fr", "wikipedia-fr"
+ ]
+ }
+ },
+ "sq": {
+ "default": {
+ "visibleDefaultEngines": [
+ "google-b-m", "bing", "amazon-co-uk", "ddg", "wikipedia-sq"
+ ]
+ }
+ },
+ "sr": {
+ "default": {
+ "visibleDefaultEngines": [
+ "google-b-m", "bing", "ddg", "wikipedia-sr"
+ ]
+ }
+ },
+ "sv-SE": {
+ "default": {
+ "visibleDefaultEngines": [
+ "google-b-m", "bing", "prisjakt-sv-SE", "ddg", "wikipedia-sv-SE", "amazon-se", "ebay-ch"
+ ]
+ }
+ },
+ "ta": {
+ "default": {
+ "visibleDefaultEngines": [
+ "google-b-m", "bing", "amazon-in", "ddg", "wikipedia-ta", "wiktionary-ta"
+ ]
+ }
+ },
+ "te": {
+ "default": {
+ "visibleDefaultEngines": [
+ "google-b-m", "bing", "amazon-in", "ddg", "wikipedia-te", "wiktionary-te"
+ ]
+ }
+ },
+ "th": {
+ "default": {
+ "visibleDefaultEngines": [
+ "google-b-m", "bing", "ddg", "wikipedia-th"
+ ]
+ }
+ },
+ "tl": {
+ "default": {
+ "visibleDefaultEngines": [
+ "google-b-m", "bing", "amazondotcom", "ddg"
+ ]
+ }
+ },
+ "tr": {
+ "default": {
+ "visibleDefaultEngines": [
+ "google-b-m", "bing", "ddg", "wikipedia-tr"
+ ]
+ },
+ "TR": {
+ "visibleDefaultEngines": [
+ "google-com-nocodes", "ddg", "bing", "wikipedia-tr"
+ ]
+ },
+ "BY": {
+ "visibleDefaultEngines": [
+ "google-com-nocodes", "ddg", "bing", "wikipedia-tr"
+ ]
+ },
+ "KZ": {
+ "visibleDefaultEngines": [
+ "google-com-nocodes", "ddg", "bing", "wikipedia-tr"
+ ]
+ },
+ "RU": {
+ "visibleDefaultEngines": [
+ "google-com-nocodes", "ddg", "bing", "wikipedia-tr"
+ ]
+ }
+ },
+ "trs": {
+ "default": {
+ "visibleDefaultEngines": [
+ "google-b-m", "bing", "amazondotcom", "ddg", "wikipedia-es"
+ ]
+ }
+ },
+ "uk": {
+ "default": {
+ "visibleDefaultEngines": [
+ "google-b-m", "bing", "ddg", "wikipedia-uk"
+ ]
+ }
+ },
+ "ur": {
+ "default": {
+ "visibleDefaultEngines": [
+ "google-b-m", "bing", "amazon-in", "ddg", "wikipedia-ur"
+ ]
+ }
+ },
+ "uz": {
+ "default": {
+ "visibleDefaultEngines": [
+ "google-b-m", "bing", "amazondotcom", "ddg", "wikipedia-uz"
+ ]
+ }
+ },
+ "vi": {
+ "default": {
+ "visibleDefaultEngines": [
+ "google-b-m", "coccoc", "ddg", "wikipedia-vi"
+ ]
+ }
+ },
+ "wo": {
+ "default": {
+ "visibleDefaultEngines": [
+ "google-b-m", "bing", "ddg", "ebay-fr", "wikipedia-wo"
+ ]
+ }
+ },
+ "xh": {
+ "default": {
+ "visibleDefaultEngines": [
+ "google-b-m", "bing", "ddg", "wikipedia"
+ ]
+ }
+ },
+ "zam": {
+ "default": {
+ "visibleDefaultEngines": [
+ "google-b-m", "bing", "ddg", "wikipedia-es"
+ ]
+ }
+ },
+ "zh-CN": {
+ "default": {
+ "visibleDefaultEngines": [
+ "google-b-m", "baidu", "bing", "ddg", "wikipedia-zh-CN"
+ ]
+ },
+ "CN": {
+ "searchDefault": "百度"
+ }
+ },
+ "zh-TW": {
+ "default": {
+ "visibleDefaultEngines": [
+ "google-b-m", "bing", "ddg", "wikipedia-zh-TW"
+ ]
+ }
+ }
+ }
+}
diff --git a/mobile/android/android-components/components/feature/search/src/main/assets/search/search_telemetry_v2.json b/mobile/android/android-components/components/feature/search/src/main/assets/search/search_telemetry_v2.json
new file mode 100644
index 0000000000..1803977187
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/assets/search/search_telemetry_v2.json
@@ -0,0 +1,657 @@
+{
+ "data": [
+ {
+ "isSPA": true,
+ "schema": 1707523204491,
+ "components": [
+ {
+ "type": "ad_image_row",
+ "included": {
+ "parent": {
+ "selector": "[data-testid='pam.container']"
+ },
+ "children": [
+ {
+ "selector": "[data-slide-index]",
+ "countChildren": true
+ }
+ ]
+ }
+ },
+ {
+ "type": "ad_link",
+ "included": {
+ "parent": {
+ "selector": "[data-testid='adResult']"
+ }
+ }
+ },
+ {
+ "type": "incontent_searchbox",
+ "topDown": true,
+ "included": {
+ "parent": {
+ "selector": "._1zdrb._1cR1n"
+ },
+ "related": {
+ "selector": "#search-suggestions"
+ },
+ "children": [
+ {
+ "selector": "input[type='search']"
+ }
+ ]
+ }
+ },
+ {
+ "type": "ad_link",
+ "default": true
+ }
+ ],
+ "taggedCodes": [
+ "brz-moz",
+ "firefoxqwant"
+ ],
+ "telemetryId": "qwant",
+ "organicCodes": [],
+ "codeParamName": "client",
+ "queryParamName": "q",
+ "queryParamNames": [
+ "q"
+ ],
+ "searchPageRegexp": "^https://www\\.qwant\\.com/",
+ "filter_expression": "env.version|versionCompare(\"124.0a1\")>=0",
+ "followOnParamNames": [],
+ "defaultPageQueryParam": {
+ "key": "t",
+ "value": "web"
+ },
+ "extraAdServersRegexps": [
+ "^https://www\\.bing\\.com/acli?c?k",
+ "^https://api\\.qwant\\.com/v3/r/"
+ ],
+ "id": "19c434a3-d173-4871-9743-290ac92a3f6b",
+ "last_modified": 1707833261849
+ },
+ {
+ "schema": 1705948294201,
+ "components": [
+ {
+ "type": "ad_carousel",
+ "included": {
+ "parent": {
+ "selector": ".pla-exp-container"
+ },
+ "related": {
+ "selector": "g-right-button, g-left-button, .exp-button"
+ },
+ "children": [
+ {
+ "selector": "[data-dtld]",
+ "countChildren": true
+ }
+ ]
+ }
+ },
+ {
+ "type": "refined_search_buttons",
+ "topDown": true,
+ "included": {
+ "parent": {
+ "selector": "#appbar g-scrolling-carousel"
+ },
+ "related": {
+ "selector": "g-right-button, g-left-button"
+ },
+ "children": [
+ {
+ "selector": "a"
+ }
+ ]
+ }
+ },
+ {
+ "type": "ad_link",
+ "excluded": {
+ "parent": {
+ "selector": "#rhs"
+ }
+ },
+ "included": {
+ "parent": {
+ "selector": "[data-text-ad='1']"
+ },
+ "children": [
+ {
+ "type": "ad_sitelink",
+ "selector": "[role='list']"
+ }
+ ]
+ }
+ },
+ {
+ "type": "ad_sidebar",
+ "included": {
+ "parent": {
+ "selector": "#rhs"
+ },
+ "children": [
+ {
+ "selector": ".pla-unit, .mnr-c",
+ "countChildren": true
+ }
+ ]
+ }
+ },
+ {
+ "type": "incontent_searchbox",
+ "topDown": true,
+ "included": {
+ "parent": {
+ "selector": "form[role='search']"
+ },
+ "related": {
+ "selector": "div.logo + div + div"
+ },
+ "children": [
+ {
+ "selector": "input[type='text']"
+ },
+ {
+ "selector": "textarea[name='q']"
+ }
+ ]
+ }
+ },
+ {
+ "type": "ad_image_row",
+ "excluded": {
+ "parent": {
+ "selector": ".pla-exp-container"
+ }
+ },
+ "included": {
+ "parent": {
+ "selector": ".top-pla-group-inner"
+ },
+ "children": [
+ {
+ "selector": "[data-dtld]",
+ "countChildren": true
+ }
+ ]
+ }
+ },
+ {
+ "type": "ad_link",
+ "default": true
+ }
+ ],
+ "shoppingTab": {
+ "regexp": "&tbm=shop",
+ "selector": "div[role='navigation'] a",
+ "inspectRegexpInSERP": true
+ },
+ "taggedCodes": [
+ "firefox-a",
+ "firefox-b",
+ "firefox-b-1",
+ "firefox-b-ab",
+ "firefox-b-1-ab",
+ "firefox-b-d",
+ "firefox-b-1-d",
+ "firefox-b-e",
+ "firefox-b-1-e",
+ "firefox-b-m",
+ "firefox-b-1-m",
+ "firefox-b-o",
+ "firefox-b-1-o",
+ "firefox-b-lm",
+ "firefox-b-1-lm",
+ "firefox-b-lg",
+ "firefox-b-huawei-h1611",
+ "firefox-b-is-oem1",
+ "firefox-b-oem1",
+ "firefox-b-oem2",
+ "firefox-b-tinno",
+ "firefox-b-pn-wt",
+ "firefox-b-pn-wt-us",
+ "ubuntu",
+ "ubuntu-sn"
+ ],
+ "telemetryId": "google",
+ "organicCodes": [],
+ "codeParamName": "client",
+ "queryParamName": "q",
+ "queryParamNames": [
+ "q"
+ ],
+ "domainExtraction": {
+ "ads": [
+ {
+ "method": "data-attribute",
+ "options": {
+ "dataAttributeKey": "dtld"
+ },
+ "selectors": "[data-dtld]"
+ }
+ ],
+ "nonAds": [
+ {
+ "method": "href",
+ "selectors": "#rso div.g[jscontroller] > div > div > div > div a[data-usg]"
+ }
+ ]
+ },
+ "searchPageRegexp": "^https://www\\.google\\.(?:.+)/search",
+ "nonAdsLinkRegexps": [
+ "^https?://www\\.google\\.(?:.+)/url?(?:.+)&url="
+ ],
+ "adServerAttributes": [
+ "rw"
+ ],
+ "followOnParamNames": [
+ "oq",
+ "ved",
+ "ei"
+ ],
+ "extraAdServersRegexps": [
+ "^https?://www\\.google(?:adservices)?\\.com/(?:pagead/)?aclk"
+ ],
+ "id": "635a3325-1995-42d6-be09-dbe4b2a95453",
+ "last_modified": 1706198445460
+ },
+ {
+ "schema": 1705363206938,
+ "components": [
+ {
+ "type": "ad_carousel",
+ "included": {
+ "parent": {
+ "selector": ".module--carousel"
+ },
+ "related": {
+ "selector": ".module--carousel__left, .module--carousel__right"
+ },
+ "children": [
+ {
+ "selector": ".module--carousel__item",
+ "countChildren": true
+ }
+ ]
+ }
+ },
+ {
+ "type": "ad_link",
+ "excluded": {
+ "parent": {
+ "selector": ".js-results-sidebar"
+ }
+ },
+ "included": {
+ "parent": {
+ "selector": "article[data-testid='ad']"
+ },
+ "children": [
+ {
+ "type": "ad_sitelink",
+ "selector": "ul"
+ }
+ ]
+ }
+ },
+ {
+ "type": "incontent_searchbox",
+ "topDown": true,
+ "included": {
+ "parent": {
+ "selector": "form#search_form"
+ },
+ "related": {
+ "selector": "input#search_button, .search__autocomplete"
+ },
+ "children": [
+ {
+ "selector": " input#search_form_input"
+ }
+ ]
+ }
+ },
+ {
+ "type": "ad_sidebar",
+ "included": {
+ "parent": {
+ "selector": ".js-results-sidebar"
+ },
+ "children": [
+ {
+ "selector": "article[data-testid='ad']",
+ "countChildren": true
+ }
+ ]
+ }
+ },
+ {
+ "type": "ad_link",
+ "default": true
+ }
+ ],
+ "shoppingTab": {
+ "regexp": "&iax=shopping&ia=shopping",
+ "selector": "#duckbar a[data-zci-link='products']"
+ },
+ "taggedCodes": [
+ "ffab",
+ "ffcm",
+ "ffhp",
+ "ffip",
+ "ffit",
+ "ffnt",
+ "ffocus",
+ "ffos",
+ "ffsb",
+ "fpas",
+ "fpsa",
+ "ftas",
+ "ftsa",
+ "lm",
+ "newext"
+ ],
+ "telemetryId": "duckduckgo",
+ "organicCodes": [],
+ "codeParamName": "t",
+ "queryParamName": "q",
+ "queryParamNames": [
+ "q"
+ ],
+ "domainExtraction": {
+ "ads": [
+ {
+ "method": "href",
+ "options": {
+ "queryParamKey": "ad_domain"
+ },
+ "selectors": ".products-carousel a.js-carousel-item-title, [data-testid='ad'] a[data-testid='result-title-a']"
+ }
+ ],
+ "nonAds": [
+ {
+ "method": "href",
+ "selectors": "[data-layout='organic'] a[data-testid='result-title-a']"
+ }
+ ]
+ },
+ "searchPageRegexp": "^https://duckduckgo\\.com/",
+ "expectedOrganicCodes": [
+ "h_",
+ "ha",
+ "hb",
+ "hc",
+ "hd",
+ "he",
+ "hf",
+ "hg",
+ "hh",
+ "hi",
+ "hj",
+ "hk",
+ "hl",
+ "hm",
+ "hn",
+ "ho",
+ "hp",
+ "hq",
+ "hr",
+ "hs",
+ "ht",
+ "hu",
+ "hv",
+ "hw",
+ "hx",
+ "hy",
+ "hz"
+ ],
+ "extraAdServersRegexps": [
+ "^https://duckduckgo.com/y\\.js?.*ad_provider\\=",
+ "^https://www\\.amazon\\.(?:[a-z.]{2,24}).*(?:tag=duckduckgo-)"
+ ],
+ "id": "9dfd626b-26f2-4913-9d0a-27db6cb7d8ca",
+ "last_modified": 1706198445456
+ },
+ {
+ "schema": 1698656464939,
+ "taggedCodes": [
+ "monline_dg",
+ "monline_3_dg",
+ "monline_4_dg",
+ "monline_7_dg"
+ ],
+ "telemetryId": "baidu",
+ "organicCodes": [],
+ "codeParamName": "tn",
+ "queryParamName": "wd",
+ "queryParamNames": [
+ "wd",
+ "word"
+ ],
+ "searchPageRegexp": "^https://(?:m|www)\\.baidu\\.com/(?:s|baidu)",
+ "followOnParamNames": [
+ "oq"
+ ],
+ "extraAdServersRegexps": [
+ "^https?://www\\.baidu\\.com/baidu\\.php?"
+ ],
+ "id": "19c434a3-d173-4871-9743-290ac92a3f6a",
+ "last_modified": 1698666532326
+ },
+ {
+ "schema": 1698656463945,
+ "components": [
+ {
+ "type": "ad_carousel",
+ "included": {
+ "parent": {
+ "selector": ".product-ads-carousel"
+ },
+ "related": {
+ "selector": ".snippet__control"
+ },
+ "children": [
+ {
+ "selector": ".product-ads-carousel__item",
+ "countChildren": true
+ }
+ ]
+ }
+ },
+ {
+ "type": "ad_link",
+ "included": {
+ "parent": {
+ "selector": ".ad-result"
+ },
+ "children": [
+ {
+ "type": "ad_sitelink",
+ "selector": ".result__extra-content .deep-links--descriptions"
+ }
+ ]
+ }
+ },
+ {
+ "type": "incontent_searchbox",
+ "topDown": true,
+ "included": {
+ "parent": {
+ "selector": "form.search-form"
+ },
+ "related": {
+ "selector": ".search-form__suggestions"
+ },
+ "children": [
+ {
+ "selector": ".search-form__input, .search-form__submit"
+ }
+ ]
+ }
+ },
+ {
+ "type": "ad_link",
+ "default": true
+ }
+ ],
+ "shoppingTab": {
+ "regexp": "/shopping?",
+ "selector": "nav li[data-test-id='search-navigation-item-shopping'] a"
+ },
+ "taggedCodes": [
+ "mzl",
+ "813cf1dd",
+ "16eeffc4"
+ ],
+ "telemetryId": "ecosia",
+ "organicCodes": [],
+ "codeParamName": "tt",
+ "queryParamName": "q",
+ "queryParamNames": [
+ "q"
+ ],
+ "searchPageRegexp": "^https://www\\.ecosia\\.org/",
+ "filter_expression": "env.version|versionCompare(\"110.0a1\")>=0",
+ "expectedOrganicCodes": [],
+ "extraAdServersRegexps": [
+ "^https://www\\.bing\\.com/acli?c?k"
+ ],
+ "id": "9a487171-3a06-4647-8866-36250ec84f3a",
+ "last_modified": 1698666532324
+ },
+ {
+ "schema": 1698656462833,
+ "components": [
+ {
+ "type": "ad_carousel",
+ "included": {
+ "parent": {
+ "selector": ".adsMvCarousel"
+ },
+ "related": {
+ "selector": ".cr"
+ },
+ "children": [
+ {
+ "selector": ".pa_item",
+ "countChildren": true
+ }
+ ]
+ }
+ },
+ {
+ "type": "ad_link",
+ "excluded": {
+ "parent": {
+ "selector": "aside"
+ }
+ },
+ "included": {
+ "parent": {
+ "selector": ".sb_adTA"
+ },
+ "children": [
+ {
+ "type": "ad_sitelink",
+ "selector": ".b_vlist2col"
+ }
+ ]
+ }
+ },
+ {
+ "type": "ad_sidebar",
+ "included": {
+ "parent": {
+ "selector": "aside"
+ },
+ "children": [
+ {
+ "selector": ".pa_item, .sb_adTA",
+ "countChildren": true
+ }
+ ]
+ }
+ },
+ {
+ "type": "incontent_searchbox",
+ "topDown": true,
+ "included": {
+ "parent": {
+ "selector": "form#sb_form"
+ },
+ "related": {
+ "selector": "#sw_as"
+ },
+ "children": [
+ {
+ "selector": "input[name='q']"
+ }
+ ]
+ }
+ },
+ {
+ "type": "ad_link",
+ "default": true
+ }
+ ],
+ "shoppingTab": {
+ "regexp": "^/shop?",
+ "selector": "#b-scopeListItem-shop a"
+ },
+ "taggedCodes": [
+ "MOZ2",
+ "MOZ4",
+ "MOZ5",
+ "MOZA",
+ "MOZB",
+ "MOZD",
+ "MOZE",
+ "MOZI",
+ "MOZL",
+ "MOZM",
+ "MOZO",
+ "MOZR",
+ "MOZT",
+ "MOZW",
+ "MOZX",
+ "MZSL01",
+ "MZSL02",
+ "MZSL03"
+ ],
+ "telemetryId": "bing",
+ "organicCodes": [],
+ "codeParamName": "pc",
+ "queryParamName": "q",
+ "followOnCookies": [
+ {
+ "host": "www.bing.com",
+ "name": "SRCHS",
+ "codeParamName": "PC",
+ "extraCodePrefixes": [
+ "QBRE"
+ ],
+ "extraCodeParamName": "form"
+ }
+ ],
+ "queryParamNames": [
+ "q"
+ ],
+ "searchPageRegexp": "^https://www\\.bing\\.com/search",
+ "nonAdsLinkRegexps": [
+ "^https://www.bing.com/ck/a"
+ ],
+ "extraAdServersRegexps": [
+ "^https://www\\.bing\\.com/acli?c?k"
+ ],
+ "id": "e1eec461-f1f3-40de-b94b-3b670b78108c",
+ "last_modified": 1698666532321
+ }
+ ],
+ "timestamp": 1707833261849
+}
diff --git a/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/amazon-au.xml b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/amazon-au.xml
new file mode 100644
index 0000000000..6e8801d893
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/amazon-au.xml
@@ -0,0 +1,12 @@
+<!-- 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/. -->
+
+<SearchPlugin xmlns="http://www.mozilla.org/2006/browser/search/">
+<ShortName>Amazon.com.au</ShortName>
+<Image width="16" height="16">data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGAAAABgCAMAAADVRocKAAABaFBMVEUAAAAAAAAAAAAAAAAAAAAAAAAAAAD/////mQACAgH7+/uEhIT9mACFhYX9/f0JCQkFBQWwagBtQgAJBQANDQ36lgDr6+vj4+O7u7u3t7dDQ0M9PT0oKCgbGxvVgADGdwCqZgBYNQBCKAAkFgAcEQARCgDw8PDS0tKysrKtra2Xl5eSkpJtbW1dXV1aWlpLS0tHR0c5OTkzMzMuLi4qKirrjQDniwDehgC7cACZXACKUwBjOwBPLwA8JAAsGwAgEwD19fXn5+fZ2dnPz8/Ly8vHx8ekpKSdnZ2JiYl/f394eHggICD7lwD2lADRfgDPfACeXwCETwBdOAA4IgA0IAAWDgDd3d3W1ta/v7+oqKiPj497e3twcHBpaWljY2NWVlYUFBTsjgDiiADZgwDAcwC3bgCmYwCPVgB2RwBnPgBKLQAMCADt7e1fX19SUlIWFhYSEhLwkADujwCRVwB8SwB6SgBSMgAPCQBOQY7nAAAABnRSTlMA8si8ZBgxEvPEAAADLklEQVRo3u2aZ1MiMRiA0dO8WeWkd6miNEVF6c3ee++ent3r9e/fgm6iggJuMjfO7PMxs+wTkrcEJiqRluYmxIGm5hZVidZ3iBvvWkUBj/dTg7g+iCstqmbElWZVE+JKkwpxRhEoAkWgCBTBfxBoNVpEYCz41hexbbUBfBoPtQ8KzAUOm/huyui+kanAaYWn9HxmKBgwQxUizAT2NqjKHCNBZw9UZ2SejcAGzzHNROAAgqU92n8wDgSzwEIwBRLvNUhEmKGGGAOBQCJoRhqaJIIvDARDJPBJah0SQS8DgWbnPkjDZGiQCGaZRJEw7+ibnZ5yVn4paOdTrofptqO3JdAOH89O28ZHO7gIBtsnSEliL9AeBYDAQeAYA+ApmOsAroJ9oHQErFORMNs8sAPBfPC13CCYCjRbIGE1kjxgKOgDiQkNl1KxAxJ2aSjGUqAhEWShhwyWAlqag2Ssl4yF5QuOQSJU5RQQlC+ge2wlxxhakyzyBVF6VpTO1SGgDMgW2OFpA56DBwS0cgUfaB1qi5aOwXvwiD3ZeRAAyvautaInxOQKeuFl+uUKjKNQwcQuSMzIr6YDFd0gqDGO3W/LIYt+cPRk3SMCQvMWEBnpZ9PR7GNAmXTcZZsZwDJEzmaFnF6vv/HXFnQJVXt+NDhS7mfbYTLn2GTIKX0oHcd3eGoKXK7ccwnR6TSiqmQWsMRiTUFxGbt9qDGuvfmC/7Z7PY3x99p7YLjAeClrQK+gG+Ozejb5So3xj0wRNULxt6cbFTFerSuKfEmMsVr35xbVx6beLT6/gdYwvqkvTA2XaixiSum7aq9LNlV6OOlDaAUnhXrzYH0Z3+HK5PzoOfze9HJ5KgsZA0LCCdY3kGjej1gicb66lvcLj1ZlY23Vc4rv0RWQSA4nDI1kspAtKSjquMud0ul05+6lU9PD8YsCKqMzrTdaKnweE65B4meXtBmm7Ctq0aY+9YLjJO0TaGTkX1ns/npXlhZwBXHdVZ68XfYPEMPG9aXHnYwvYvViwnW28stL4peJgFJ9zm/qb01FgJAiUASKACFFUAH3SwPcrz1wv7jB++oJ/8sz3K///AMH5R5E/GGrogAAAABJRU5ErkJggg==</Image>
+<Url type="text/html" method="GET" template="https://www.amazon.com.au/s">
+ <Param name="k" value="{searchTerms}"/>
+</Url>
+<SearchForm>https://www.amazon.com.au/</SearchForm>
+</SearchPlugin>
diff --git a/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/amazon-ca.xml b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/amazon-ca.xml
new file mode 100644
index 0000000000..932f62b276
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/amazon-ca.xml
@@ -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/. -->
+
+<SearchPlugin xmlns="http://www.mozilla.org/2006/browser/search/">
+<ShortName>Amazon.ca</ShortName>
+<InputEncoding>UTF-8</InputEncoding>
+<Image width="16" height="16">data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGAAAABgCAMAAADVRocKAAABaFBMVEUAAAAAAAAAAAAAAAAAAAAAAAAAAAD/////mQACAgH7+/uEhIT9mACFhYX9/f0JCQkFBQWwagBtQgAJBQANDQ36lgDr6+vj4+O7u7u3t7dDQ0M9PT0oKCgbGxvVgADGdwCqZgBYNQBCKAAkFgAcEQARCgDw8PDS0tKysrKtra2Xl5eSkpJtbW1dXV1aWlpLS0tHR0c5OTkzMzMuLi4qKirrjQDniwDehgC7cACZXACKUwBjOwBPLwA8JAAsGwAgEwD19fXn5+fZ2dnPz8/Ly8vHx8ekpKSdnZ2JiYl/f394eHggICD7lwD2lADRfgDPfACeXwCETwBdOAA4IgA0IAAWDgDd3d3W1ta/v7+oqKiPj497e3twcHBpaWljY2NWVlYUFBTsjgDiiADZgwDAcwC3bgCmYwCPVgB2RwBnPgBKLQAMCADt7e1fX19SUlIWFhYSEhLwkADujwCRVwB8SwB6SgBSMgAPCQBOQY7nAAAABnRSTlMA8si8ZBgxEvPEAAADLklEQVRo3u2aZ1MiMRiA0dO8WeWkd6miNEVF6c3ee++ent3r9e/fgm6iggJuMjfO7PMxs+wTkrcEJiqRluYmxIGm5hZVidZ3iBvvWkUBj/dTg7g+iCstqmbElWZVE+JKkwpxRhEoAkWgCBTBfxBoNVpEYCz41hexbbUBfBoPtQ8KzAUOm/huyui+kanAaYWn9HxmKBgwQxUizAT2NqjKHCNBZw9UZ2SejcAGzzHNROAAgqU92n8wDgSzwEIwBRLvNUhEmKGGGAOBQCJoRhqaJIIvDARDJPBJah0SQS8DgWbnPkjDZGiQCGaZRJEw7+ibnZ5yVn4paOdTrofptqO3JdAOH89O28ZHO7gIBtsnSEliL9AeBYDAQeAYA+ApmOsAroJ9oHQErFORMNs8sAPBfPC13CCYCjRbIGE1kjxgKOgDiQkNl1KxAxJ2aSjGUqAhEWShhwyWAlqag2Ssl4yF5QuOQSJU5RQQlC+ge2wlxxhakyzyBVF6VpTO1SGgDMgW2OFpA56DBwS0cgUfaB1qi5aOwXvwiD3ZeRAAyvautaInxOQKeuFl+uUKjKNQwcQuSMzIr6YDFd0gqDGO3W/LIYt+cPRk3SMCQvMWEBnpZ9PR7GNAmXTcZZsZwDJEzmaFnF6vv/HXFnQJVXt+NDhS7mfbYTLn2GTIKX0oHcd3eGoKXK7ccwnR6TSiqmQWsMRiTUFxGbt9qDGuvfmC/7Z7PY3x99p7YLjAeClrQK+gG+Ozejb5So3xj0wRNULxt6cbFTFerSuKfEmMsVr35xbVx6beLT6/gdYwvqkvTA2XaixiSum7aq9LNlV6OOlDaAUnhXrzYH0Z3+HK5PzoOfze9HJ5KgsZA0LCCdY3kGjej1gicb66lvcLj1ZlY23Vc4rv0RWQSA4nDI1kspAtKSjquMud0ul05+6lU9PD8YsCKqMzrTdaKnweE65B4meXtBmm7Ctq0aY+9YLjJO0TaGTkX1ns/npXlhZwBXHdVZ68XfYPEMPG9aXHnYwvYvViwnW28stL4peJgFJ9zm/qb01FgJAiUASKACFFUAH3SwPcrz1wv7jB++oJ/8sz3K///AMH5R5E/GGrogAAAABJRU5ErkJggg==</Image>
+<Url type="text/html" method="GET" template="https://www.amazon.ca/s" resultdomain="amazon.ca">
+ <Param name="k" value="{searchTerms}"/>
+</Url>
+<SearchForm>https://www.amazon.ca/</SearchForm>
+</SearchPlugin>
diff --git a/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/amazon-co-uk.xml b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/amazon-co-uk.xml
new file mode 100644
index 0000000000..5ff238cc73
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/amazon-co-uk.xml
@@ -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/. -->
+
+<SearchPlugin xmlns="http://www.mozilla.org/2006/browser/search/">
+<ShortName>Amazon.co.uk</ShortName>
+<InputEncoding>UTF-8</InputEncoding>
+<Image width="16" height="16">data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGAAAABgCAMAAADVRocKAAABaFBMVEUAAAAAAAAAAAAAAAAAAAAAAAAAAAD/////mQACAgH7+/uEhIT9mACFhYX9/f0JCQkFBQWwagBtQgAJBQANDQ36lgDr6+vj4+O7u7u3t7dDQ0M9PT0oKCgbGxvVgADGdwCqZgBYNQBCKAAkFgAcEQARCgDw8PDS0tKysrKtra2Xl5eSkpJtbW1dXV1aWlpLS0tHR0c5OTkzMzMuLi4qKirrjQDniwDehgC7cACZXACKUwBjOwBPLwA8JAAsGwAgEwD19fXn5+fZ2dnPz8/Ly8vHx8ekpKSdnZ2JiYl/f394eHggICD7lwD2lADRfgDPfACeXwCETwBdOAA4IgA0IAAWDgDd3d3W1ta/v7+oqKiPj497e3twcHBpaWljY2NWVlYUFBTsjgDiiADZgwDAcwC3bgCmYwCPVgB2RwBnPgBKLQAMCADt7e1fX19SUlIWFhYSEhLwkADujwCRVwB8SwB6SgBSMgAPCQBOQY7nAAAABnRSTlMA8si8ZBgxEvPEAAADLklEQVRo3u2aZ1MiMRiA0dO8WeWkd6miNEVF6c3ee++ent3r9e/fgm6iggJuMjfO7PMxs+wTkrcEJiqRluYmxIGm5hZVidZ3iBvvWkUBj/dTg7g+iCstqmbElWZVE+JKkwpxRhEoAkWgCBTBfxBoNVpEYCz41hexbbUBfBoPtQ8KzAUOm/huyui+kanAaYWn9HxmKBgwQxUizAT2NqjKHCNBZw9UZ2SejcAGzzHNROAAgqU92n8wDgSzwEIwBRLvNUhEmKGGGAOBQCJoRhqaJIIvDARDJPBJah0SQS8DgWbnPkjDZGiQCGaZRJEw7+ibnZ5yVn4paOdTrofptqO3JdAOH89O28ZHO7gIBtsnSEliL9AeBYDAQeAYA+ApmOsAroJ9oHQErFORMNs8sAPBfPC13CCYCjRbIGE1kjxgKOgDiQkNl1KxAxJ2aSjGUqAhEWShhwyWAlqag2Ssl4yF5QuOQSJU5RQQlC+ge2wlxxhakyzyBVF6VpTO1SGgDMgW2OFpA56DBwS0cgUfaB1qi5aOwXvwiD3ZeRAAyvautaInxOQKeuFl+uUKjKNQwcQuSMzIr6YDFd0gqDGO3W/LIYt+cPRk3SMCQvMWEBnpZ9PR7GNAmXTcZZsZwDJEzmaFnF6vv/HXFnQJVXt+NDhS7mfbYTLn2GTIKX0oHcd3eGoKXK7ccwnR6TSiqmQWsMRiTUFxGbt9qDGuvfmC/7Z7PY3x99p7YLjAeClrQK+gG+Ozejb5So3xj0wRNULxt6cbFTFerSuKfEmMsVr35xbVx6beLT6/gdYwvqkvTA2XaixiSum7aq9LNlV6OOlDaAUnhXrzYH0Z3+HK5PzoOfze9HJ5KgsZA0LCCdY3kGjej1gicb66lvcLj1ZlY23Vc4rv0RWQSA4nDI1kspAtKSjquMud0ul05+6lU9PD8YsCKqMzrTdaKnweE65B4meXtBmm7Ctq0aY+9YLjJO0TaGTkX1ns/npXlhZwBXHdVZ68XfYPEMPG9aXHnYwvYvViwnW28stL4peJgFJ9zm/qb01FgJAiUASKACFFUAH3SwPcrz1wv7jB++oJ/8sz3K///AMH5R5E/GGrogAAAABJRU5ErkJggg==</Image>
+<Url type="text/html" method="GET" template="https://www.amazon.co.uk/s" resultdomain="amazon.co.uk">
+ <Param name="k" value="{searchTerms}"/>
+</Url>
+<SearchForm>https://www.amazon.co.uk/</SearchForm>
+</SearchPlugin>
diff --git a/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/amazon-de.xml b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/amazon-de.xml
new file mode 100644
index 0000000000..137abd4b94
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/amazon-de.xml
@@ -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/. -->
+
+<SearchPlugin xmlns="http://www.mozilla.org/2006/browser/search/">
+<ShortName>Amazon.de</ShortName>
+<InputEncoding>UTF-8</InputEncoding>
+<Image width="16" height="16">data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGAAAABgCAMAAADVRocKAAABaFBMVEUAAAAAAAAAAAAAAAAAAAAAAAAAAAD/////mQACAgH7+/uEhIT9mACFhYX9/f0JCQkFBQWwagBtQgAJBQANDQ36lgDr6+vj4+O7u7u3t7dDQ0M9PT0oKCgbGxvVgADGdwCqZgBYNQBCKAAkFgAcEQARCgDw8PDS0tKysrKtra2Xl5eSkpJtbW1dXV1aWlpLS0tHR0c5OTkzMzMuLi4qKirrjQDniwDehgC7cACZXACKUwBjOwBPLwA8JAAsGwAgEwD19fXn5+fZ2dnPz8/Ly8vHx8ekpKSdnZ2JiYl/f394eHggICD7lwD2lADRfgDPfACeXwCETwBdOAA4IgA0IAAWDgDd3d3W1ta/v7+oqKiPj497e3twcHBpaWljY2NWVlYUFBTsjgDiiADZgwDAcwC3bgCmYwCPVgB2RwBnPgBKLQAMCADt7e1fX19SUlIWFhYSEhLwkADujwCRVwB8SwB6SgBSMgAPCQBOQY7nAAAABnRSTlMA8si8ZBgxEvPEAAADLklEQVRo3u2aZ1MiMRiA0dO8WeWkd6miNEVF6c3ee++ent3r9e/fgm6iggJuMjfO7PMxs+wTkrcEJiqRluYmxIGm5hZVidZ3iBvvWkUBj/dTg7g+iCstqmbElWZVE+JKkwpxRhEoAkWgCBTBfxBoNVpEYCz41hexbbUBfBoPtQ8KzAUOm/huyui+kanAaYWn9HxmKBgwQxUizAT2NqjKHCNBZw9UZ2SejcAGzzHNROAAgqU92n8wDgSzwEIwBRLvNUhEmKGGGAOBQCJoRhqaJIIvDARDJPBJah0SQS8DgWbnPkjDZGiQCGaZRJEw7+ibnZ5yVn4paOdTrofptqO3JdAOH89O28ZHO7gIBtsnSEliL9AeBYDAQeAYA+ApmOsAroJ9oHQErFORMNs8sAPBfPC13CCYCjRbIGE1kjxgKOgDiQkNl1KxAxJ2aSjGUqAhEWShhwyWAlqag2Ssl4yF5QuOQSJU5RQQlC+ge2wlxxhakyzyBVF6VpTO1SGgDMgW2OFpA56DBwS0cgUfaB1qi5aOwXvwiD3ZeRAAyvautaInxOQKeuFl+uUKjKNQwcQuSMzIr6YDFd0gqDGO3W/LIYt+cPRk3SMCQvMWEBnpZ9PR7GNAmXTcZZsZwDJEzmaFnF6vv/HXFnQJVXt+NDhS7mfbYTLn2GTIKX0oHcd3eGoKXK7ccwnR6TSiqmQWsMRiTUFxGbt9qDGuvfmC/7Z7PY3x99p7YLjAeClrQK+gG+Ozejb5So3xj0wRNULxt6cbFTFerSuKfEmMsVr35xbVx6beLT6/gdYwvqkvTA2XaixiSum7aq9LNlV6OOlDaAUnhXrzYH0Z3+HK5PzoOfze9HJ5KgsZA0LCCdY3kGjej1gicb66lvcLj1ZlY23Vc4rv0RWQSA4nDI1kspAtKSjquMud0ul05+6lU9PD8YsCKqMzrTdaKnweE65B4meXtBmm7Ctq0aY+9YLjJO0TaGTkX1ns/npXlhZwBXHdVZ68XfYPEMPG9aXHnYwvYvViwnW28stL4peJgFJ9zm/qb01FgJAiUASKACFFUAH3SwPcrz1wv7jB++oJ/8sz3K///AMH5R5E/GGrogAAAABJRU5ErkJggg==</Image>
+<Url type="text/html" method="GET" template="https://www.amazon.de/s" resultdomain="amazon.de">
+ <Param name="k" value="{searchTerms}"/>
+</Url>
+<SearchForm>https://www.amazon.de/</SearchForm>
+</SearchPlugin>
diff --git a/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/amazon-es.xml b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/amazon-es.xml
new file mode 100644
index 0000000000..c989b9f361
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/amazon-es.xml
@@ -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/. -->
+
+<SearchPlugin xmlns="http://www.mozilla.org/2006/browser/search/">
+<ShortName>Amazon.es</ShortName>
+<InputEncoding>UTF-8</InputEncoding>
+<Image width="16" height="16">data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGAAAABgCAMAAADVRocKAAABaFBMVEUAAAAAAAAAAAAAAAAAAAAAAAAAAAD/////mQACAgH7+/uEhIT9mACFhYX9/f0JCQkFBQWwagBtQgAJBQANDQ36lgDr6+vj4+O7u7u3t7dDQ0M9PT0oKCgbGxvVgADGdwCqZgBYNQBCKAAkFgAcEQARCgDw8PDS0tKysrKtra2Xl5eSkpJtbW1dXV1aWlpLS0tHR0c5OTkzMzMuLi4qKirrjQDniwDehgC7cACZXACKUwBjOwBPLwA8JAAsGwAgEwD19fXn5+fZ2dnPz8/Ly8vHx8ekpKSdnZ2JiYl/f394eHggICD7lwD2lADRfgDPfACeXwCETwBdOAA4IgA0IAAWDgDd3d3W1ta/v7+oqKiPj497e3twcHBpaWljY2NWVlYUFBTsjgDiiADZgwDAcwC3bgCmYwCPVgB2RwBnPgBKLQAMCADt7e1fX19SUlIWFhYSEhLwkADujwCRVwB8SwB6SgBSMgAPCQBOQY7nAAAABnRSTlMA8si8ZBgxEvPEAAADLklEQVRo3u2aZ1MiMRiA0dO8WeWkd6miNEVF6c3ee++ent3r9e/fgm6iggJuMjfO7PMxs+wTkrcEJiqRluYmxIGm5hZVidZ3iBvvWkUBj/dTg7g+iCstqmbElWZVE+JKkwpxRhEoAkWgCBTBfxBoNVpEYCz41hexbbUBfBoPtQ8KzAUOm/huyui+kanAaYWn9HxmKBgwQxUizAT2NqjKHCNBZw9UZ2SejcAGzzHNROAAgqU92n8wDgSzwEIwBRLvNUhEmKGGGAOBQCJoRhqaJIIvDARDJPBJah0SQS8DgWbnPkjDZGiQCGaZRJEw7+ibnZ5yVn4paOdTrofptqO3JdAOH89O28ZHO7gIBtsnSEliL9AeBYDAQeAYA+ApmOsAroJ9oHQErFORMNs8sAPBfPC13CCYCjRbIGE1kjxgKOgDiQkNl1KxAxJ2aSjGUqAhEWShhwyWAlqag2Ssl4yF5QuOQSJU5RQQlC+ge2wlxxhakyzyBVF6VpTO1SGgDMgW2OFpA56DBwS0cgUfaB1qi5aOwXvwiD3ZeRAAyvautaInxOQKeuFl+uUKjKNQwcQuSMzIr6YDFd0gqDGO3W/LIYt+cPRk3SMCQvMWEBnpZ9PR7GNAmXTcZZsZwDJEzmaFnF6vv/HXFnQJVXt+NDhS7mfbYTLn2GTIKX0oHcd3eGoKXK7ccwnR6TSiqmQWsMRiTUFxGbt9qDGuvfmC/7Z7PY3x99p7YLjAeClrQK+gG+Ozejb5So3xj0wRNULxt6cbFTFerSuKfEmMsVr35xbVx6beLT6/gdYwvqkvTA2XaixiSum7aq9LNlV6OOlDaAUnhXrzYH0Z3+HK5PzoOfze9HJ5KgsZA0LCCdY3kGjej1gicb66lvcLj1ZlY23Vc4rv0RWQSA4nDI1kspAtKSjquMud0ul05+6lU9PD8YsCKqMzrTdaKnweE65B4meXtBmm7Ctq0aY+9YLjJO0TaGTkX1ns/npXlhZwBXHdVZ68XfYPEMPG9aXHnYwvYvViwnW28stL4peJgFJ9zm/qb01FgJAiUASKACFFUAH3SwPcrz1wv7jB++oJ/8sz3K///AMH5R5E/GGrogAAAABJRU5ErkJggg==</Image>
+<Url type="text/html" method="GET" template="https://www.amazon.es/s" resultdomain="amazon.es">
+ <Param name="k" value="{searchTerms}"/>
+</Url>
+<SearchForm>https://www.amazon.es/</SearchForm>
+</SearchPlugin>
diff --git a/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/amazon-fr.xml b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/amazon-fr.xml
new file mode 100644
index 0000000000..abfb75bee5
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/amazon-fr.xml
@@ -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/. -->
+
+<SearchPlugin xmlns="http://www.mozilla.org/2006/browser/search/">
+<ShortName>Amazon.fr</ShortName>
+<InputEncoding>UTF-8</InputEncoding>
+<Image width="16" height="16">data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGAAAABgCAMAAADVRocKAAABaFBMVEUAAAAAAAAAAAAAAAAAAAAAAAAAAAD/////mQACAgH7+/uEhIT9mACFhYX9/f0JCQkFBQWwagBtQgAJBQANDQ36lgDr6+vj4+O7u7u3t7dDQ0M9PT0oKCgbGxvVgADGdwCqZgBYNQBCKAAkFgAcEQARCgDw8PDS0tKysrKtra2Xl5eSkpJtbW1dXV1aWlpLS0tHR0c5OTkzMzMuLi4qKirrjQDniwDehgC7cACZXACKUwBjOwBPLwA8JAAsGwAgEwD19fXn5+fZ2dnPz8/Ly8vHx8ekpKSdnZ2JiYl/f394eHggICD7lwD2lADRfgDPfACeXwCETwBdOAA4IgA0IAAWDgDd3d3W1ta/v7+oqKiPj497e3twcHBpaWljY2NWVlYUFBTsjgDiiADZgwDAcwC3bgCmYwCPVgB2RwBnPgBKLQAMCADt7e1fX19SUlIWFhYSEhLwkADujwCRVwB8SwB6SgBSMgAPCQBOQY7nAAAABnRSTlMA8si8ZBgxEvPEAAADLklEQVRo3u2aZ1MiMRiA0dO8WeWkd6miNEVF6c3ee++ent3r9e/fgm6iggJuMjfO7PMxs+wTkrcEJiqRluYmxIGm5hZVidZ3iBvvWkUBj/dTg7g+iCstqmbElWZVE+JKkwpxRhEoAkWgCBTBfxBoNVpEYCz41hexbbUBfBoPtQ8KzAUOm/huyui+kanAaYWn9HxmKBgwQxUizAT2NqjKHCNBZw9UZ2SejcAGzzHNROAAgqU92n8wDgSzwEIwBRLvNUhEmKGGGAOBQCJoRhqaJIIvDARDJPBJah0SQS8DgWbnPkjDZGiQCGaZRJEw7+ibnZ5yVn4paOdTrofptqO3JdAOH89O28ZHO7gIBtsnSEliL9AeBYDAQeAYA+ApmOsAroJ9oHQErFORMNs8sAPBfPC13CCYCjRbIGE1kjxgKOgDiQkNl1KxAxJ2aSjGUqAhEWShhwyWAlqag2Ssl4yF5QuOQSJU5RQQlC+ge2wlxxhakyzyBVF6VpTO1SGgDMgW2OFpA56DBwS0cgUfaB1qi5aOwXvwiD3ZeRAAyvautaInxOQKeuFl+uUKjKNQwcQuSMzIr6YDFd0gqDGO3W/LIYt+cPRk3SMCQvMWEBnpZ9PR7GNAmXTcZZsZwDJEzmaFnF6vv/HXFnQJVXt+NDhS7mfbYTLn2GTIKX0oHcd3eGoKXK7ccwnR6TSiqmQWsMRiTUFxGbt9qDGuvfmC/7Z7PY3x99p7YLjAeClrQK+gG+Ozejb5So3xj0wRNULxt6cbFTFerSuKfEmMsVr35xbVx6beLT6/gdYwvqkvTA2XaixiSum7aq9LNlV6OOlDaAUnhXrzYH0Z3+HK5PzoOfze9HJ5KgsZA0LCCdY3kGjej1gicb66lvcLj1ZlY23Vc4rv0RWQSA4nDI1kspAtKSjquMud0ul05+6lU9PD8YsCKqMzrTdaKnweE65B4meXtBmm7Ctq0aY+9YLjJO0TaGTkX1ns/npXlhZwBXHdVZ68XfYPEMPG9aXHnYwvYvViwnW28stL4peJgFJ9zm/qb01FgJAiUASKACFFUAH3SwPcrz1wv7jB++oJ/8sz3K///AMH5R5E/GGrogAAAABJRU5ErkJggg==</Image>
+<Url type="text/html" method="GET" template="https://www.amazon.fr/s" resultdomain="amazon.fr">
+ <Param name="k" value="{searchTerms}"/>
+</Url>
+<SearchForm>https://www.amazon.fr/</SearchForm>
+</SearchPlugin>
diff --git a/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/amazon-in.xml b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/amazon-in.xml
new file mode 100644
index 0000000000..2c1be1f73a
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/amazon-in.xml
@@ -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/. -->
+
+<SearchPlugin xmlns="http://www.mozilla.org/2006/browser/search/">
+<ShortName>Amazon.in</ShortName>
+<InputEncoding>utf-8</InputEncoding>
+<Image width="16" height="16">data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGAAAABgCAMAAADVRocKAAABaFBMVEUAAAAAAAAAAAAAAAAAAAAAAAAAAAD/////mQACAgH7+/uEhIT9mACFhYX9/f0JCQkFBQWwagBtQgAJBQANDQ36lgDr6+vj4+O7u7u3t7dDQ0M9PT0oKCgbGxvVgADGdwCqZgBYNQBCKAAkFgAcEQARCgDw8PDS0tKysrKtra2Xl5eSkpJtbW1dXV1aWlpLS0tHR0c5OTkzMzMuLi4qKirrjQDniwDehgC7cACZXACKUwBjOwBPLwA8JAAsGwAgEwD19fXn5+fZ2dnPz8/Ly8vHx8ekpKSdnZ2JiYl/f394eHggICD7lwD2lADRfgDPfACeXwCETwBdOAA4IgA0IAAWDgDd3d3W1ta/v7+oqKiPj497e3twcHBpaWljY2NWVlYUFBTsjgDiiADZgwDAcwC3bgCmYwCPVgB2RwBnPgBKLQAMCADt7e1fX19SUlIWFhYSEhLwkADujwCRVwB8SwB6SgBSMgAPCQBOQY7nAAAABnRSTlMA8si8ZBgxEvPEAAADLklEQVRo3u2aZ1MiMRiA0dO8WeWkd6miNEVF6c3ee++ent3r9e/fgm6iggJuMjfO7PMxs+wTkrcEJiqRluYmxIGm5hZVidZ3iBvvWkUBj/dTg7g+iCstqmbElWZVE+JKkwpxRhEoAkWgCBTBfxBoNVpEYCz41hexbbUBfBoPtQ8KzAUOm/huyui+kanAaYWn9HxmKBgwQxUizAT2NqjKHCNBZw9UZ2SejcAGzzHNROAAgqU92n8wDgSzwEIwBRLvNUhEmKGGGAOBQCJoRhqaJIIvDARDJPBJah0SQS8DgWbnPkjDZGiQCGaZRJEw7+ibnZ5yVn4paOdTrofptqO3JdAOH89O28ZHO7gIBtsnSEliL9AeBYDAQeAYA+ApmOsAroJ9oHQErFORMNs8sAPBfPC13CCYCjRbIGE1kjxgKOgDiQkNl1KxAxJ2aSjGUqAhEWShhwyWAlqag2Ssl4yF5QuOQSJU5RQQlC+ge2wlxxhakyzyBVF6VpTO1SGgDMgW2OFpA56DBwS0cgUfaB1qi5aOwXvwiD3ZeRAAyvautaInxOQKeuFl+uUKjKNQwcQuSMzIr6YDFd0gqDGO3W/LIYt+cPRk3SMCQvMWEBnpZ9PR7GNAmXTcZZsZwDJEzmaFnF6vv/HXFnQJVXt+NDhS7mfbYTLn2GTIKX0oHcd3eGoKXK7ccwnR6TSiqmQWsMRiTUFxGbt9qDGuvfmC/7Z7PY3x99p7YLjAeClrQK+gG+Ozejb5So3xj0wRNULxt6cbFTFerSuKfEmMsVr35xbVx6beLT6/gdYwvqkvTA2XaixiSum7aq9LNlV6OOlDaAUnhXrzYH0Z3+HK5PzoOfze9HJ5KgsZA0LCCdY3kGjej1gicb66lvcLj1ZlY23Vc4rv0RWQSA4nDI1kspAtKSjquMud0ul05+6lU9PD8YsCKqMzrTdaKnweE65B4meXtBmm7Ctq0aY+9YLjJO0TaGTkX1ns/npXlhZwBXHdVZ68XfYPEMPG9aXHnYwvYvViwnW28stL4peJgFJ9zm/qb01FgJAiUASKACFFUAH3SwPcrz1wv7jB++oJ/8sz3K///AMH5R5E/GGrogAAAABJRU5ErkJggg==</Image>
+<Url type="text/html" method="GET" template="https://www.amazon.in/s">
+ <Param name="k" value="{searchTerms}"/>
+</Url>
+<SearchForm>https://www.amazon.in/</SearchForm>
+</SearchPlugin>
diff --git a/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/amazon-it.xml b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/amazon-it.xml
new file mode 100644
index 0000000000..805bbf0af2
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/amazon-it.xml
@@ -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/. -->
+
+<SearchPlugin xmlns="http://www.mozilla.org/2006/browser/search/">
+<ShortName>Amazon.it</ShortName>
+<InputEncoding>UTF-8</InputEncoding>
+<Image width="16" height="16">data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGAAAABgCAMAAADVRocKAAABaFBMVEUAAAAAAAAAAAAAAAAAAAAAAAAAAAD/////mQACAgH7+/uEhIT9mACFhYX9/f0JCQkFBQWwagBtQgAJBQANDQ36lgDr6+vj4+O7u7u3t7dDQ0M9PT0oKCgbGxvVgADGdwCqZgBYNQBCKAAkFgAcEQARCgDw8PDS0tKysrKtra2Xl5eSkpJtbW1dXV1aWlpLS0tHR0c5OTkzMzMuLi4qKirrjQDniwDehgC7cACZXACKUwBjOwBPLwA8JAAsGwAgEwD19fXn5+fZ2dnPz8/Ly8vHx8ekpKSdnZ2JiYl/f394eHggICD7lwD2lADRfgDPfACeXwCETwBdOAA4IgA0IAAWDgDd3d3W1ta/v7+oqKiPj497e3twcHBpaWljY2NWVlYUFBTsjgDiiADZgwDAcwC3bgCmYwCPVgB2RwBnPgBKLQAMCADt7e1fX19SUlIWFhYSEhLwkADujwCRVwB8SwB6SgBSMgAPCQBOQY7nAAAABnRSTlMA8si8ZBgxEvPEAAADLklEQVRo3u2aZ1MiMRiA0dO8WeWkd6miNEVF6c3ee++ent3r9e/fgm6iggJuMjfO7PMxs+wTkrcEJiqRluYmxIGm5hZVidZ3iBvvWkUBj/dTg7g+iCstqmbElWZVE+JKkwpxRhEoAkWgCBTBfxBoNVpEYCz41hexbbUBfBoPtQ8KzAUOm/huyui+kanAaYWn9HxmKBgwQxUizAT2NqjKHCNBZw9UZ2SejcAGzzHNROAAgqU92n8wDgSzwEIwBRLvNUhEmKGGGAOBQCJoRhqaJIIvDARDJPBJah0SQS8DgWbnPkjDZGiQCGaZRJEw7+ibnZ5yVn4paOdTrofptqO3JdAOH89O28ZHO7gIBtsnSEliL9AeBYDAQeAYA+ApmOsAroJ9oHQErFORMNs8sAPBfPC13CCYCjRbIGE1kjxgKOgDiQkNl1KxAxJ2aSjGUqAhEWShhwyWAlqag2Ssl4yF5QuOQSJU5RQQlC+ge2wlxxhakyzyBVF6VpTO1SGgDMgW2OFpA56DBwS0cgUfaB1qi5aOwXvwiD3ZeRAAyvautaInxOQKeuFl+uUKjKNQwcQuSMzIr6YDFd0gqDGO3W/LIYt+cPRk3SMCQvMWEBnpZ9PR7GNAmXTcZZsZwDJEzmaFnF6vv/HXFnQJVXt+NDhS7mfbYTLn2GTIKX0oHcd3eGoKXK7ccwnR6TSiqmQWsMRiTUFxGbt9qDGuvfmC/7Z7PY3x99p7YLjAeClrQK+gG+Ozejb5So3xj0wRNULxt6cbFTFerSuKfEmMsVr35xbVx6beLT6/gdYwvqkvTA2XaixiSum7aq9LNlV6OOlDaAUnhXrzYH0Z3+HK5PzoOfze9HJ5KgsZA0LCCdY3kGjej1gicb66lvcLj1ZlY23Vc4rv0RWQSA4nDI1kspAtKSjquMud0ul05+6lU9PD8YsCKqMzrTdaKnweE65B4meXtBmm7Ctq0aY+9YLjJO0TaGTkX1ns/npXlhZwBXHdVZ68XfYPEMPG9aXHnYwvYvViwnW28stL4peJgFJ9zm/qb01FgJAiUASKACFFUAH3SwPcrz1wv7jB++oJ/8sz3K///AMH5R5E/GGrogAAAABJRU5ErkJggg==</Image>
+<Url type="text/html" method="GET" template="https://www.amazon.it/s" resultdomain="amazon.it">
+ <Param name="k" value="{searchTerms}"/>
+</Url>
+<SearchForm>https://www.amazon.it/</SearchForm>
+</SearchPlugin>
diff --git a/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/amazon-jp.xml b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/amazon-jp.xml
new file mode 100644
index 0000000000..7d57698067
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/amazon-jp.xml
@@ -0,0 +1,31 @@
+<!-- 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/. -->
+
+<SearchPlugin xmlns="http://www.mozilla.org/2006/browser/search/">
+<ShortName>Amazon.co.jp</ShortName>
+<Description>検索エンジン - Amazon.co.jp 検索</Description>
+<InputEncoding>UTF-8</InputEncoding>
+<Image width="16" height="16">data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGAAAABgCAMAAADVRocKAAABaFBMVEUAAAAAAAAAAAAAAAAAAAAAAAAAAAD/////mQACAgH7+/uEhIT9mACFhYX9/f0JCQkFBQWwagBtQgAJBQANDQ36lgDr6+vj4+O7u7u3t7dDQ0M9PT0oKCgbGxvVgADGdwCqZgBYNQBCKAAkFgAcEQARCgDw8PDS0tKysrKtra2Xl5eSkpJtbW1dXV1aWlpLS0tHR0c5OTkzMzMuLi4qKirrjQDniwDehgC7cACZXACKUwBjOwBPLwA8JAAsGwAgEwD19fXn5+fZ2dnPz8/Ly8vHx8ekpKSdnZ2JiYl/f394eHggICD7lwD2lADRfgDPfACeXwCETwBdOAA4IgA0IAAWDgDd3d3W1ta/v7+oqKiPj497e3twcHBpaWljY2NWVlYUFBTsjgDiiADZgwDAcwC3bgCmYwCPVgB2RwBnPgBKLQAMCADt7e1fX19SUlIWFhYSEhLwkADujwCRVwB8SwB6SgBSMgAPCQBOQY7nAAAABnRSTlMA8si8ZBgxEvPEAAADLklEQVRo3u2aZ1MiMRiA0dO8WeWkd6miNEVF6c3ee++ent3r9e/fgm6iggJuMjfO7PMxs+wTkrcEJiqRluYmxIGm5hZVidZ3iBvvWkUBj/dTg7g+iCstqmbElWZVE+JKkwpxRhEoAkWgCBTBfxBoNVpEYCz41hexbbUBfBoPtQ8KzAUOm/huyui+kanAaYWn9HxmKBgwQxUizAT2NqjKHCNBZw9UZ2SejcAGzzHNROAAgqU92n8wDgSzwEIwBRLvNUhEmKGGGAOBQCJoRhqaJIIvDARDJPBJah0SQS8DgWbnPkjDZGiQCGaZRJEw7+ibnZ5yVn4paOdTrofptqO3JdAOH89O28ZHO7gIBtsnSEliL9AeBYDAQeAYA+ApmOsAroJ9oHQErFORMNs8sAPBfPC13CCYCjRbIGE1kjxgKOgDiQkNl1KxAxJ2aSjGUqAhEWShhwyWAlqag2Ssl4yF5QuOQSJU5RQQlC+ge2wlxxhakyzyBVF6VpTO1SGgDMgW2OFpA56DBwS0cgUfaB1qi5aOwXvwiD3ZeRAAyvautaInxOQKeuFl+uUKjKNQwcQuSMzIr6YDFd0gqDGO3W/LIYt+cPRk3SMCQvMWEBnpZ9PR7GNAmXTcZZsZwDJEzmaFnF6vv/HXFnQJVXt+NDhS7mfbYTLn2GTIKX0oHcd3eGoKXK7ccwnR6TSiqmQWsMRiTUFxGbt9qDGuvfmC/7Z7PY3x99p7YLjAeClrQK+gG+Ozejb5So3xj0wRNULxt6cbFTFerSuKfEmMsVr35xbVx6beLT6/gdYwvqkvTA2XaixiSum7aq9LNlV6OOlDaAUnhXrzYH0Z3+HK5PzoOfze9HJ5KgsZA0LCCdY3kGjej1gicb66lvcLj1ZlY23Vc4rv0RWQSA4nDI1kspAtKSjquMud0ul05+6lU9PD8YsCKqMzrTdaKnweE65B4meXtBmm7Ctq0aY+9YLjJO0TaGTkX1ns/npXlhZwBXHdVZ68XfYPEMPG9aXHnYwvYvViwnW28stL4peJgFJ9zm/qb01FgJAiUASKACFFUAH3SwPcrz1wv7jB++oJ/8sz3K///AMH5R5E/GGrogAAAABJRU5ErkJggg==</Image>
+<Url type="application/x-suggestions+json" method="GET" template="https://completion.amazon.co.jp/search/complete?q={searchTerms}&amp;client=amazon-search-ui&amp;search-alias=aps&amp;mkt=6"/>
+<Url type="text/html" method="GET" template="https://www.amazon.co.jp/exec/obidos/external-search/" resultdomain="amazon.co.jp">
+ <Param name="field-keywords" value="{searchTerms}"/>
+ <Param name="mode" value="blended"/>
+ <!--
+ <Param name="mode" value="books-jp"/>
+ <Param name="mode" value="books-us"/>
+ -->
+ <Param name="tag" value="moz-jp-mbl-22"/>
+ <Param name="sourceid" value="Mozilla-search"/>
+ <!--
+ <Param name="sz" value="25"/>
+ <Param name="rank" value="+salesrank"/>
+ <Param name="rank" value="+pricerank"/>
+ <Param name="rank" value="+inverse-pricerank"/>
+ <Param name="rank" value="+daterank"/>
+ <Param name="rank" value="+titlerank"/>
+ <Param name="rank" value="-titlerank"/>
+ -->
+</Url>
+<SearchForm>https://www.amazon.co.jp/</SearchForm>
+</SearchPlugin>
diff --git a/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/amazon-nl.xml b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/amazon-nl.xml
new file mode 100644
index 0000000000..75530332cc
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/amazon-nl.xml
@@ -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/. -->
+
+<SearchPlugin xmlns="http://www.mozilla.org/2006/browser/search/">
+<ShortName>Amazon.nl</ShortName>
+<InputEncoding>UTF-8</InputEncoding>
+<Image width="16" height="16">data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGAAAABgCAMAAADVRocKAAABaFBMVEUAAAAAAAAAAAAAAAAAAAAAAAAAAAD/////mQACAgH7+/uEhIT9mACFhYX9/f0JCQkFBQWwagBtQgAJBQANDQ36lgDr6+vj4+O7u7u3t7dDQ0M9PT0oKCgbGxvVgADGdwCqZgBYNQBCKAAkFgAcEQARCgDw8PDS0tKysrKtra2Xl5eSkpJtbW1dXV1aWlpLS0tHR0c5OTkzMzMuLi4qKirrjQDniwDehgC7cACZXACKUwBjOwBPLwA8JAAsGwAgEwD19fXn5+fZ2dnPz8/Ly8vHx8ekpKSdnZ2JiYl/f394eHggICD7lwD2lADRfgDPfACeXwCETwBdOAA4IgA0IAAWDgDd3d3W1ta/v7+oqKiPj497e3twcHBpaWljY2NWVlYUFBTsjgDiiADZgwDAcwC3bgCmYwCPVgB2RwBnPgBKLQAMCADt7e1fX19SUlIWFhYSEhLwkADujwCRVwB8SwB6SgBSMgAPCQBOQY7nAAAABnRSTlMA8si8ZBgxEvPEAAADLklEQVRo3u2aZ1MiMRiA0dO8WeWkd6miNEVF6c3ee++ent3r9e/fgm6iggJuMjfO7PMxs+wTkrcEJiqRluYmxIGm5hZVidZ3iBvvWkUBj/dTg7g+iCstqmbElWZVE+JKkwpxRhEoAkWgCBTBfxBoNVpEYCz41hexbbUBfBoPtQ8KzAUOm/huyui+kanAaYWn9HxmKBgwQxUizAT2NqjKHCNBZw9UZ2SejcAGzzHNROAAgqU92n8wDgSzwEIwBRLvNUhEmKGGGAOBQCJoRhqaJIIvDARDJPBJah0SQS8DgWbnPkjDZGiQCGaZRJEw7+ibnZ5yVn4paOdTrofptqO3JdAOH89O28ZHO7gIBtsnSEliL9AeBYDAQeAYA+ApmOsAroJ9oHQErFORMNs8sAPBfPC13CCYCjRbIGE1kjxgKOgDiQkNl1KxAxJ2aSjGUqAhEWShhwyWAlqag2Ssl4yF5QuOQSJU5RQQlC+ge2wlxxhakyzyBVF6VpTO1SGgDMgW2OFpA56DBwS0cgUfaB1qi5aOwXvwiD3ZeRAAyvautaInxOQKeuFl+uUKjKNQwcQuSMzIr6YDFd0gqDGO3W/LIYt+cPRk3SMCQvMWEBnpZ9PR7GNAmXTcZZsZwDJEzmaFnF6vv/HXFnQJVXt+NDhS7mfbYTLn2GTIKX0oHcd3eGoKXK7ccwnR6TSiqmQWsMRiTUFxGbt9qDGuvfmC/7Z7PY3x99p7YLjAeClrQK+gG+Ozejb5So3xj0wRNULxt6cbFTFerSuKfEmMsVr35xbVx6beLT6/gdYwvqkvTA2XaixiSum7aq9LNlV6OOlDaAUnhXrzYH0Z3+HK5PzoOfze9HJ5KgsZA0LCCdY3kGjej1gicb66lvcLj1ZlY23Vc4rv0RWQSA4nDI1kspAtKSjquMud0ul05+6lU9PD8YsCKqMzrTdaKnweE65B4meXtBmm7Ctq0aY+9YLjJO0TaGTkX1ns/npXlhZwBXHdVZ68XfYPEMPG9aXHnYwvYvViwnW28stL4peJgFJ9zm/qb01FgJAiUASKACFFUAH3SwPcrz1wv7jB++oJ/8sz3K///AMH5R5E/GGrogAAAABJRU5ErkJggg==</Image>
+<Url type="text/html" method="GET" template="https://www.amazon.nl/s">
+ <Param name="k" value="{searchTerms}"/>
+</Url>
+<SearchForm>https://www.amazon.nl/</SearchForm>
+</SearchPlugin>
diff --git a/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/amazon-se.xml b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/amazon-se.xml
new file mode 100644
index 0000000000..98f7b2d35a
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/amazon-se.xml
@@ -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/. -->
+
+<SearchPlugin xmlns="http://www.mozilla.org/2006/browser/search/">
+<ShortName>Amazon.se</ShortName>
+<InputEncoding>UTF-8</InputEncoding>
+<Image width="16" height="16">data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGAAAABgCAMAAADVRocKAAABaFBMVEUAAAAAAAAAAAAAAAAAAAAAAAAAAAD/////mQACAgH7+/uEhIT9mACFhYX9/f0JCQkFBQWwagBtQgAJBQANDQ36lgDr6+vj4+O7u7u3t7dDQ0M9PT0oKCgbGxvVgADGdwCqZgBYNQBCKAAkFgAcEQARCgDw8PDS0tKysrKtra2Xl5eSkpJtbW1dXV1aWlpLS0tHR0c5OTkzMzMuLi4qKirrjQDniwDehgC7cACZXACKUwBjOwBPLwA8JAAsGwAgEwD19fXn5+fZ2dnPz8/Ly8vHx8ekpKSdnZ2JiYl/f394eHggICD7lwD2lADRfgDPfACeXwCETwBdOAA4IgA0IAAWDgDd3d3W1ta/v7+oqKiPj497e3twcHBpaWljY2NWVlYUFBTsjgDiiADZgwDAcwC3bgCmYwCPVgB2RwBnPgBKLQAMCADt7e1fX19SUlIWFhYSEhLwkADujwCRVwB8SwB6SgBSMgAPCQBOQY7nAAAABnRSTlMA8si8ZBgxEvPEAAADLklEQVRo3u2aZ1MiMRiA0dO8WeWkd6miNEVF6c3ee++ent3r9e/fgm6iggJuMjfO7PMxs+wTkrcEJiqRluYmxIGm5hZVidZ3iBvvWkUBj/dTg7g+iCstqmbElWZVE+JKkwpxRhEoAkWgCBTBfxBoNVpEYCz41hexbbUBfBoPtQ8KzAUOm/huyui+kanAaYWn9HxmKBgwQxUizAT2NqjKHCNBZw9UZ2SejcAGzzHNROAAgqU92n8wDgSzwEIwBRLvNUhEmKGGGAOBQCJoRhqaJIIvDARDJPBJah0SQS8DgWbnPkjDZGiQCGaZRJEw7+ibnZ5yVn4paOdTrofptqO3JdAOH89O28ZHO7gIBtsnSEliL9AeBYDAQeAYA+ApmOsAroJ9oHQErFORMNs8sAPBfPC13CCYCjRbIGE1kjxgKOgDiQkNl1KxAxJ2aSjGUqAhEWShhwyWAlqag2Ssl4yF5QuOQSJU5RQQlC+ge2wlxxhakyzyBVF6VpTO1SGgDMgW2OFpA56DBwS0cgUfaB1qi5aOwXvwiD3ZeRAAyvautaInxOQKeuFl+uUKjKNQwcQuSMzIr6YDFd0gqDGO3W/LIYt+cPRk3SMCQvMWEBnpZ9PR7GNAmXTcZZsZwDJEzmaFnF6vv/HXFnQJVXt+NDhS7mfbYTLn2GTIKX0oHcd3eGoKXK7ccwnR6TSiqmQWsMRiTUFxGbt9qDGuvfmC/7Z7PY3x99p7YLjAeClrQK+gG+Ozejb5So3xj0wRNULxt6cbFTFerSuKfEmMsVr35xbVx6beLT6/gdYwvqkvTA2XaixiSum7aq9LNlV6OOlDaAUnhXrzYH0Z3+HK5PzoOfze9HJ5KgsZA0LCCdY3kGjej1gicb66lvcLj1ZlY23Vc4rv0RWQSA4nDI1kspAtKSjquMud0ul05+6lU9PD8YsCKqMzrTdaKnweE65B4meXtBmm7Ctq0aY+9YLjJO0TaGTkX1ns/npXlhZwBXHdVZ68XfYPEMPG9aXHnYwvYvViwnW28stL4peJgFJ9zm/qb01FgJAiUASKACFFUAH3SwPcrz1wv7jB++oJ/8sz3K///AMH5R5E/GGrogAAAABJRU5ErkJggg==</Image>
+<Url type="text/html" method="GET" template="https://www.amazon.se/s" resultdomain="amazon.se">
+ <Param name="k" value="{searchTerms}"/>
+</Url>
+<SearchForm>https://www.amazon.se/</SearchForm>
+</SearchPlugin>
diff --git a/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/amazondotcom.xml b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/amazondotcom.xml
new file mode 100644
index 0000000000..2af84b936c
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/amazondotcom.xml
@@ -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/. -->
+
+<SearchPlugin xmlns="http://www.mozilla.org/2006/browser/search/">
+<ShortName>Amazon.com</ShortName>
+<InputEncoding>UTF-8</InputEncoding>
+<Image width="32" height="32">data:image/png;base64,AAABAAIAEBAAAAEACACtAQAAJgAAACAgAAABACAArAMAANMBAACJUE5HDQoaCgAAAA1JSERSAAAAEAAAABAIBgAAAB/z/2EAAAF0SURBVDiNpVM9S8NQFD2RvC6KCE6V5gdUHBonF6eQrQ4q6dbVjkKH/gN3oVmLk8VFK7gKuiklU6lguliHpliXhrRLKxyH1NB8aEUP3OHdd+9559z3niQLgelkQvwBIpWSJJKx5k6ng1qthpduFwCwl8+jWCwmszACy7IoCxGLSqUSLSVJxgiOSiXKQlDTddq2HawzipJIELPQ7/fhOA5c14XneTiv19FoNAAA08lksQXbtplT1UQbv7JgFAqUhWBOVek4Dqum+SPBUlTRl1zDMJBOp9FqtYK90Wi02MK8fE3XQxaqpvmNhXEvSFiWxYyiBJOvmiaNQoGartPzPLJzRjbLfgQEN1ly+JzoMYS7fb/x6ZS8wBxB79ZPNMshNTGMe2T3yj/scp3k/Dt4bQCPB/5g1nYB5TA8rLd7YHAN7FwBYhUYtoHNY4Qf0rsFtE/8wiiWs8B2FdjQgI/ZbcgrSPxMcG1g8ABM3ZmiLb8xAdJ/v/Mnx1XnNJorMikAAAAASUVORK5CYIKJUE5HDQoaCgAAAA1JSERSAAAAIAAAACAIBgAAAHN6evQAAANzSURBVFiFtZdPaBRXHMc/r+4GlGAbylYWXZFQaCOt7CSK/+hJt/XSogUDvfTQ0OzBg2hgblEQFA9iLeauBDyYUB3x0kv6J0pr4gZLum0yFIpt3V3cUJoymxwS4edhMnEn+3bmJSFfGNj3m9+832d+7/d7bxaWJCKbRaRPRP6QjdPkUozN1EtE2jc4sA6kHUAt0UwCb2OoWq2G67rLY6UU6XSadDptOgXAr8B+ROScKbbjOHI0l5NEMqm9juZy4jjOajLRhxik3vO8yMArL9u2TQEKmHid7O4OBdiUSMRCGGZiPhbAcRxtgKxlycnu7qaZOZLLmQBILMCXvb2xKbZtWwthotfiSlUp1WDr7+8PjXt6elZT/eH5RUTinOrbTilFZ2dng0+ypaXBtriwEAuQMKFsbW2lq6treVypVCiXy/z86BEAo6OjAIiINmPrBgiC3rh5k+HhYYrFotZntcEBjNrQcRzZkckY7wOrKcLYGpiYmODAwYPae2fPnCGzcye7Ozr46NixhvsmNRCbgaxlabfcUqkU8ltrBiIBXNfVTlwoFEJ+5XJ5Y/aBqakprb2+I6L8KpVK7ApEAvzz7JnWXqvVQuPbQ0Nav/Hx8ViAyCUYGRnRHj71W/Hg4GDTAyprWeJ5XuQSRAI0W9tgcpPWvD4wsHYAkcajOApopW1HJiOu664PoNnHSH3KbdsWz/NCp2LWsmKDGwEEENcHBpZBNiUSkrUs6c3nG1ry4qVL0pvPh9d+riRSfSxSHRdZDNdEeCf8/WvYkoFdn8ZXr4nmyzB2CqoOBFH2XIPdp5t0wey0yDdvinx33CderxY9f565kv/7fofIb9dCLuF94PV34JOnsPAvjOyD70/A0zvwItz3xqqOQfEi3N8OcyWoTUHqUMhFfxi9qMGT8/Dn1Vepy3wBbXsgdRja3oVEa+Mz/03DbBGqD+D5Pf9FFHDgDiS3QvECfPhj/VP/KxGZBN7XvsFMAcY+98mDo34lrqqzrfwc2HYcrMt+ZmceQ8tW//crPVQi0gdc0QIE+usuTH8Fsw/8YEFQHZQC2s/Crs8gtTdyWiAf/DX7CcjGeTNfhpkxmPsbnv+wFFBBss1fnjfeg7f2Ny6PXg+VUh/4LyCSEpF76y97Y90SkVSQsGWJyAngY2Avzepi7foFeAIMKaW+DYwvASfwPtL4PwlOAAAAAElFTkSuQmCC</Image>
+<Url type="text/html" method="GET" template="https://www.amazon.com/s" resultdomain="amazon.com">
+ <Param name="k" value="{searchTerms}"/>
+</Url>
+<SearchForm>https://www.amazon.com/</SearchForm>
+</SearchPlugin>
diff --git a/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/azerdict.xml b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/azerdict.xml
new file mode 100644
index 0000000000..779c658f60
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/azerdict.xml
@@ -0,0 +1,17 @@
+<!-- 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/. -->
+
+<SearchPlugin xmlns="http://www.mozilla.org/2006/browser/search/">
+<ShortName>Azerdict</ShortName>
+<InputEncoding>UTF-8</InputEncoding>
+<Image width="16" height="16">data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGAAAABgCAMAAADVRocKAAAB3VBMVEUAAAD86x776hf76hf76hf76hf76hf76hf87DL76hf87DL76hf76hf76hdXV1f87DL96xb/7hX+7BZTU1n/8hTSyVd+fGD/8xNraU9UVFhWVlfJv1//8BRVVVhPUFpTVFhlZFZQUV1ZWVxRUVn05SB7eWbTyWJdXV1eXltiYlloZlO9tUjr3S756Br/8BZnaG5fYGidmWGEgWFbW1vq3Ubt3iL35yD66h7/7xmUknOemmiRj2hYWmOwq2BgYF+Oil2/uFpYWVpWVlnXzVRsalPSyEb05jf46Cfm1yT/8CP76hq0sH13d3RubnJpanG0r2tmZmrHwGaGg2W1r2RnZ2S9tmLSyl5UVV53dVvOxlrOxVdzcldvblfSx03Nw0zFvEzaz0rQxUqdl0i5sELg1UG2rUDazz+wpzzs3zjl2Dju4DH15jDh1DDy4ij87CLu3yGLiXvZ0XiDgXSYlXOfm3GPjHHDvG+jn26Zlm15d23X0Gy9t2x+fWnn3GiWkWh0c2hra2ZpaWWrpmRqaWSoomJqaWDZ0F/JwF9+e11qaFrLw1a8s1TBuFGalVDh106rpE6XkUzWy0vJv0XFu0Xj10Pn2kHMwkHVyT7g1D2poDjn2THazC7/8if66Sb45xkFAQu1AAAADXRSTlMABtL5xWwbz8LAb2/zKa6xSQAAAxJJREFUaN7tmmVX21AYgANdiy3hRtjWLAnVVaiXtrj7cHeGO8zd3d3tt65lg8DO2uZtd884O3l+QJ5773tyn3wIQRAZ2hwNiQFNjjaDiKLLIrGRpYuuP5PESGYGoSWxoiUOkFg5QGhIrGgIEjOqQBWogsQCtAUJACRAwtzsp8U3HyMcjXAI0Gq1o1asCzqcgb45WkgigQuQ6wZP/UI0V5yu/BKyuBFCf02wYdVTu+BZyWd9ufh6uUTeS1oC4bZI/Q7P19kcDeUDLo5m0hYgJxUHXpR85560bMYOLA2By0AlQDQbuwMz840rgnxgQMG6LIi7k1q7YazscVh2gGYwRiVGHn7HxfehNrCArmGpZMhD8b5oRkABybTzlHLq/BGogAzdghikUQQVoLXqCklUbOhshV924Zap0k6JVbaRwstMCj1AtNA8WjZssJv4ZBr+OA0UyA7PUuPsTK/XaBYxCLbL47ZsttSUeiV9vJ3oTzFpJ5Ohuaaes+MOe+0fDqzjK2DICQ+sZGl6/tnVbuPe4fvuo/QFcqkjltBa30mfPBRTTxu8yckPrPhKeYPDFgxWWa/RJEAAObDWd9NFU89bEQkQwNj9ZbP/PrxUQXIBswOdiFSHTG/UF2zz4Gh8Rt7KCojAdcbI7qBPQKHZ+/Q7WEC/uqOnFMNWW4ACVGzjKQD66wJMUGKlYJgbQT1AJ+wUkIccSFAUhAqcFpjABBUY1kGCCRtUMA6Lfv4jCoZYCRPQ50UKAn/TA3zRPHeHIOu/twyOfqSmQlS6fPbS5xTuIrqpq/eQIspHOBIu2Go6pwiB3rfBUQX/XIAYZaQc/W+x6A8eizFYEJ/6JiG16Jf+jH5hDDYRUvukGx79iX5R+VXH+t3g6Jtg0S/DHX1pAXf0AwLmJjubcUd/BSSYtIF30AYa8qqBgsH7BVj0u/Sw51eFETD6fiPo+R8Y6FURrhxS/KqJ/QupRL/4wvARJTQEBjwopegL3GFFcGr0VcEeVMH/KNCQWDmI/7eHPBIrefh/PSF0GA2ZOiJKRm52Phayc6Pr/wHPrTIRNf30iwAAAABJRU5ErkJggg==</Image>
+<Url type="application/x-suggestions+json" method="GET" template="https://api.azerdict.com/english/autocomplete">
+ <Param name="action" value="opensearch" />
+ <Param name="query" value="{searchTerms}" />
+</Url>
+<Url type="text/html" method="GET" template="https://azerdict.com/english/" resultdomain="azerdict.com">
+ <Param name="word" value="{searchTerms}"/>
+</Url>
+<SearchForm>https://azerdict.com/</SearchForm>
+</SearchPlugin>
diff --git a/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/baidu.xml b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/baidu.xml
new file mode 100644
index 0000000000..494d8b1b06
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/baidu.xml
@@ -0,0 +1,25 @@
+<!-- This Source Code Form is subject to the terms of the Mozilla Public
+ - License, v. 2.0. If a copy of the MPL was not distributed with this
+ - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
+
+<SearchPlugin xmlns="http://www.mozilla.org/2006/browser/search/">
+ <ShortName>百度</ShortName>
+ <InputEncoding>UTF-8</InputEncoding>
+ <Image width="16" height="16">data:image/png;base64,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</Image>
+ <Url type="application/x-suggestions+json" method="GET" template="https://m.baidu.com/su">
+ <Param name="wd" value="{searchTerms}"/>
+ <Param name="action" value="opensearch"/>
+ <Param name="ie" value="UTF-8"/>b
+ </Url>
+ <Url type="text/html" method="GET" template="https://m.baidu.com/s">
+ <Param name="word" value="{searchTerms}"/>
+ </Url>
+ <!-- As of Bug 861164, we can do a client-side detection to determine whether a user is using
+ tablet or a phone(relative to this case).
+ Note: The order of <URL> DOES not affect the way we pick between them.
+ -->
+ <Url type="application/x-moz-tabletsearch" method="GET" template="https://m.baidu.com/s">
+ <Param name="word" value="{searchTerms}"/>
+ </Url>
+ <SearchForm>https://m.baidu.com/</SearchForm>
+</SearchPlugin>
diff --git a/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/bing.xml b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/bing.xml
new file mode 100644
index 0000000000..0b3bc82461
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/bing.xml
@@ -0,0 +1,24 @@
+<!-- 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/. -->
+
+<SearchPlugin xmlns="http://www.mozilla.org/2006/browser/search/">
+<ShortName>Bing</ShortName>
+<Image width="32" height="32">data:image/png;base64,AAABAAEAICAAAAEAIACoEAAAFgAAACgAAAAgAAAAQAAAAAEAIAAAAAAAABAAABILAAASCwAAAAAAAAAAAAD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD+0k4S/NFTevzNUtb6yFL/98JQ//W8Tv/ytEz/76tIuO6hREf///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A/tVSNv7UVeT80VX/+81T//rIUv/3wlD/9bxO//K0TP/vq0n/76JG/++YQrjwijcS////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP/WUzb+1lby/tRW//zRVf/7zVP/+shS//fCUP/1vE7/8rRM/++rSf/uokb/75hD//COP/Lxgzp6////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD/108S/9dX8v7WVv/+1Fb//NFV//vNU//6yFL/98JQ//S8Tv/ytEz/7qtJ/+6hRf/umEP/8I4///CEO//xezfH8HEyJP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP/YVInrk0Tz310u6dxTKffjcDbn8adK9vrIUv/3wlD/9LxO//K0TP/uq0n/7qFF/+6XQv/vjT7/74M7/+96N//ucDLy7mYsWP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A64RB7N9PI//fTiH/304h/99OIf/fUCT/5XE67vfCUP/0vE7/8bNL/+6qSf/toUX/7ZZB/+6MPf/ugjn/7ng1/+xuMP/qZSz/4381vf///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////APerRWHkWiz/41Qk/+NUJP/jVCT/41Qk/+NUJP/jVCT/98JPR/S7TOTxs0v/7apI/+ygRP/slkH/7Ys8/+yAN//rdjP/6Wwt/+dhKP/jWyT31NxgQP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A6nAwUudbJ//nWyf/51sn/+dbJ//nWyf/51sn/+dbJ/////8A////APGySInsqUfy7J9D/+uUP//riTr/6n41/+lzMP/maCr/410k/95THv/V212w////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wDqYStF6mEr/+phK//qYSv/6mEr/+phK//qYSv/6mEr/////wD///8A////AOynRCTqnUC46ZI9/+mHOP/nezP/5XAt/+JkJv/eWB//2FAZ99bbWv/V3F8Q////AP///wD///8A////AP///wD///8A////AP///wD///8A////AO1oLUXtaC3/7Wgt/+1oLf/taC3/7Wgt/+1oLf/taC3/////AP///wD///8A////AP///wDnkDpH5oQ01uR4L//hbCn/3V8h/9hTGv/VbyHq19pV/9XbXED///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A724vRe9uL//vbi//724v/+9uL//vbi//724v/+9uL/////8A////AP///wD///8A////AP///wD///8A4HMqetxnJPLXWRv/1GMZ7dvOQv/Z2k//1ttYQP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wDyczFF8nMx//JzMf/yczH/8nMx//JzMf/yczH/8nMx/////wD///8A////AP///wD///8A////AO3NGxDp0BRg5MYctt2wIv/f1jT/3NhA/9rZSv/Y2lNA////AP///wD///8A////AP///wD///8A////AP///wD///8A////APR6MkX0ejL/9Hoy//R6Mv/0ejL/9Hoy//R6Mv/0ejL/////AP///wD///8A////APbEKhDzxyWQ78of/+vOGP/n0RT/5NMh/+HVLf/e1zn/29hF/9naTjD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A9YAzRfWAM//1gDP/9YAz//WAM//1gDP/9YAz//WAM/////8A////AP///wD///8A+MMswPXFKP/xyCL/7cwc/+nQFf/l0hr/49Qm/+DWMv/d1z/g////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD3hzRF94c0//eHNP/3hzT/94c0//eHNP/3hzT/94c0/////wD///8A////APzAMiD5wi7/98Qq//TGJv/wyiD/7M4Z/+fREv/k0h//4dQr/97WN4D///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////APiNNUX4jTX/+I01//iNNf/4jTX/+I01//iNNf/4jTX/////AP///wD///8A/b8zkPvBMP/4wyz/9sUp//LII//uyx3/6s8W/+bSGP/j0yTQ4NUwEP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A+pI2RfqSNv/6kjb/+pI2//qSNv/6kjb/+pI2//qSNv////8A////AP///wD9vzTw/L8y//rBL//3wyv/9MYn//DJIP/szRr/6NET8OXSHTD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD7mDdF+5g3//uYN//7mDf/+5g3//uYN//7mDf/+5g3/////wD///8A/r42UP6+Nf/9vzP/+8Ax//nCLf/2xCn/88ck/+/LHsDrzxcQ////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////APudN0X7nTf/+503//udN//7nTf/+503//udN//7nTf/////AP///wD/vTew/r41//6+NP/9vzP/+sEv//jDLMD1xShA////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A+qA4RfqgOP/6oDj/+qA4//qgOP/6oDj/+qA4//qgOP////8A////AP+9N/D/vTb//r41//2/NOD8wDFQ////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD5ozhF+aM4//mjOP/5ozj/+aM4//mjOP/5ozj/+aM4/////wD///8A/703MP+9N8D+vjZg////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////APmnOUX5pzn/+ac5//mnOf/5pzn/+ac5//mnOf/5pzn/////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A+ao5RfmqOf/5qjn/+ao5//mqOf/5qjn/+ao5//mqOf////8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD5rTlF+a05//mtOf/5rTn/+a05//mtOf/5rTn/+a05/////wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////APixOkX4sTr/+LE6//ixOv/4sTr/+LE6//ixOv/4sTr/////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A97M6RfezOv/3szr/97M6//ezOv/3szr/97M6//ezOfH///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD3tztF97c7//e3O//3tzv/97c7//e3O//3tzv/97c6hv///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////APa6O0X2ujv/9ro7//a6O//2ujv/9ro7//a6Oob///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A9b08RfW9PP/1vTz/9b08//W9O9T1vTs0////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD1wD4S9b871PW/O/H1vzp2////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A///////AH///gAf//wAD//4AAP/+AAB//gAAP/wAAB/8AwAf/AOAD/wD4A/8A/gP/APwD/wDwA/8A8Af/AOAH/wDgB/8A4A//AMAf/wDAf/8Awf//AMf//wD///8A////AP///wD///8A////AP///wH///8D////D////////8=</Image>
+<Url type="application/x-suggestions+json" template="https://www.bing.com/osjson.aspx">
+ <Param name="query" value="{searchTerms}"/>
+ <Param name="language" value="{moz:locale}"/>
+</Url>
+<!-- this is effectively x-moz-phonesearch, but search service expects a text/html entry -->
+<Url type="text/html" method="GET" template="https://www.bing.com/search">
+ <Param name="q" value="{searchTerms}" />
+ <Param name="pc" value="MOZB" />
+ <Param name="form" value="MOZMBA" />
+</Url>
+<Url type="application/x-moz-tabletsearch" method="GET" template="https://www.bing.com/search">
+ <Param name="q" value="{searchTerms}" />
+ <Param name="pc" value="MOZA" />
+ <Param name="form" value="MOZAT" />
+</Url>
+<SearchForm>http://www.bing.com</SearchForm>
+</SearchPlugin>
diff --git a/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/ceneje.xml b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/ceneje.xml
new file mode 100644
index 0000000000..624c8ebde4
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/ceneje.xml
@@ -0,0 +1,15 @@
+<!-- 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/. -->
+
+<SearchPlugin xmlns="http://www.mozilla.org/2006/browser/search/">
+<ShortName>m.Ceneje.si</ShortName>
+<Description>Mobilni iskalnik Ceneje.si</Description>
+<InputEncoding>UTF-8</InputEncoding>
+<Image height="16" width="16" type="image/x-icon">data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGAAAABgCAMAAADVRocKAAAAnFBMVEX6qxgAAAD6qxj6qxj6qxj6qxj////7wFL+6sX9/f391Yz7+/v6+fn4+Pjs7Ozv7+/8y2/w7/Do6Oj19fXz8/Py8vLn5ubk5OTi4uL7u0P/+vH65sH5vU/2ukz7v1D29fXy8fH14bzw3Lfq1rL704n80H36tTT6sCb+9eL93qT3z4X8xWDz7uTz693yyoH3tz/+79Tt49H95bfvx37SQQ9XAAAABXRSTlPvAJ8gMC39vXwAAAHiSURBVGje7drpasJAFIbhE+1kc4vdo0laTd1bu93/vXWkH1UIhszUr1SY9+/AeRAimQkjntduiaIkrbbniXchipZceNIWRUyPbylqLRFFDfOJOcABDnCAAxzggN8D81yXZVlRFEFdqSWQvtzf9geP171uJ4r8uhIrIB0NKoC5IDXz/QpgIUjN/ApgI8jx+RXASpCj8yuAnSDH5lcAS0GOzDcEIDQFMN9/LsvpdDIZ68K6ngfotSHgo1A1q7xHOQu4RSxg2kc0YIAyEjC5QTTgCrGAcQ/RgC4qWEAHnQ6Yz+LkAIjQyYDNSK++LRQKIxScCFjo+brVD+CjUwEB1s8XmGPZGohQFUArXzdKGQBKwnCVKmugg8aqNnugi2hAD9GABzRhAdeIBgzRlAX0EQ24RCULuEMl+xe8x3U96dbr9Xb7+eKjtCGQ+A2Kok63d3Uz7F/eDQ02vxAMAZPtOwQzwOgAAsEIMDtCQTABDA+BEAwA02MshOYA5ifLZWwAQGgCJPu9QGwAqDSoqyiKTJfnOY5m8Q4IiZ9zZjvgQyECsFjutxoMQAvJbK7Q//jiZdksTBQiAN9P90YhBhAf/BsowObg1UYBVBCnCp3pU+QABzjgzwGyIPSLG/SrJ/TLM/TrP1+lfdf1LcQ9IwAAAABJRU5ErkJggg==</Image>
+<Url type="text/html" method="GET" template="https://www.ceneje.si/search_new.aspx">
+ <Param name="q" value="{searchTerms}" />
+ <Param name="FF-SearchBox" value="1" />
+</Url>
+<SearchForm>https://ceneje.si</SearchForm>
+</SearchPlugin>
diff --git a/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/coccoc.xml b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/coccoc.xml
new file mode 100644
index 0000000000..1baa2a3118
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/coccoc.xml
@@ -0,0 +1,21 @@
+<?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/. -->
+
+<SearchPlugin xmlns="http://www.mozilla.org/2006/browser/search/">
+<ShortName>Cốc Cốc</ShortName>
+<InputEncoding>UTF-8</InputEncoding>
+<Image width="16" height="16">data:image/png;base64,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</Image>
+<Url type="application/x-suggestions+json" method="GET"
+ template="https://coccoc.com/composer/autocomplete">
+ <Param name="of" value="b" />
+ <Param name="q" value="{searchTerms}"/>
+ <Param name="s" value="ff"/>
+</Url>
+<Url type="text/html" method="GET" template="https://coccoc.com/search" resultdomain="coccoc.com">
+ <Param name="query" value="{searchTerms}"/>
+ <Param name="s" value="ff"/>
+ <Param name="utm_source" value="ffmobile"/>
+</Url>
+</SearchPlugin>
diff --git a/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/daum-kr.xml b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/daum-kr.xml
new file mode 100644
index 0000000000..b86cb446ee
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/daum-kr.xml
@@ -0,0 +1,21 @@
+<!-- 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/. -->
+
+<SearchPlugin xmlns="http://www.mozilla.org/2006/browser/search/">
+<ShortName>다음</ShortName>
+<InputEncoding>utf-8</InputEncoding>
+<Image width="16" height="16">data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGAAAABgCAMAAADVRocKAAAARVBMVEUAAAD5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+flNkP//1Smn3wAoffz9dG7kWlfjngNhtAAke/0gdv9isiRZrCSQTyACAAAACnRSTlMAwwbS+W9sG8/zKHP4TgAAALhJREFUaN7t2ksOwjAMRdGXfzEQoAH2v1QKE6ARIi0yQvTdmSc5Y0cGYKPxopA30WIodaJWlwDrRDFnEUW1CCOqGXhRzUOUI0CAAAECBL4D5MaO+dyPO1TtqyYA/bKBcu3+Wrn1NM0HmjvNB0peN7St2lTtHiJAgAABAgQIECBAgAABApOB1j5cY9/264s4gdfAH/x4jWYCBAiIECCwSMCLaiv9s4cgqgX90xMkRcElDNlgRCUTLHAB68OktAP7gdIAAAAASUVORK5CYII=</Image>
+<Url type="application/x-suggestions+json" method="GET" template="http://sug.search.daum.net/search_nsuggest">
+ <Param name="mod" value="fxjson" />
+ <Param name="code" value="utf_in_out" />
+ <Param name="q" value="{searchTerms}" />
+</Url>
+
+<Url type="text/html" method="GET" template="https://m.search.daum.net/search">
+ <Param name="w" value="tot"/>
+ <Param name="nil_ch" value="ffsr"/>
+ <Param name="q" value="{searchTerms}"/>
+</Url>
+<SearchForm>http://m.search.daum.net</SearchForm>
+</SearchPlugin>
diff --git a/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/ddg.xml b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/ddg.xml
new file mode 100644
index 0000000000..21364b08aa
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/ddg.xml
@@ -0,0 +1,23 @@
+<!-- This Source Code Form is subject to the terms of the Mozilla Public
+ - License, v. 2.0. If a copy of the MPL was not distributed with this
+ - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
+
+<SearchPlugin xmlns="http://www.mozilla.org/2006/browser/search/">
+<ShortName>DuckDuckGo</ShortName>
+<InputEncoding>UTF-8</InputEncoding>
+<Image width="32" height="32">data:image/png;base64,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</Image>
+<Url type="application/x-suggestions+json" method="GET" template="https://ac.duckduckgo.com/ac/">
+ <Param name="q" value="{searchTerms}"/>
+ <Param name="type" value="list"/>
+</Url>
+<!-- this is effectively x-moz-phonesearch, but search service expects a text/html entry -->
+<Url type="text/html" method="GET" template="https://duckduckgo.com/">
+ <Param name="q" value="{searchTerms}" />
+ <Param name="t" value="fpas" />
+</Url>
+<Url type="application/x-moz-tabletsearch" method="GET" template="https://duckduckgo.com/">
+ <Param name="q" value="{searchTerms}" />
+ <Param name="t" value="fpas" />
+</Url>
+<SearchForm>https://duckduckgo.com</SearchForm>
+</SearchPlugin>
diff --git a/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/ebay-at.xml b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/ebay-at.xml
new file mode 100644
index 0000000000..31ac7f6b9b
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/ebay-at.xml
@@ -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/. -->
+
+<SearchPlugin xmlns="http://www.mozilla.org/2006/browser/search/">
+<ShortName>eBay</ShortName>
+<InputEncoding>UTF-8</InputEncoding>
+<Image width="68" height="68">data:image/png;base64,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</Image>
+<Url type="application/x-suggestions+json" method="GET" template="https://autosug.ebay.at/autosug?sId=16&amp;fmt=osr&amp;kwd={searchTerms}"/>
+<Url type="text/html" method="GET" template="https://www.ebay.at/sch/">
+ <Param name="kw" value="{searchTerms}"/>
+ <Param name="toolid" value="20004"/>
+ <Param name="campid" value="5338791379"/>
+ <Param name="mkevt" value="1"/>
+ <Param name="mkcid" value="1"/>
+ <Param name="mkrid" value="5221-53469-19255-0"/>
+</Url>
+<SearchForm>https://www.ebay.at/</SearchForm>
+</SearchPlugin>
diff --git a/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/ebay-au.xml b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/ebay-au.xml
new file mode 100644
index 0000000000..490b34de9e
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/ebay-au.xml
@@ -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/. -->
+
+<SearchPlugin xmlns="http://www.mozilla.org/2006/browser/search/">
+<ShortName>eBay</ShortName>
+<InputEncoding>UTF-8</InputEncoding>
+<Image width="68" height="68">data:image/png;base64,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</Image>
+<Url type="application/x-suggestions+json" method="GET" template="https://autosug.ebay.au/autosug?sId=15&amp;fmt=osr&amp;kwd={searchTerms}"/>
+<Url type="text/html" method="GET" template="https://www.ebay.com.au/sch/">
+ <Param name="kw" value="{searchTerms}"/>
+ <Param name="toolid" value="20004"/>
+ <Param name="campid" value="5338791379"/>
+ <Param name="mkevt" value="1"/>
+ <Param name="mkcid" value="1"/>
+ <Param name="mkrid" value="705-53470-19255-0"/>
+</Url>
+<SearchForm>https://www.ebay.com.au/</SearchForm>
+</SearchPlugin>
diff --git a/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/ebay-befr.xml b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/ebay-befr.xml
new file mode 100644
index 0000000000..db76954be3
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/ebay-befr.xml
@@ -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/. -->
+
+<SearchPlugin xmlns="http://www.mozilla.org/2006/browser/search/">
+<ShortName>eBay</ShortName>
+<InputEncoding>UTF-8</InputEncoding>
+<Image width="68" height="68">data:image/png;base64,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</Image>
+<Url type="application/x-suggestions+json" method="GET" template="https://autosug.befr.ebay.be/autosug?sId=23&amp;fmt=osr&amp;kwd={searchTerms}"/>
+<Url type="text/html" method="GET" template="https://www.befr.ebay.be/sch/">
+ <Param name="kw" value="{searchTerms}"/>
+ <Param name="toolid" value="20004"/>
+ <Param name="campid" value="5338791379"/>
+ <Param name="mkevt" value="1"/>
+ <Param name="mkcid" value="1"/>
+ <Param name="mkrid" value="1553-53471-19255-0"/>
+</Url>
+<SearchForm>https://www.befr.ebay.be/</SearchForm>
+</SearchPlugin>
diff --git a/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/ebay-ca.xml b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/ebay-ca.xml
new file mode 100644
index 0000000000..7cf4fc531e
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/ebay-ca.xml
@@ -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/. -->
+
+<SearchPlugin xmlns="http://www.mozilla.org/2006/browser/search/">
+<ShortName>eBay</ShortName>
+<InputEncoding>UTF-8</InputEncoding>
+<Image width="68" height="68">data:image/png;base64,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</Image>
+<Url type="application/x-suggestions+json" method="GET" template="https://autosug.ebay.ca/autosug?sId=2&amp;fmt=osr&amp;kwd={searchTerms}"/>
+<Url type="text/html" method="GET" template="https://www.ebay.ca/sch/">
+ <Param name="kw" value="{searchTerms}"/>
+ <Param name="toolid" value="20004"/>
+ <Param name="campid" value="5338791379"/>
+ <Param name="mkevt" value="1"/>
+ <Param name="mkcid" value="1"/>
+ <Param name="mkrid" value="706-53473-19255-0"/>
+</Url>
+<SearchForm>https://www.ebay.ca/</SearchForm>
+</SearchPlugin>
diff --git a/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/ebay-ch.xml b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/ebay-ch.xml
new file mode 100644
index 0000000000..7557e24c6c
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/ebay-ch.xml
@@ -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/. -->
+
+<SearchPlugin xmlns="http://www.mozilla.org/2006/browser/search/">
+<ShortName>eBay</ShortName>
+<InputEncoding>UTF-8</InputEncoding>
+<Image width="68" height="68">data:image/png;base64,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</Image>
+<Url type="application/x-suggestions+json" method="GET" template="https://autosug.ebay.ch/autosug?sId=193&amp;fmt=osr&amp;kwd={searchTerms}"/>
+<Url type="text/html" method="GET" template="https://www.ebay.ch/sch/">
+ <Param name="kw" value="{searchTerms}"/>
+ <Param name="toolid" value="20004"/>
+ <Param name="campid" value="5338791379"/>
+ <Param name="mkevt" value="1"/>
+ <Param name="mkcid" value="1"/>
+ <Param name="mkrid" value="5222-53480-19255-0"/>
+</Url>
+<SearchForm>https://www.ebay.ch/</SearchForm>
+</SearchPlugin>
diff --git a/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/ebay-co-uk.xml b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/ebay-co-uk.xml
new file mode 100644
index 0000000000..06e8f22820
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/ebay-co-uk.xml
@@ -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/. -->
+
+<SearchPlugin xmlns="http://www.mozilla.org/2006/browser/search/">
+<ShortName>eBay</ShortName>
+<InputEncoding>UTF-8</InputEncoding>
+<Image width="68" height="68">data:image/png;base64,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</Image>
+<Url type="application/x-suggestions+json" method="GET" template="https://autosug.ebay.co.uk/autosug?sId=3&amp;fmt=osr&amp;kwd={searchTerms}"/>
+<Url type="text/html" method="GET" template="https://www.ebay.co.uk/sch/">
+ <Param name="kw" value="{searchTerms}"/>
+ <Param name="toolid" value="20004"/>
+ <Param name="campid" value="5338791379"/>
+ <Param name="mkevt" value="1"/>
+ <Param name="mkcid" value="1"/>
+ <Param name="mkrid" value="710-53481-19255-0"/>
+</Url>
+<SearchForm>https://www.ebay.co.uk/</SearchForm>
+</SearchPlugin>
diff --git a/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/ebay-de.xml b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/ebay-de.xml
new file mode 100644
index 0000000000..8e05c24fe8
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/ebay-de.xml
@@ -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/. -->
+
+<SearchPlugin xmlns="http://www.mozilla.org/2006/browser/search/">
+<ShortName>eBay</ShortName>
+<InputEncoding>UTF-8</InputEncoding>
+<Image width="68" height="68">data:image/png;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/4QB+RXhpZgAASUkqAAgAAAACADEBAgAHAAAAJgAAAGmHBAABAAAALgAAAAAAAABHb29nbGUAAAMAAJAHAAQAAAAwMjIwAaADAAEAAAABAAAABaAEAAEAAABYAAAAAAAAAAIAAQACAAQAAABSOTgAAgAHAAQAAAAwMTAwAAAAAP/bAIQAAwICCw0LCwMJCgsJCQgKCAgKDQgLCQgJCAoICwoKCQgICAoICgoJCAgJDgkNCwgICAoVFQsIDAwYDQsYCAsKFAEDBAQGBQYKBgYKEA4LDg8VEBISEg4RDxANDRIQEQ8NDg4QDQ0UDhIOEQ8PFA0NDxAOEhIQEA8OEA4ODQ4QDRQQ/8AAEQgARABEAwERAAIRAQMRAf/EABsAAQADAQADAAAAAAAAAAAAAAAGBwgFAwQJ/8QALxAAAgEDAgUCBgEFAQAAAAAAAQIDAAQRBRIGBxMhIjEyCBRBQlFiYRUjM1JxFv/EABwBAQADAQEBAQEAAAAAAAAAAAAFBgcECAMCAf/EADgRAAEDAgQEBAMDDQAAAAAAAAEAAhEDBAUSITEGQVFhEyJxgRSRoTJCsQcWIyQzUnKCosHC0fD/2gAMAwEAAhEDEQA/APqnREoiURKIlESiJREoiURKIlESiJREoiURKIlESiJREoirrSuettJqc3LJVm+btYhO5ZUEBUpC/i/ULFsSp2MY7g9+wqcqYPXp2LMQJHhuMDXWZI1ER908+ii2YjSfdOsxOdok6aRod57qxag1KJREoiURKIlEVIc1PiCljvE5e6Xai91B1DydR+nBaoRuDSkd2IXazDcmFdfJi6oYyvdubUFGk2XfQeq0DB+GqNaydieJVjStwYECX1DMQ0eugMHUHQAEiO8U84tbsEGu6nY2VxZhkWVtNkmEsAchQzCbs3cgDsBuIBdM5r4vuLmgM1VoLe06fNSdngeBYu/4bD7iqytByiq1uV8awCzbTXrGwKomHnBs4nu+JbGB9Qk1C0torOKMiPqvcWtjIpldv8UcaI5kYg7dhzjBYb1b2tO+4aty+oGUw4vc4iYbmeNANySQAF5qvjWwziG5oPpk1R5Moj7QDee0aTPTXZXPxnzf4jsozxPeafYXFlHhplsZZ+vAn1d3csCF+50hcD1O0AsK9aYZgt88W9CvUbUOxe1uVx6ADXXlJHuVJ3N9ido01qtJjmDcNJzNHUz/AGH0VnaZz2jns7fiWwie4+cyEUggwsh2SJOV3BXjk8cA4ONwbGGrIeMb274eqC1Zbuq1y6AGzljSHFwGgMiJjnMQVe8Bp0MVp/EeIGU4kzE+gE7iNfpMhezqfEmoxIdTlhtnjQbnWJpBIqj1OSSO31IDfnBqk3mK8S4fRdeXFCg6m0S5rHOD2t5mSY05wCrBRtMLuHijTqVA46AkCCeW2uvLZcjl7z4M90eH5olh3qzQMGJ6m3J2kEYyUDdwfchFffh7jMYrcCi+mGBwJYZ3g7HvAO3Qqr3dF9pcvtqu459RuD7j/Sn/AB9xgttbya0/fpr4rnG927Rpn9mIyQDgZP0q7YtiLMOtKly/XKNB+846NHufluvg9+RpK8XLniKWe3j1ieNYmmBdVQk4jPsYk/Vx5f8AGH81+MHvK17aMuK7Awu1ABny/dOvUa+hC/lNxc2Ssg3vDr/+lvdLe+l0uS8XfBND08zq6wFIMyDG19jgY9ZLfZ69q4iw/GOaXFs7Hrtp/wB0XoendU/zXt6zLdtdtMw5rp8hBdLvLrIzAns+dlPeb/K35e1efVOIr75WXETK8ccpm3keCxRo0j49TsU4VSxwFJrruKGRh8WsY/FVzBMY+Lu2tw7C6PijzAhzhljmXOdlHQSdSQBqQqH5CanZ2PEYgadntZraKK2nuk+XbN5bW88LSI4Uxb1JjXcB71zjca2+2sqlbhGgy3l2Ul22pbnfy7TPoF56x/ES/jG7q3bWse4hhAOZrXhjGmHTBnLvO5W4uefGkFtp91qVyyiM288aqxGZ3kRlSFFJ82kJxgfQk9gCaomEWlW6vKVOiDOYH+EAyXHsN1KYhcU6Fu99U6ZT76bD1WVPg7e6Syg4e6ptY764mukcjDmJ1WJdpOCFeSJym0jJkByQRVF/K7j1zccV2+C2dbwWmm3O8RJcS85QT2AaIM5jB2hSnAWHU6OC1L6uzOc5LWmYDYaNR83emq0bxxwSsVvJeSXt0x2Mqq83jK7DCoU2+SsfcoPtz+KzXiPh6nh+HVq9fELknKQGureV7iIDS2NQTuOk8ldMNxF1xcsp07ekNdwzVo5mZ0I5Hqq617hJjp9vxjB2uLCSRyR6mISs2T+ei/lj/Vnqu4bh7zw7bYjb6VaLnH+XxCf6Tr6ZuqguKmfrznjcAfgF0Nd4l/qtxZ8Px5FuiLd3WM+LY84yf0z01YfdMT9tWq7vRxLd21pS/ZACpU7Hm32+wO7p5Kql3jODRtuVo6OMACMDAAAAHYAD0AH0A/FbGAAIGykFDeZPJyyvlFvfW6zbMhGy0csYbGQkqMrhWIGU3YOBkHFc9a3p1hFQSp3CscvsKeX2dUtncaFp6S1wInoYkcioVonwf6VHIuoNA9w0fsF3NNcIuO+Ok77GX08XVh/FczcPoNMxPqSVP3HG+L1qZpNqBgO+RjWE+7RM9wQpDrPw6aZLPPxBPZpNPexiCcytK6uiiIKBEZOnGyCOLbJEikFMgjJNW6ljl9Ro06FOqWsYZaAAIOvOJI8xkExrssuqYVa1Kr6z2AucIMkmRpymOQ1AlQ2w+CDRlkW8NtJKI/ZHPcTywp+ojaTyT08HLDt3BqVfxbibmFoqATuQxoJ9wN+4XC3h6xDgSwmNgXEgexKtrXuAreVVtJIl2xALHs/tmNRgBU24wgAHh6dvTtWX4zgVljIAvqecjYyQ4Tv5gZ15g6K52V/Xsj+gdA6cu2h0XP07lRaqersaRsFQZXeQqGGDtycKcfcBn+RUTbcH4XQdn8MvdBAL3udAIg5ZMAxzAkciF2Vcau6gy5g0TPlAEkdYGvovDxZJHZ2UqwxF1CuscYDy9R5cgKQdzFCSS36g1016NvgeGPp2lI5QDlZ5ny53LWXRJk9pURe3dSu41aplx7D0GwUZ+G7l8YLb+pSLia7w5DDDJEuekhB7gt3cj9wPtqL4Mwg2Nn4tQRUqamdw0fZH+R9Y5Lgt6eVsncq3K0BdSURKIlESiJREoiURKIlESiJREoiURKIlESiJREoiURKIlESiJREoiURKIlEX/9k=</Image>
+<Url type="application/x-suggestions+json" method="GET" template="https://autosug.ebay.de/autosug?sId=77&amp;fmt=osr&amp;kwd={searchTerms}"/>
+<Url type="text/html" method="GET" template="https://www.ebay.de/sch/">
+ <Param name="kw" value="{searchTerms}"/>
+ <Param name="toolid" value="20004"/>
+ <Param name="campid" value="5338791379"/>
+ <Param name="mkevt" value="1"/>
+ <Param name="mkcid" value="1"/>
+ <Param name="mkrid" value="707-53477-19255-0"/>
+</Url>
+<SearchForm>https://www.ebay.de/</SearchForm>
+</SearchPlugin>
diff --git a/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/ebay-es.xml b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/ebay-es.xml
new file mode 100644
index 0000000000..6e7d644d1d
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/ebay-es.xml
@@ -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/. -->
+
+<SearchPlugin xmlns="http://www.mozilla.org/2006/browser/search/">
+<ShortName>eBay</ShortName>
+<InputEncoding>UTF-8</InputEncoding>
+<Image width="68" height="68">data:image/png;base64,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</Image>
+<Url type="application/x-suggestions+json" method="GET" template="https://autosug.ebay.es/autosug?sId=186&amp;fmt=osr&amp;kwd={searchTerms}"/>
+<Url type="text/html" method="GET" template="https://www.ebay.es/sch/">
+ <Param name="kw" value="{searchTerms}"/>
+ <Param name="toolid" value="20004"/>
+ <Param name="campid" value="5338791379"/>
+ <Param name="mkevt" value="1"/>
+ <Param name="mkcid" value="1"/>
+ <Param name="mkrid" value="1185-53479-19255-0"/>
+</Url>
+<SearchForm>https://www.ebay.es/</SearchForm>
+</SearchPlugin>
diff --git a/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/ebay-fr.xml b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/ebay-fr.xml
new file mode 100644
index 0000000000..a060af1ca4
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/ebay-fr.xml
@@ -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/. -->
+
+<SearchPlugin xmlns="http://www.mozilla.org/2006/browser/search/">
+<ShortName>eBay</ShortName>
+<InputEncoding>UTF-8</InputEncoding>
+<Image width="68" height="68">data:image/png;base64,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</Image>
+<Url type="application/x-suggestions+json" method="GET" template="https://autosug.ebay.fr/autosug?sId=71&amp;fmt=osr&amp;kwd={searchTerms}"/>
+<Url type="text/html" method="GET" template="https://www.ebay.fr/sch/">
+ <Param name="kw" value="{searchTerms}"/>
+ <Param name="toolid" value="20004"/>
+ <Param name="campid" value="5338791379"/>
+ <Param name="mkevt" value="1"/>
+ <Param name="mkcid" value="1"/>
+ <Param name="mkrid" value="709-53476-19255-0"/>
+</Url>
+<SearchForm>https://www.ebay.fr/</SearchForm>
+</SearchPlugin>
diff --git a/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/ebay-ie.xml b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/ebay-ie.xml
new file mode 100644
index 0000000000..2397a28e79
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/ebay-ie.xml
@@ -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/. -->
+
+<SearchPlugin xmlns="http://www.mozilla.org/2006/browser/search/">
+<ShortName>eBay</ShortName>
+<InputEncoding>UTF-8</InputEncoding>
+<Image width="68" height="68">data:image/png;base64,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</Image>
+<Url type="application/x-suggestions+json" method="GET" template="https://autosug.ebay.ie/autosug?sId=205&amp;fmt=osr&amp;kwd={searchTerms}"/>
+<Url type="text/html" method="GET" template="https://www.ebay.ie/sch/">
+ <Param name="kw" value="{searchTerms}"/>
+ <Param name="toolid" value="20004"/>
+ <Param name="campid" value="5338791379"/>
+ <Param name="mkevt" value="1"/>
+ <Param name="mkcid" value="1"/>
+ <Param name="mkrid" value="5282-53468-19255-0"/>
+</Url>
+<SearchForm>https://www.ebay.ie/</SearchForm>
+</SearchPlugin>
diff --git a/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/ebay-it.xml b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/ebay-it.xml
new file mode 100644
index 0000000000..8fe7c4313b
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/ebay-it.xml
@@ -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/. -->
+
+<SearchPlugin xmlns="http://www.mozilla.org/2006/browser/search/">
+<ShortName>eBay</ShortName>
+<InputEncoding>UTF-8</InputEncoding>
+<Image width="68" height="68">data:image/png;base64,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</Image>
+<Url type="application/x-suggestions+json" method="GET" template="https://autosug.ebay.it/autosug?sId=101&amp;fmt=osr&amp;kwd={searchTerms}"/>
+<Url type="text/html" method="GET" template="https://www.ebay.it/sch/">
+ <Param name="kw" value="{searchTerms}"/>
+ <Param name="toolid" value="20004"/>
+ <Param name="campid" value="5338791379"/>
+ <Param name="mkevt" value="1"/>
+ <Param name="mkcid" value="1"/>
+ <Param name="mkrid" value="724-53478-19255-0"/>
+</Url>
+<SearchForm>https://www.ebay.it/</SearchForm>
+</SearchPlugin>
diff --git a/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/ebay-nl.xml b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/ebay-nl.xml
new file mode 100644
index 0000000000..f265d912a6
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/ebay-nl.xml
@@ -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/. -->
+
+<SearchPlugin xmlns="http://www.mozilla.org/2006/browser/search/">
+<ShortName>eBay</ShortName>
+<InputEncoding>UTF-8</InputEncoding>
+<Image width="68" height="68">data:image/png;base64,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</Image>
+<Url type="application/x-suggestions+json" method="GET" template="https://autosug.ebay.nl/autosug?sId=146&amp;fmt=osr&amp;kwd={searchTerms}"/>
+<Url type="text/html" method="GET" template="https://www.ebay.nl/sch/">
+ <Param name="kw" value="{searchTerms}"/>
+ <Param name="toolid" value="20004"/>
+ <Param name="campid" value="5338791379"/>
+ <Param name="mkevt" value="1"/>
+ <Param name="mkcid" value="1"/>
+ <Param name="mkrid" value="1346-53482-19255-0"/>
+</Url>
+<SearchForm>https://www.ebay.nl/</SearchForm>
+</SearchPlugin>
diff --git a/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/ebay-pl.xml b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/ebay-pl.xml
new file mode 100644
index 0000000000..66ec476113
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/ebay-pl.xml
@@ -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/. -->
+
+<SearchPlugin xmlns="http://www.mozilla.org/2006/browser/search/">
+<ShortName>eBay</ShortName>
+<InputEncoding>UTF-8</InputEncoding>
+<Image width="68" height="68">data:image/png;base64,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</Image>
+<Url type="text/html" method="GET" template="https://www.ebay.pl/sch/">
+ <Param name="kw" value="{searchTerms}"/>
+ <Param name="toolid" value="20004"/>
+ <Param name="campid" value="5338791379"/>
+ <Param name="mkevt" value="1"/>
+ <Param name="mkcid" value="1"/>
+ <Param name="mkrid" value="4908-226936-19255-0"/>
+</Url>
+<SearchForm>https://www.ebay.pl/</SearchForm>
+</SearchPlugin>
diff --git a/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/ebay.xml b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/ebay.xml
new file mode 100644
index 0000000000..67c9251ef5
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/ebay.xml
@@ -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/. -->
+
+<SearchPlugin xmlns="http://www.mozilla.org/2006/browser/search/">
+<ShortName>eBay</ShortName>
+<InputEncoding>UTF-8</InputEncoding>
+<Image width="68" height="68">data:image/png;base64,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</Image>
+<Url type="application/x-suggestions+json" method="GET" template="https://autosug.ebay.com/autosug?sId=0&amp;fmt=osr&amp;kwd={searchTerms}"/>
+<Url type="text/html" method="GET" template="https://www.ebay.com/sch/">
+ <Param name="kw" value="{searchTerms}"/>
+ <Param name="toolid" value="20004"/>
+ <Param name="campid" value="5338791379"/>
+ <Param name="mkevt" value="1"/>
+ <Param name="mkcid" value="1"/>
+ <Param name="mkrid" value="711-53200-19255-0"/>
+</Url>
+<SearchForm>https://www.ebay.com/</SearchForm>
+</SearchPlugin>
diff --git a/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/ecosia.xml b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/ecosia.xml
new file mode 100644
index 0000000000..81d2aa4856
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/ecosia.xml
@@ -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/. -->
+
+<SearchPlugin xmlns="http://www.mozilla.org/2006/browser/search/">
+<ShortName>Ecosia</ShortName>
+<InputEncoding>UTF-8</InputEncoding>
+<Image width="16" height="16">data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAMAAABg3Am1AAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAAUVBMVEX////z8+7x8evw8Ozw8Orw8Ovw8Ovw8Ovx8evw8Ovw8Ovx8ez///vw8Ozz8+zw8Ozw8Ozw8OuSxJOXx5bf6NsAgAkHgw9vtHLj695grWP///8j4WLWAAAAEXRSTlMCGFuSutvt+2zM9I8HeidRuGeLDAwAAAABYktHRACIBR1IAAAAB3RJTUUH5gkHFxQIpRLiZQAAARFJREFUSMelltmawiAMhQNd2LpFnVHf/0XVLgqFImfmXPbLX0ISkhDtJWRVN61SbVNXUtAXCW04kNE5RlSWI1l3hHQ6YT4jfZeyHwwfygyx/Wg5Izvu7aXirJQO7fX6+RTrvCIBMa7/v/zE+t3O8LwaNv9zANv3zbt3fLIAmy26PZcB3K/5taWAXXJecSnAbnfAV2A+QnM5MCfDIIB5esQIwIJkCrjePAWA9GPkAYdF6KjGgIkaDGiozV36HgEtKQxQKGBxl+BLw2GFE5cujYunAJB48cHljT8g+ImSKwfc39oM3MjwVgk3Y7zdfwbKOSEvBf8YWfhQxMcuPthfOXfQ6jAj2HKyMNJNy/ozucT68wBb1oA/nm9/dAAAACV0RVh0ZGF0ZTpjcmVhdGUAMjAyMi0wOS0wN1QyMzoyMDowOCswMDowMDZRlR8AAAAldEVYdGRhdGU6bW9kaWZ5ADIwMjItMDktMDdUMjM6MjA6MDgrMDA6MDBHDC2jAAAAKHRFWHRkYXRlOnRpbWVzdGFtcAAyMDIyLTA5LTA3VDIzOjIwOjA4KzAwOjAwEBkMfAAAAABJRU5ErkJggg==</Image>
+<Url type="application/x-suggestions+json" method="GET" template="https://ac.ecosia.org/autocomplete">
+ <Param name="q" value="{searchTerms}"/>
+ <Param name="type" value="list"/>
+</Url>
+<Url type="text/html" method="GET" template="https://www.ecosia.org/search">
+ <Param name="tt" value="813cf1dd"/>
+ <Param name="q" value="{searchTerms}"/>
+</Url>
+<SearchForm>https://www.ecosia.org/</SearchForm>
+</SearchPlugin>
diff --git a/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/faclair-beag.xml b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/faclair-beag.xml
new file mode 100644
index 0000000000..a2fcef2fe2
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/faclair-beag.xml
@@ -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/. -->
+
+<SearchPlugin xmlns="http://www.mozilla.org/2006/browser/search/">
+<ShortName>Am Faclair Beag</ShortName>
+<InputEncoding>UTF-8</InputEncoding>
+<Image width="16" height="16">data:image/png;base64,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</Image>
+<Url type="text/html" method="GET" template="https://www.faclair.com/m" resultdomain="faclair.com">
+ <Param name="txtSearch" value="{searchTerms}" />
+</Url>
+<SearchForm>https://www.faclair.com/m</SearchForm>
+</SearchPlugin>
diff --git a/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/google-b-1-m.xml b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/google-b-1-m.xml
new file mode 100644
index 0000000000..ed4ee58ad3
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/google-b-1-m.xml
@@ -0,0 +1,17 @@
+<!-- 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/. -->
+
+<SearchPlugin xmlns="http://www.mozilla.org/2006/browser/search/">
+<ShortName>Google</ShortName>
+<InputEncoding>UTF-8</InputEncoding>
+<Image width="16" height="16">data:image/png;base64,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</Image>
+<Url type="application/x-suggestions+json" method="GET" template="https://www.google.com/complete/search?client=firefox&amp;q={searchTerms}"/>
+<Url type="text/html" method="GET" template="https://www.google.com/search">
+ <Param name="q" value="{searchTerms}"/>
+ <Param name="ie" value="utf-8"/>
+ <Param name="oe" value="utf-8"/>
+ <Param name="client" value="firefox-b-1-m"/>
+</Url>
+<SearchForm>https://www.google.com</SearchForm>
+</SearchPlugin>
diff --git a/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/google-b-m.xml b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/google-b-m.xml
new file mode 100644
index 0000000000..232bbce214
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/google-b-m.xml
@@ -0,0 +1,17 @@
+<!-- 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/. -->
+
+<SearchPlugin xmlns="http://www.mozilla.org/2006/browser/search/">
+<ShortName>Google</ShortName>
+<InputEncoding>UTF-8</InputEncoding>
+<Image width="16" height="16">data:image/png;base64,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</Image>
+<Url type="application/x-suggestions+json" method="GET" template="https://www.google.com/complete/search?client=firefox&amp;q={searchTerms}"/>
+<Url type="text/html" method="GET" template="https://www.google.com/search">
+ <Param name="q" value="{searchTerms}"/>
+ <Param name="ie" value="utf-8"/>
+ <Param name="oe" value="utf-8"/>
+ <Param name="client" value="firefox-b-m"/>
+</Url>
+<SearchForm>https://www.google.com</SearchForm>
+</SearchPlugin>
diff --git a/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/google-com-nocodes.xml b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/google-com-nocodes.xml
new file mode 100644
index 0000000000..2df8e9d277
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/google-com-nocodes.xml
@@ -0,0 +1,14 @@
+<!-- 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/. -->
+
+<SearchPlugin xmlns="http://www.mozilla.org/2006/browser/search/">
+<ShortName>Google</ShortName>
+<InputEncoding>UTF-8</InputEncoding>
+<Image width="16" height="16">data:image/png;base64,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</Image>
+<Url type="application/x-suggestions+json" method="GET" template="https://www.google.com/complete/search?client=firefox&amp;q={searchTerms}"/>
+<Url type="text/html" method="GET" template="https://www.google.com/search">
+ <Param name="q" value="{searchTerms}"/>
+</Url>
+<SearchForm>https://www.google.com</SearchForm>
+</SearchPlugin>
diff --git a/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/gulesider-mobile-NO.xml b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/gulesider-mobile-NO.xml
new file mode 100644
index 0000000000..bfd642190a
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/gulesider-mobile-NO.xml
@@ -0,0 +1,15 @@
+<!-- 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/. -->
+
+<SearchPlugin xmlns="http://www.mozilla.org/2006/browser/search/">
+<ShortName>Gule sider mobil</ShortName>
+<InputEncoding>UTF-8</InputEncoding>
+<Image width="16" height="16">data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGAAAABgCAMAAADVRocKAAAAYFBMVEX/zDMAAAD/zDP/zDP/zDP/zDP/zDP/zDP/zDP/zDP/zDP/zDP/zDP/zDP/zDP/zDP/zDMAAADhtC3MoylpVBVmUhQyKAkGBQH7yTHwwDDesix1XhdNPQ9NPg5BMwzPpikazJPsAAAAEHRSTlPhAMQV27ID8u28jWZXQCWuasw+GwAAANhJREFUaN7t2ssOgjAQheEpinfxUEDu+P5vaXTV1gVBmETJ+deTfOlqkmbEmN05gkpy2hgjZhNBrcPVyC6CYvtELlAtlhi6yRa6icCLAAECAAECBIAVAf3drasQVHXeQD8ZSP0sgmwwQIAAAQJ/CZSpW1kjqA4GJgM2c2vwUeMN2NkL51F4ZYtvtDz1ygkQIECAwDeAbQun1s4GxsWFF87iKzNsbOkTIECAwCqBakjdBvzchxQBAgQIECCwZPpHAzF00z7cuIk5QrF9on488z7/UXrE9nX+8wScyz9pRUX+FgAAAABJRU5ErkJggg==</Image>
+<Url type="text/html" method="GET" template="https://www.gulesider.no/search">
+ <Param name="what" value="all" />
+ <Param name="cmpid" value="fre_partner_fire_gssbtop"/>
+ <Param name="q" value="{searchTerms}"/>
+</Url>
+<SearchForm>http://m.gulesider.no/</SearchForm>
+</SearchPlugin>
diff --git a/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/leo_ende_de.xml b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/leo_ende_de.xml
new file mode 100644
index 0000000000..5e8eb8681f
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/leo_ende_de.xml
@@ -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/. -->
+
+<SearchPlugin xmlns="http://www.mozilla.org/2006/browser/search/">
+<ShortName>LEO Eng-Tud</ShortName>
+<InputEncoding>UTF-8</InputEncoding>
+<Image width="16" height="16">data:image/png;base64,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</Image>
+<Url type="application/x-suggestions+json" method="get" template="https://dict.leo.org/dictQuery/m-query/conf/ende/query.conf/strlist.json">
+ <Param name="q" value="{searchTerms}"/>
+ <Param name="sort" value="PLa"/>
+ <Param name="shortQuery"/>
+ <Param name="noDescription"/>
+ <Param name="noQueryURLs"/>
+</Url>
+<Url type="text/html" method="GET" template="https://dict.leo.org/englisch-deutsch/{searchTerms}" resultdomain="leo.org"/>
+<SearchForm>https://dict.leo.org</SearchForm>
+</SearchPlugin>
diff --git a/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/mapy-cz.xml b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/mapy-cz.xml
new file mode 100644
index 0000000000..6f198bf526
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/mapy-cz.xml
@@ -0,0 +1,14 @@
+<!-- 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/. -->
+
+<SearchPlugin xmlns="http://www.mozilla.org/2006/browser/search/">
+<ShortName>Mapy.cz</ShortName>
+<InputEncoding>UTF-8</InputEncoding>
+<Image width="16" height="16">data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGAAAABgCAMAAADVRocKAAAAt1BMVEUAAAAorAYorAYoqwYoqwUqqgAprAf///8srQr3/PUzsBP9/vxLuS5AtSLX8NCk3JWe2o99zWhVvjv7/frw+e7p9+Wz4qer356T1YLl9eHB57eO03x1yV9tx1ZdwUNZvz41sRX0+/Le8tnc8dbR7cq55K5oxFBGuCgwrxD4/Pfs+Ori9N3N7MbH6b2v4KOn3ZmZ2IiH0XSEz3B/zms6sxotrgzJ6sF4y2NwyFlkw0tQuzS14qlmxE6e93VUAAAABnRSTlMA8si8ZBgxEvPEAAACyklEQVRo3u2a2VbyMBCAAXXSHcoulR0FRBbZVPT9n+uHHpJpAn+hg7nwnH53bUq/kExmAieZPfe5LGggm7vPHHi4A23cPewFOt6Phv34gFbuMznQSi6TBa1kM6CZVJAKUkEqSAV7RoFnml7QCS80CCyPhVSKAFoE7+yIWQQtgjzjPFpaBAsmKICeIRKM3fOzdJtgxZAanKFjzt1bBE8MsYfnHxgXLLrghUXIwymDMIibvyMw16DydWyq3yw4/xrD403+rwjK6mAv8du5NMEnk1jKrW43OkH0KEImhjRAW4b0aQKfyUjhUpeGjyYIFMEWkB872mLTBAWmgEm1WJYaujRBVRV88xbnlSH0IXpTBaVjOA4rSsOEJsBuyovNeVTvD0gCS3RcdLhi4PhEaZAERf7xqWNGIrVdZifUSAIfy1mAXW1yWZQ6RYAl+QNGfNRtflPGpwgwiHaYNaJEpvqHIjBMPseb/UWfqUytEuPsCAKcYw8TX4TGCHriYk0QYMmfhd+np8TNJjKGY6AIqnIdWErJLTjcaojZIAnE6moftyiR3NYESTCgCIait8dSOWOcngMhz/zGM0WwUqvVl3idpQ5iniDA7s0PVzjN5up0lgKCwBAZ54nfapUOw+1IYUDftrQYB7ck7Vnt0wCkJlIgQVAQMwr/Zc6faREEE0yllzuxSy4oMlwFKqc7l2FyQR4X6RU/UNzEAkMs48U1W8t1YgHGkBMjaPOHOkkFGIBvEINlUwVWF6tlHB5RgOW+PIoV1LEcJBN4V/48HtqYDpMIWpGtYjzT8LFqUsE3FssYMIX7CQUuDw4bYzRumkvrhIKFWqguLIU5JBNsXvELXObdbFgJBR9YCKnECwZ85zYC0CDgiXriGwA6BGEa6lZfwtdrEfS3i9Ym5jN/63/TVJAKUkEqSAXXoP3QgPZjD9oPbug+eqL/8Iz24z//AHok9WmpkU9rAAAAAElFTkSuQmCC</Image>
+<Url type="text/html" method="GET" template="https://www.mapy.cz/" resultdomain="mapy.cz">
+ <Param name="q" value="{searchTerms}"/>
+ <Param name="sourceid" value="Searchmodule_3"/>
+</Url>
+<SearchForm>https://www.mapy.cz/</SearchForm>
+</SearchPlugin>
diff --git a/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/mercadolibre-ar.xml b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/mercadolibre-ar.xml
new file mode 100644
index 0000000000..f886dad815
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/mercadolibre-ar.xml
@@ -0,0 +1,14 @@
+<!-- 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/. -->
+
+<SearchPlugin xmlns="http://www.mozilla.org/2006/browser/search/">
+<ShortName>MercadoLibre Argentina</ShortName>
+<InputEncoding>ISO-8859-1</InputEncoding>
+<Image width="16" height="16">data:image/png;base64,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</Image>
+<Url type="text/html" method="GET" template="https://www.mercadolibre.com.ar/jm/search">
+ <Param name="as_word" value="{searchTerms}"/>
+ <Param name="source" value="firefox_box"/>
+</Url>
+<SearchForm>https://www.mercadolibre.com.ar/</SearchForm>
+</SearchPlugin>
diff --git a/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/mercadolibre-cl.xml b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/mercadolibre-cl.xml
new file mode 100644
index 0000000000..3881fc348f
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/mercadolibre-cl.xml
@@ -0,0 +1,14 @@
+<!-- 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/. -->
+
+<SearchPlugin xmlns="http://www.mozilla.org/2006/browser/search/">
+<ShortName>MercadoLibre Chile</ShortName>
+<InputEncoding>ISO-8859-1</InputEncoding>
+<Image width="16" height="16">data:image/png;base64,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</Image>
+<Url type="text/html" method="GET" template="https://www.mercadolibre.cl/jm/search">
+ <Param name="as_word" value="{searchTerms}"/>
+ <Param name="source" value="firefox_box"/>
+</Url>
+<SearchForm>https://www.mercadolibre.cl/</SearchForm>
+</SearchPlugin>
diff --git a/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/mercadolibre-mx.xml b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/mercadolibre-mx.xml
new file mode 100644
index 0000000000..ae628ab554
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/mercadolibre-mx.xml
@@ -0,0 +1,14 @@
+<!-- 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/. -->
+
+<SearchPlugin xmlns="http://www.mozilla.org/2006/browser/search/">
+<ShortName>MercadoLibre Mexico</ShortName>
+<InputEncoding>ISO-8859-1</InputEncoding>
+<Image width="16" height="16">data:image/png;base64,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</Image>
+<Url type="text/html" method="GET" template="https://www.mercadolibre.com.mx/jm/search">
+ <Param name="as_word" value="{searchTerms}"/>
+ <Param name="source" value="firefox_box"/>
+</Url>
+<SearchForm>https://www.mercadolibre.com.mx/</SearchForm>
+</SearchPlugin>
diff --git a/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/odpiralni.xml b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/odpiralni.xml
new file mode 100644
index 0000000000..5ad1167292
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/odpiralni.xml
@@ -0,0 +1,15 @@
+<!-- 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/. -->
+
+<SearchPlugin xmlns="http://www.mozilla.org/2006/browser/search/">
+<ShortName>Odpiralni Časi</ShortName>
+<Description>Odpiralni Časi v Sloveniji</Description>
+<InputEncoding>UTF-8</InputEncoding>
+<Image width="16" height="16">data:image/png;base64,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</Image>
+<UpdateUrl>https://www.odpiralnicasi.com/opensearch/description.xml</UpdateUrl>
+<Url type="text/html" method="GET" template="https://www.odpiralnicasi.com/spots">
+ <Param name="q" value="{searchTerms}"/>
+ <Param name="source" value="1"/>
+</Url>
+</SearchPlugin>
diff --git a/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/pazaruvaj.xml b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/pazaruvaj.xml
new file mode 100644
index 0000000000..8e79095eec
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/pazaruvaj.xml
@@ -0,0 +1,14 @@
+<!-- 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/. -->
+
+<SearchPlugin xmlns="http://www.mozilla.org/2006/browser/search/">
+<ShortName>Pazaruvaj</ShortName>
+<InputEncoding>UTF-8</InputEncoding>
+<Image width="16" height="16">data:image/png;base64,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</Image>
+<Url type="text/html" method="GET" template="https://www.pazaruvaj.com/CategorySearch.php"
+ resultdomain="pazaruvaj.com">
+ <Param name="st" value="{searchTerms}"/>
+</Url>
+<SearchForm>https://www.pazaruvaj.com/</SearchForm>
+</SearchPlugin>
diff --git a/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/prisjakt-sv-SE.xml b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/prisjakt-sv-SE.xml
new file mode 100644
index 0000000000..1027b39dad
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/prisjakt-sv-SE.xml
@@ -0,0 +1,14 @@
+<!-- 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/. -->
+
+<SearchPlugin xmlns="http://www.mozilla.org/2006/browser/search/">
+<ShortName>Prisjakt</ShortName>
+<InputEncoding>UTF-8</InputEncoding>
+<Image width="16" height="16">data:image/png;base64,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</Image>
+<Url type="application/x-suggestions+json" method="GET" template="https://www.prisjakt.nu/plugins/opensearch/suggestions.php">
+ <Param name="search" value="{searchTerms}"/>
+</Url>
+<Url type="text/html" method="GET" template="https://m.prisjakt.nu/search/{searchTerms}"/>
+<Url type="application/x-moz-tabletsearch" method="GET" template="https://www.prisjakt.nu/#rparams=ss={searchTerms}"/>
+</SearchPlugin>
diff --git a/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/qwant.xml b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/qwant.xml
new file mode 100644
index 0000000000..e5b9dfb328
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/qwant.xml
@@ -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/. -->
+
+<SearchPlugin xmlns="http://www.mozilla.org/2006/browser/search/">
+<ShortName>Qwant</ShortName>
+<InputEncoding>UTF-8</InputEncoding>
+<Image width="16" height="16">data:image/png;base64,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</Image>
+<Url type="application/x-suggestions+json" method="GET" template="https://api.qwant.com/api/suggest/">
+ <Param name="q" value="{searchTerms}"/>
+ <Param name="client" value="ff_android"/>
+</Url>
+<Url type="text/html" method="GET" template="https://www.qwant.com/">
+ <Param name="q" value="{searchTerms}"/>
+ <Param name="client" value="ff_android"/>
+</Url>
+<SearchForm>https://www.qwant.com/</SearchForm>
+</SearchPlugin> \ No newline at end of file
diff --git a/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/rakuten.xml b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/rakuten.xml
new file mode 100644
index 0000000000..1b6d0e18e8
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/rakuten.xml
@@ -0,0 +1,16 @@
+<!-- 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/. -->
+
+<SearchPlugin xmlns="http://www.mozilla.org/2006/browser/search/">
+ <ShortName>楽天市場</ShortName>
+ <Description>楽天市場 商品検索</Description>
+ <InputEncoding>EUC-JP</InputEncoding>
+ <Image height="16" width="16">data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAMAAABEpIrGAAAAIGNIUk0AAHomAACAhAAA+gAAAIDoAAB1MAAA6mAAADqYAAAXcJy6UTwAAAJMUExURQAAALA6J7IzHbIxHbMxHrIyHbMyHbIxHrIxHrIyHrIyHrMzHH8AAK8vH7IyHbIyHbQxHr8/ALMyHbIyHrIyHrQzHrIzIrIxHbMyHqoqKrIzH7MyHbkuF7YtG7MyHbMxHcwzM7IyHrIzHbIyHrIwHK80GrMxHbMzH6oqFbIyHrEzHbMyHbYwGLMyHbIyHrMzH7IyHbMxHbMxHrIyHbMyHrMxHbMyHrMzHbMxHrQwHrIwHLMyHrMyHrIxHbQyHrMyHbMwHrIxHbYzHbEyHbYkJLMxHrIxHrIxHbIxHbMxH7MxHbIxHrA0ILMyH7IxHrMxHbEyH7czHrIwH7MxHbIxHrMyHrIyHrMyHbY2JLMyHrMzH7EuGa4lEK8mEbEsGLEsF8JbS+Cro9+ooNOKfr1NPK8nErIwHM97b/////z29dmXjbEtGM13at2jmq8oE/vz8uOzq+KwqOW6s/rx8MViU7ApFfLd2rAoE60jDq0kD71OPPXl4uKzrPPf3LQ0IK0hC9WNgvHY1bIxHa4jDtCBdPLc2K4kD60jDbMxHu3Py+jBuq8pFPjr6tGEeNCAdNOJfe7Szs15bO3Qy7MxHf/+/urIwrlCMLAsF/37+vXj4Prz8v7+/spyZKwgCvPg3bU3I71OPffp6Pfp57pEMrArF60iDchrXejCvLAqFq4lD9yhmNSMgbIvGu/Tz/z4+MFZSc56bvbn5b5RQPv19PXk4rc+K7IuGrEuGrxLOc98cMpwY7AqFcRfUM99cM58b9CBdb1MO7ApFLArFrIvG0f5g2cAAABZdFJOUwANRoKwz9/dyaZ1NgIgieBtBHru2VUevpcGKLYLHN6zBcF4/j8d8koM5EXvFYOxc9CRn53Ki6hpdjo15dSaM6xU8SNgB7mGtIxix6onUeObOBlJlKCNaz0ObmhQwgAAAAFiS0dEaMts9CIAAAAHdElNRQfnCw0VEQ11qlZgAAAB1klEQVQ4y2NggANGJmYWVjZ2Dk4ubh4GTMDLxx8JB6wCjGjSgkLCkShARBRFXkw8EgNISCLkpdgjsQBpGZi8rFwkViAvCJFXUARzo6JjwCA2Dq6CD6JACcKLT0gEgaTklNQ0qAJlFZC8qhqEF5ueAQGZWdkwFRygAOGDclJzMmAgNw9miToDg4YmkoL8gsKiYqCKklKoIAsDg1YkkoKy8orKquqMjJpUqKC2DoMusoLaurTI+oaMjMYmmCuYGPTQFTS3ZGS0RsEU6DMYoFrR1t7RmZHR1Q0TNWTgR1bQ09vXPwHoyIkwN0QaMcghK4CCSZNhNkQaM5hgKJgyddp0eGibMpghK5gxc1ZGxuw5c6PgCswZLJAVzJu/YGFGxqLFS+AKLBmsULwZuXTZlIyM5StgbrDWYBC0QQ2HlauAzljdBhW0BUaWAKqCNU1rMzLWrYdEl7IdKLVDQyJ2Q0bGRmBIdm/anJGxZes2kJg9OME4QBRs37Fz566oyZGRu/fs3bf/wHagkKMTJEnZQpLcttTUg2DWodTU1MMgnzpDE62LK/ZE64bIdO745YEZywNDWtsTNe9peaHKe/ugZ14eXz1tmKyffwADNhAYxBUcYhQaFh6BJAgAIIcuyjSYZL4AAAAldEVYdGRhdGU6Y3JlYXRlADIwMjMtMTEtMTNUMjE6MTc6MTMrMDA6MDDL58yPAAAAJXRFWHRkYXRlOm1vZGlmeQAyMDIzLTExLTEzVDIxOjE3OjEzKzAwOjAwurp0MwAAACh0RVh0ZGF0ZTp0aW1lc3RhbXAAMjAyMy0xMS0xM1QyMToxNzoxMyswMDowMO2vVewAAAAASUVORK5CYII=</Image>
+ <Url method="GET" template="https://pt.afl.rakuten.co.jp/c/013ca98b.cd7c5f0c/" type="text/html">
+ <Param name="sv" value="2" />
+ <Param name="p" value="0" />
+ <Param name="sitem" value="{searchTerms}" />
+ </Url>
+ <SearchForm>https://www.rakuten.co.jp/</SearchForm>
+</SearchPlugin>
diff --git a/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/reddit.xml b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/reddit.xml
new file mode 100644
index 0000000000..4f761ba236
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/reddit.xml
@@ -0,0 +1,11 @@
+<?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/. -->
+<SearchPlugin xmlns="http://www.mozilla.org/2006/browser/search/">
+ <ShortName>Reddit</ShortName>
+ <Description>Search Reddit</Description>
+ <LongName>Reddit Search</LongName>
+ <Image width="16" height="16">data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAAD9UlEQVR4AcyYA9QkSwyF69k2j59te/Bs27Zt2/batm3btu1v+55eN6p6uPec/P/MlJJCchNTCHCj2YGsuYq0+dqTxp4MJ2VmkDZLkfifh6tNfdRXY0w5weVmD1LmHtKmticLvc8kEY3RWM2huUqn+JVmR9LmDU/mSZFCiObSnJq7eIrfaLYibR7yZJIWLYZobq2htQqr/BXmIFKmuyeUSLprzcIonzanW3a9mKdxen7Kp8wdnizWhGWSxdIhH+XZTOSOxNem1DtvkcXSyf3BFvrOP3A0PHMOXLFjsO3q3eCTO+C7x+C6PWPfhHSzusqieJuxg0FYsRyG94YGv8IX98FjJ8PwXqzD1LGxRki3WBcrH1xw5bXDq1bByyl4/gL4/SVoVwMpG4rvH7d5p4ciI2xR3OVLl8DyZXDZ9sG2bx4mAF0lm3sNi9gK5UV5gH++BkO7h7ddtQuMG8I6TBoJ1+zuEiPeCBCzPLlNtHSsA3V/jG6/cmf4/F748n5dN2futBEBFCMsmgucMQk+vasYc9+z4fWpXRTlbz0YhHsPLwbVqL0uGYnm83nKO9fB/NmQ2qIYBiyU7kbZUcEmlaIPHgNvXQ3fPAI9m8O08b5rfPsaeOg4SG9ZMCOku1GKl9ckl24LH9wMnerBvFlYoRNR3w9v1dh8T+FrGdDYaWdfzcJvL/o7md0GMlvDL8/B7GnkjDnT4feXfUMyW/knpzXeuELfXQxoLAOGx3YSf+nbho0wsi+M6k/BoFgwtAcbYVAXa0yQ7kYVg9hO1T6nbGj4m+0UZugEltqIWNkwY5LtBJbaDZg0iliIlInviBaIsOl7dF/1UV+Nie8rzJ1hNcB+hWp9SwykyEb9pWAE1BYgerFo+o/1CtkfsXarfwciIC4T6B8Jtbn2HT0Art/b+ojd3KiCz6ypbrv6StrxBCyndeVOTm7UPZDNmmK91/4bGEck1ObSVwnQZds5BjJXKjGgIyWDDHOmEq5krupnlAytKrmTOWc6fduhSsopCZ44zZ1OJ0po/n+PUMiwmw+Av9+AxQuJxLKlUOMruGEfWDCHUDT5O3lC45xSyht1aUAoWlb0SyJyq8oD/n8X6v8Ctb+DX1+Ad6+Ha/eAq3eFRr8TiiHdlPwnTykTJfVioo3+iKbKCj6iyo+cCDcf6J+M8oD3bhC3iWavoth+THFP6vMqq3x8O0yfQN6YOxO+fyKY6NjLKvkXtkS1lRMoaiaGSij/vGWrxLkXtvIuLerK/Pg0tKqsXMFnkksX+w9XQXDMQGhf06/MPX1WDnny+tJi4uJu+WX1EIO7Q3p4fUhPcAzpKaaRO8k38NOsoxPd9F9qMLrYY6gttwEAUidatlp2alsAAAAASUVORK5CYII=</Image>
+ <Url type="text/html" method="get" template="https://www.reddit.com/search/?q={searchTerms}"/>
+</SearchPlugin>
diff --git a/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/salidzinilv.xml b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/salidzinilv.xml
new file mode 100644
index 0000000000..436261f8f5
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/salidzinilv.xml
@@ -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/. -->
+
+<SearchPlugin xmlns="http://www.mozilla.org/2006/browser/search/">
+<ShortName>Salidzini.lv</ShortName>
+<InputEncoding>UTF-8</InputEncoding>
+<Image width="16" height="16">data:image/png;base64,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</Image>
+<Url type="text/html" method="GET" template="https://www.salidzini.lv/search.php">
+ <Param name="q" value="{searchTerms}"/>
+ <Param name="utm_source" value="firefox_mobile"/>
+</Url>
+<Url type="application/x-suggestions+json" method="GET" template="https://www.salidzini.lv/suggested_search.php">
+ <Param name="q" value="{searchTerms}"/>
+ <Param name="utm_source" value="firefox_mobile"/>
+</Url>
+<SearchForm>https://salidzini.lv</SearchForm>
+</SearchPlugin>
diff --git a/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/seznam-cz.xml b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/seznam-cz.xml
new file mode 100644
index 0000000000..98132cd2a5
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/seznam-cz.xml
@@ -0,0 +1,17 @@
+<!-- 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/. -->
+
+<SearchPlugin xmlns="http://www.mozilla.org/2006/browser/search/">
+<ShortName>Seznam</ShortName>
+<InputEncoding>UTF-8</InputEncoding>
+<Image width="16" height="16">data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGAAAABgCAMAAADVRocKAAAAw1BMVEUAAADMAADMAADMAADMAADMAADMAADMAAD////++vrNBQX//v7dVFTWLy/43d3zw8Pto6PsoKDhaWnTIyP99vb87+/1y8vxt7fSHR3RGBjOCwv77Oz31NTrm5vmg4PbS0vaQkLZPDzQExPqkpLnh4fibGzfX1/eWlrXNjbVKyv98/P65+f54OD32Njyu7vwsbHle3vkd3fUKCjPEBDOCQn54+P1zs7tpqbjcnLgZWXaRkb0yMjvrKzojY3XNDTniYnlfX1mR6ZxAAAAB3RSTlMA8si8ZBhlc+JuAAAAAmtJREFUaN7t2uly2jAQwHFDSHdlG3yAwZhw3+E+wpWjff+nKm3GNsM6oc1KHzLj/wPopxHWWHiknctlM6CgTDan/en+DpR1d38GyPhSBU37AUrLaVlQWlbLgNIyGiguBVIgBVLgewNj2xsBSRYwXpYNxEkVSHxAf3PtJ3zP0uUCQdutlwVetJQH5F1nZuB1Ii8F6BxfapicxQd0syLw49pcYDDFT+vyAN/CG1ksoFXDW5U5QLOEN7MZwNs/jC9GXwe2BbzZpMV4TBt4q4dDwNjJgYefNXPcIgAwgBN+lFdpNDtwjgcMk1elOwwnzgVGSCr1yOAMAKYEMAFkAnSNmnIBcOhTLxfQ99eCsS9yANqKvAmEk5cJQPsBSc/HjTwA9FWJEmIx6HCBOL8ukCbmbpUJxBWdJAIN6+DzgLhqr4bJxiBgAXFBv4CJea8+D4gzK0YiIeo+D4jzf80SidJSZwJx+V7iUu3WDIAYjRkVHpssgBpkhwuTB1Dj5+RKaHMBeip+xsuetlyAdipcCq58AHQb4+YSAFolBh6VAEURC0oAsDCsBkoAJwIWoASYk2OTXGBskP86UoHNQ/QLrFUA/i7ax3mQD+h9L3x32h2QDmyit6ixGAHIBtpOKdzA9TGAZCDfC8/2ojIMAKQC21a3EI1+JEvPBIr9SrQyi8EGSBygOqxHU7caLR1IDKBqdsMdNd0f2luI4gP6qG+/z1zs7NWpCiQGsB50/36j88rOylyTRWEBnWZj7mGt/PLqtsisuUDRXNbtntscB/B/fa9PyymQAimQAvJSfmlA/bWHHCgtp/rqifrLM8qv//wGWy8ZH4yviOAAAAAASUVORK5CYII=</Image>
+<Url type="application/x-suggestions+json" method="GET" template="https://suggest.seznam.cz/fulltext_ff">
+ <Param name="phrase" value="{searchTerms}"/>
+</Url>
+<Url type="text/html" method="GET" template="https://search.seznam.cz/">
+ <Param name="q" value="{searchTerms}"/>
+ <Param name="sourceid" value="SearchBox"/>
+</Url>
+<SearchForm>http://search.seznam.cz/</SearchForm>
+</SearchPlugin>
diff --git a/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/vatera.xml b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/vatera.xml
new file mode 100644
index 0000000000..8e0929c0b4
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/vatera.xml
@@ -0,0 +1,17 @@
+<!-- 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/. -->
+
+<SearchPlugin xmlns="http://www.mozilla.org/2006/browser/search/">
+ <ShortName>Vatera.hu</ShortName>
+ <Language>hu</Language>
+ <OutputEncoding>ISO-8859-2</OutputEncoding>
+ <InputEncoding>ISO-8859-2</InputEncoding>
+ <Image width="16" height="16">data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGAAAABgCAMAAADVRocKAAAA3lBMVEUAAAD5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn/WgD59/b/WwH/XAP/XwD/XAD/Xgb59vX/YAD59fP7zrb+div59/X66d/+aRf/ZRL9kVX+dy3+cyj+cCL/Ygz638/7y7D8oG7/YAj58+/57uf65tr9l2H57+r64tX62sj7xqn8tY/8s4v8r4X8rIH8qHr9jE79iUj+gT3+fTb+ejL+bBz62MX707370br7w6X7waD9g0D58e366+P7t5L8pXX9nWj9lV39hUT63Mv61cD7vZv7u5j9m2X+fzgxJ++FAAAACnRSTlMAwwbS+W9sG8/zKHP4TgAABJlJREFUaN61mutS2zAQhR3KpV1Lli0ncaAJt1ASINxyKVBKaaFAef8XalrobLLr+Ezx+Pxj8PJZK8mf5SEIgqXV2jJVkOXa6lIwzdp7qizv16b3/44qzLulYJUqzWpQo0pTC5ap0iwHVHFmAUYGl+O64hEABLhIA+oihJJf53MBhlrDTrvJabc7v/p4DIZ2xk1RNyCjAZ4uXermk55CgKHWuiiL0/v8EXzqxN1kJlHXTTyBeHpyiUg8oEwDpoRfaRTOxtrkgiDioxNVcXebfA7A01Ec2nmAOyWPOvQ5ngdEbkREuSP4pq/9Cjv0RdxVGPHMqWX6MU3mr423tlGPeqqv0cUCgKFrZ+d7FLrbQoChfsfJUU/qCwH7G6JHSXoOpqBhw7nYyH3nvy8BdK56tL5PpgjwXVRYG15RJgA8Y7dOraPrAoCh+kR1qHPDFQqwvaV6dFe4hh4iawXgBxU9Tb/KG4o/f+MCDTiVuyyMd8gvBGR04qwtKFAZqRva/FQwAk+HCRry/7Y0EDVjNWlNnjQ1xwM5YBt/EVcHouRMbUzLy06ZbKiXdQsALq21YuOciZKCjRmlH0lEAvbaTnTVjb0gLH60WPdEXgBk0a7qUfdw0STcqQ5tHABARjtWraNjASh4vA+JCIygv6l6dC9qCgR1TF4BJKGnFLh1MDcEVqy80m79zAHg+8qVgqEbqYKEZSkAqLN5UsjoasrWsgQAFqfaPVoFTssSAvLFOd3/XqtgDGTJALw/e6Qvu0hUh1iWClAsTsfPYL7sxEWFsmQAfkaGcYMB7KakQJYCAJ/yu6LU/LkIm4MBQJyuvTdf7OkWu08DWJyRFVK4lMXnQJYCAMV5Rl6cCoAsBQCK89nM3p6n65h/q2WpAUCcUdwVj7G7NALbXQCAOO2LFPg0tCk7JGQpAVicQ2KCoR15KhCyhOdkFifLcBawC2SpAEicNnKPZHiETbkKWHsAoMWpe+zz5yiDAC3O/FXi6Uw96MQqUwAszjA+Iv9KN3qfjAi1CJ9Oe2T+7fRuHAFZKgAWp+v0ybzQj9UbXXIBAHoIj+qP2AZlL0a6FypItCw1AIvzVQqGDsSvLMsSAIA4J3+lYOgJyhIDyLM41VuJnp7mHhoBECcvFVaBlCUGYHGOXj9/SFlaLUsMyPR7yd9PI7zJpSwxQItTP3DqeSroUU5wi8yz0+cLTw0rO8SyBAAszo19VgWUJQY8yNOUjR/pZuLQyRIDWJz6bz2EamYeyb9tDvK6UT/J6dvbAPnzeTRMwclSA/AHOU78vB6HokMD8hiAxMnTHFq9+wwGAHFy5M8Jf1rFAHyW14nSEzKEAVicHCHLwxIAeeLUidzYlwLsr6seCVny16S3tIjFyVFHn6wEgD/VcvThrQxAvEFogDh+QoDOvSuchAZlpQCZfIuTnwD6JUfg6WdXA1iWP2QBAOCvx+rsbd4M4I8eic1Pwq8TZQAH3dQuGMHL2yoCwAw2bJwXG41aZQCc1kMjL1eH/M5eAgAayCkBMAtDpQHlU/U/DXyo/t8eVqjSrFT/ryfBWoWEd2vBNEsrFc1DbWV6/78B75KyRqivJp0AAAAASUVORK5CYII=</Image>
+ <Url type="text/html" method="GET" template="https://www.vatera.hu/listings/index.php">
+ <Param name="c" value="0" />
+ <Param name="td" value="on" />
+ <Param name="q" value="{searchTerms}" />
+ </Url>
+ <SearchForm>http://m.vatera.hu/</SearchForm>
+</SearchPlugin>
diff --git a/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-NN.xml b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-NN.xml
new file mode 100644
index 0000000000..f876b15112
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-NN.xml
@@ -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/. -->
+
+<SearchPlugin xmlns="http://www.mozilla.org/2006/browser/search/">
+<ShortName>Wikipedia (nn)</ShortName>
+<InputEncoding>UTF-8</InputEncoding>
+<Image width="16" height="16">data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGAAAABgCAMAAADVRocKAAAA51BMVEUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD////7+/vl5eWxsbH9/f3Ly8tzc3P39/fe3t5cXFzz8/Pt7e3i4uI3NzcaGhoHBwcFBQX5+fnIyMhTU1MXFxcMDAzx8fHX19fFxcXCwsK7u7u1tbWenp6WlpZ8fHxXV1ctLS319fXn5+fV1dWsrKySkpJnZ2cgICDv7+/p6eng4ODQ0NC9vb24uLikpKSPj4+JiYmCgoJiYmJCQkI7OzsyMjIpKSkQEBCoqKigoKCdnZ14eHhubm5PT09LS0tERETk5OTb29unp6c0NDQkJCQOGD7BAAAAB3RSTlMA8si8ZBhlc+JuAAAAAw1JREFUaN7tmtluIjEQRYEhUxd6YYew7xAggRAgCQmB7Ov8//eM3Zg2nXkJvUjz4POAVEbyQXaVy0gOMaKRMAVAOBINcY5+UWD8OmKCIOaXhlDoNwVKNBShQImEwhQo4RAFjBIogRIogRIogRIoQWCCYXqaHJVaWrtl1IfpYp3GiczFqLHQ5kY9m0l0qVM8Txrs+8ZomkhSKpbOzlraolSP15o/EtxoU9gk2iZVujM7HnVe6eUhKaL4aYrWXWMXfd7+dIlScWxpbsjibQiLPm255sH5jYjKOoCEecge5LcTxqokuItZv5F2DID0iR21ALwctslfunNCurKEBRJkgBTZdIDOoVl0CU7FjgsZHpsi+gNoJGlisDlUkC+C8SQHejzOiqCLgXRTNYazw+vg8tsaHZ+DMd7ZlyR5Qix/uOAEgGOhlzy+EPLMMUmyOHVTyQ0wDBlXB2Dw1FzreCZJGfhyIyiDs/qWSEkiarNPxxaX3J1FWcCRLJXidtFW7MO5lmV3AhMMPS8HHsH4oBJmtEcHF+ROUEgD2E/AiVXO98AtSaoJmC4F1AUjXZAD97Bo0R491ApuBRNdVq/FGhz9hPaI48p9w1mI6rVpi1qQ9FmRuRe8iTPaJgfOi6NaTr20zDoYJUfOM2aOHM15EYwBOKbQwHm14wcY5FYgTzi5CHewMPZytO9aIHuj3MY53sF5s3M0S94EFV5bdiLeshQdgdGwc9T0IJC1VROHs4EHSgHY1XKflaFXQQ6y2MpIVIiSYDStgRLOvN/sDDCSImmv7cxaWVuu5z0LxJKU+Y1M9LE4GHOrsWnkXUDx3a5mRR8zRXFsisj5IeiBc0cmPkRxZMBY0BIGeRLIYmJ8smnLDmVuiL5ngWxksUd5JhVqYEzxTv4I1tiSc9Y38OSTgOZwnki0GYhe55Pg1VqjCUnORLf2SWAVb5fIeYPRJ/4JnoFa1THSATTyT3BcQ++f+8DKRwGN299Hltr/+zdWCZRACZRACZSAlEAJDifwRwPBP3uIUqBEg356EvzjmcCf//wFVbAkwfl+5CMAAAAASUVORK5CYII=</Image>
+<Url type="application/x-suggestions+json" method="GET" template="https://nn.wikipedia.org/w/api.php">
+ <Param name="action" value="opensearch"/>
+ <Param name="search" value="{searchTerms}"/>
+</Url>
+<Url type="text/html" method="GET" template="https://nn.wikipedia.org/wiki/Spesial:Søk">
+ <Param name="search" value="{searchTerms}"/>
+ <Param name="sourceid" value="Mozilla-search"/>
+</Url>
+<SearchForm>https://nn.wikipedia.org/wiki/Spesial:Søk</SearchForm>
+</SearchPlugin>
diff --git a/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-NO.xml b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-NO.xml
new file mode 100644
index 0000000000..75bb1768f6
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-NO.xml
@@ -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/. -->
+
+<SearchPlugin xmlns="http://www.mozilla.org/2006/browser/search/">
+<ShortName>Wikipedia (no)</ShortName>
+<InputEncoding>UTF-8</InputEncoding>
+<Image width="16" height="16">data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGAAAABgCAMAAADVRocKAAAA51BMVEUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD////7+/vl5eWxsbH9/f3Ly8tzc3P39/fe3t5cXFzz8/Pt7e3i4uI3NzcaGhoHBwcFBQX5+fnIyMhTU1MXFxcMDAzx8fHX19fFxcXCwsK7u7u1tbWenp6WlpZ8fHxXV1ctLS319fXn5+fV1dWsrKySkpJnZ2cgICDv7+/p6eng4ODQ0NC9vb24uLikpKSPj4+JiYmCgoJiYmJCQkI7OzsyMjIpKSkQEBCoqKigoKCdnZ14eHhubm5PT09LS0tERETk5OTb29unp6c0NDQkJCQOGD7BAAAAB3RSTlMA8si8ZBhlc+JuAAAAAw1JREFUaN7tmtluIjEQRYEhUxd6YYew7xAggRAgCQmB7Ov8//eM3Zg2nXkJvUjz4POAVEbyQXaVy0gOMaKRMAVAOBINcY5+UWD8OmKCIOaXhlDoNwVKNBShQImEwhQo4RAFjBIogRIogRIogRIoQWCCYXqaHJVaWrtl1IfpYp3GiczFqLHQ5kY9m0l0qVM8Txrs+8ZomkhSKpbOzlraolSP15o/EtxoU9gk2iZVujM7HnVe6eUhKaL4aYrWXWMXfd7+dIlScWxpbsjibQiLPm255sH5jYjKOoCEecge5LcTxqokuItZv5F2DID0iR21ALwctslfunNCurKEBRJkgBTZdIDOoVl0CU7FjgsZHpsi+gNoJGlisDlUkC+C8SQHejzOiqCLgXRTNYazw+vg8tsaHZ+DMd7ZlyR5Qix/uOAEgGOhlzy+EPLMMUmyOHVTyQ0wDBlXB2Dw1FzreCZJGfhyIyiDs/qWSEkiarNPxxaX3J1FWcCRLJXidtFW7MO5lmV3AhMMPS8HHsH4oBJmtEcHF+ROUEgD2E/AiVXO98AtSaoJmC4F1AUjXZAD97Bo0R491ApuBRNdVq/FGhz9hPaI48p9w1mI6rVpi1qQ9FmRuRe8iTPaJgfOi6NaTr20zDoYJUfOM2aOHM15EYwBOKbQwHm14wcY5FYgTzi5CHewMPZytO9aIHuj3MY53sF5s3M0S94EFV5bdiLeshQdgdGwc9T0IJC1VROHs4EHSgHY1XKflaFXQQ6y2MpIVIiSYDStgRLOvN/sDDCSImmv7cxaWVuu5z0LxJKU+Y1M9LE4GHOrsWnkXUDx3a5mRR8zRXFsisj5IeiBc0cmPkRxZMBY0BIGeRLIYmJ8smnLDmVuiL5ngWxksUd5JhVqYEzxTv4I1tiSc9Y38OSTgOZwnki0GYhe55Pg1VqjCUnORLf2SWAVb5fIeYPRJ/4JnoFa1THSATTyT3BcQ++f+8DKRwGN299Hltr/+zdWCZRACZRACZSAlEAJDifwRwPBP3uIUqBEg356EvzjmcCf//wFVbAkwfl+5CMAAAAASUVORK5CYII=</Image>
+<Url type="application/x-suggestions+json" method="GET" template="https://no.wikipedia.org/w/api.php">
+ <Param name="action" value="opensearch"/>
+ <Param name="search" value="{searchTerms}"/>
+</Url>
+<Url type="text/html" method="GET" template="https://no.wikipedia.org/wiki/Spesial:Søk">
+ <Param name="search" value="{searchTerms}"/>
+ <Param name="sourceid" value="Mozilla-search"/>
+</Url>
+<SearchForm>https://no.wikipedia.org/wiki/Spesial:Søk</SearchForm>
+</SearchPlugin>
diff --git a/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-an.xml b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-an.xml
new file mode 100644
index 0000000000..dbaddfcb5c
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-an.xml
@@ -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/. -->
+
+<SearchPlugin xmlns="http://www.mozilla.org/2006/browser/search/">
+<ShortName>Biquipedia (an)</ShortName>
+<InputEncoding>UTF-8</InputEncoding>
+<Image width="16" height="16">data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGAAAABgCAMAAADVRocKAAAA51BMVEUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD////7+/vl5eWxsbH9/f3Ly8tzc3P39/fe3t5cXFzz8/Pt7e3i4uI3NzcaGhoHBwcFBQX5+fnIyMhTU1MXFxcMDAzx8fHX19fFxcXCwsK7u7u1tbWenp6WlpZ8fHxXV1ctLS319fXn5+fV1dWsrKySkpJnZ2cgICDv7+/p6eng4ODQ0NC9vb24uLikpKSPj4+JiYmCgoJiYmJCQkI7OzsyMjIpKSkQEBCoqKigoKCdnZ14eHhubm5PT09LS0tERETk5OTb29unp6c0NDQkJCQOGD7BAAAAB3RSTlMA8si8ZBhlc+JuAAAAAw1JREFUaN7tmtluIjEQRYEhUxd6YYew7xAggRAgCQmB7Ov8//eM3Zg2nXkJvUjz4POAVEbyQXaVy0gOMaKRMAVAOBINcY5+UWD8OmKCIOaXhlDoNwVKNBShQImEwhQo4RAFjBIogRIogRIogRIoQWCCYXqaHJVaWrtl1IfpYp3GiczFqLHQ5kY9m0l0qVM8Txrs+8ZomkhSKpbOzlraolSP15o/EtxoU9gk2iZVujM7HnVe6eUhKaL4aYrWXWMXfd7+dIlScWxpbsjibQiLPm255sH5jYjKOoCEecge5LcTxqokuItZv5F2DID0iR21ALwctslfunNCurKEBRJkgBTZdIDOoVl0CU7FjgsZHpsi+gNoJGlisDlUkC+C8SQHejzOiqCLgXRTNYazw+vg8tsaHZ+DMd7ZlyR5Qix/uOAEgGOhlzy+EPLMMUmyOHVTyQ0wDBlXB2Dw1FzreCZJGfhyIyiDs/qWSEkiarNPxxaX3J1FWcCRLJXidtFW7MO5lmV3AhMMPS8HHsH4oBJmtEcHF+ROUEgD2E/AiVXO98AtSaoJmC4F1AUjXZAD97Bo0R491ApuBRNdVq/FGhz9hPaI48p9w1mI6rVpi1qQ9FmRuRe8iTPaJgfOi6NaTr20zDoYJUfOM2aOHM15EYwBOKbQwHm14wcY5FYgTzi5CHewMPZytO9aIHuj3MY53sF5s3M0S94EFV5bdiLeshQdgdGwc9T0IJC1VROHs4EHSgHY1XKflaFXQQ6y2MpIVIiSYDStgRLOvN/sDDCSImmv7cxaWVuu5z0LxJKU+Y1M9LE4GHOrsWnkXUDx3a5mRR8zRXFsisj5IeiBc0cmPkRxZMBY0BIGeRLIYmJ8smnLDmVuiL5ngWxksUd5JhVqYEzxTv4I1tiSc9Y38OSTgOZwnki0GYhe55Pg1VqjCUnORLf2SWAVb5fIeYPRJ/4JnoFa1THSATTyT3BcQ++f+8DKRwGN299Hltr/+zdWCZRACZRACZSAlEAJDifwRwPBP3uIUqBEg356EvzjmcCf//wFVbAkwfl+5CMAAAAASUVORK5CYII=</Image>
+<Url type="application/x-suggestions+json" method="GET" template="https://an.wikipedia.org/w/api.php">
+ <Param name="action" value="opensearch"/>
+ <Param name="search" value="{searchTerms}"/>
+</Url>
+<Url type="text/html" method="GET" template="https://an.wikipedia.org/wiki/Especial:Mirar">
+ <Param name="search" value="{searchTerms}"/>
+ <Param name="sourceid" value="Mozilla-search"/>
+</Url>
+<SearchForm>https://an.wikipedia.org/wiki/Especial:Mirar</SearchForm>
+</SearchPlugin>
diff --git a/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-ar.xml b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-ar.xml
new file mode 100644
index 0000000000..78c63e61c9
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-ar.xml
@@ -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/. -->
+
+<SearchPlugin xmlns="http://www.mozilla.org/2006/browser/search/">
+<ShortName>ويكيبيديا (ar)</ShortName>
+<InputEncoding>UTF-8</InputEncoding>
+<Image width="16" height="16">data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGAAAABgCAMAAADVRocKAAAA51BMVEUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD////7+/vl5eWxsbH9/f3Ly8tzc3P39/fe3t5cXFzz8/Pt7e3i4uI3NzcaGhoHBwcFBQX5+fnIyMhTU1MXFxcMDAzx8fHX19fFxcXCwsK7u7u1tbWenp6WlpZ8fHxXV1ctLS319fXn5+fV1dWsrKySkpJnZ2cgICDv7+/p6eng4ODQ0NC9vb24uLikpKSPj4+JiYmCgoJiYmJCQkI7OzsyMjIpKSkQEBCoqKigoKCdnZ14eHhubm5PT09LS0tERETk5OTb29unp6c0NDQkJCQOGD7BAAAAB3RSTlMA8si8ZBhlc+JuAAAAAw1JREFUaN7tmtluIjEQRYEhUxd6YYew7xAggRAgCQmB7Ov8//eM3Zg2nXkJvUjz4POAVEbyQXaVy0gOMaKRMAVAOBINcY5+UWD8OmKCIOaXhlDoNwVKNBShQImEwhQo4RAFjBIogRIogRIogRIoQWCCYXqaHJVaWrtl1IfpYp3GiczFqLHQ5kY9m0l0qVM8Txrs+8ZomkhSKpbOzlraolSP15o/EtxoU9gk2iZVujM7HnVe6eUhKaL4aYrWXWMXfd7+dIlScWxpbsjibQiLPm255sH5jYjKOoCEecge5LcTxqokuItZv5F2DID0iR21ALwctslfunNCurKEBRJkgBTZdIDOoVl0CU7FjgsZHpsi+gNoJGlisDlUkC+C8SQHejzOiqCLgXRTNYazw+vg8tsaHZ+DMd7ZlyR5Qix/uOAEgGOhlzy+EPLMMUmyOHVTyQ0wDBlXB2Dw1FzreCZJGfhyIyiDs/qWSEkiarNPxxaX3J1FWcCRLJXidtFW7MO5lmV3AhMMPS8HHsH4oBJmtEcHF+ROUEgD2E/AiVXO98AtSaoJmC4F1AUjXZAD97Bo0R491ApuBRNdVq/FGhz9hPaI48p9w1mI6rVpi1qQ9FmRuRe8iTPaJgfOi6NaTr20zDoYJUfOM2aOHM15EYwBOKbQwHm14wcY5FYgTzi5CHewMPZytO9aIHuj3MY53sF5s3M0S94EFV5bdiLeshQdgdGwc9T0IJC1VROHs4EHSgHY1XKflaFXQQ6y2MpIVIiSYDStgRLOvN/sDDCSImmv7cxaWVuu5z0LxJKU+Y1M9LE4GHOrsWnkXUDx3a5mRR8zRXFsisj5IeiBc0cmPkRxZMBY0BIGeRLIYmJ8smnLDmVuiL5ngWxksUd5JhVqYEzxTv4I1tiSc9Y38OSTgOZwnki0GYhe55Pg1VqjCUnORLf2SWAVb5fIeYPRJ/4JnoFa1THSATTyT3BcQ++f+8DKRwGN299Hltr/+zdWCZRACZRACZSAlEAJDifwRwPBP3uIUqBEg356EvzjmcCf//wFVbAkwfl+5CMAAAAASUVORK5CYII=</Image>
+<Url type="application/x-suggestions+json" method="GET" template="https://ar.wikipedia.org/w/api.php">
+ <Param name="action" value="opensearch"/>
+ <Param name="search" value="{searchTerms}"/>
+</Url>
+<Url type="text/html" method="GET" template="https://ar.wikipedia.org/wiki/خاص:بحث">
+ <Param name="search" value="{searchTerms}"/>
+ <Param name="sourceid" value="Mozilla-search"/>
+</Url>
+<SearchForm>https://ar.wikipedia.org/wiki/خاص:بحث</SearchForm>
+</SearchPlugin>
diff --git a/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-as.xml b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-as.xml
new file mode 100644
index 0000000000..914e513f0e
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-as.xml
@@ -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/. -->
+
+<SearchPlugin xmlns="http://www.mozilla.org/2006/browser/search/">
+<ShortName>অসমীয়া ৱিকিপিডিয়া (as)</ShortName>
+<InputEncoding>UTF-8</InputEncoding>
+<Image width="16" height="16">data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGAAAABgCAMAAADVRocKAAAA51BMVEUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD////7+/vl5eWxsbH9/f3Ly8tzc3P39/fe3t5cXFzz8/Pt7e3i4uI3NzcaGhoHBwcFBQX5+fnIyMhTU1MXFxcMDAzx8fHX19fFxcXCwsK7u7u1tbWenp6WlpZ8fHxXV1ctLS319fXn5+fV1dWsrKySkpJnZ2cgICDv7+/p6eng4ODQ0NC9vb24uLikpKSPj4+JiYmCgoJiYmJCQkI7OzsyMjIpKSkQEBCoqKigoKCdnZ14eHhubm5PT09LS0tERETk5OTb29unp6c0NDQkJCQOGD7BAAAAB3RSTlMA8si8ZBhlc+JuAAAAAw1JREFUaN7tmtluIjEQRYEhUxd6YYew7xAggRAgCQmB7Ov8//eM3Zg2nXkJvUjz4POAVEbyQXaVy0gOMaKRMAVAOBINcY5+UWD8OmKCIOaXhlDoNwVKNBShQImEwhQo4RAFjBIogRIogRIogRIoQWCCYXqaHJVaWrtl1IfpYp3GiczFqLHQ5kY9m0l0qVM8Txrs+8ZomkhSKpbOzlraolSP15o/EtxoU9gk2iZVujM7HnVe6eUhKaL4aYrWXWMXfd7+dIlScWxpbsjibQiLPm255sH5jYjKOoCEecge5LcTxqokuItZv5F2DID0iR21ALwctslfunNCurKEBRJkgBTZdIDOoVl0CU7FjgsZHpsi+gNoJGlisDlUkC+C8SQHejzOiqCLgXRTNYazw+vg8tsaHZ+DMd7ZlyR5Qix/uOAEgGOhlzy+EPLMMUmyOHVTyQ0wDBlXB2Dw1FzreCZJGfhyIyiDs/qWSEkiarNPxxaX3J1FWcCRLJXidtFW7MO5lmV3AhMMPS8HHsH4oBJmtEcHF+ROUEgD2E/AiVXO98AtSaoJmC4F1AUjXZAD97Bo0R491ApuBRNdVq/FGhz9hPaI48p9w1mI6rVpi1qQ9FmRuRe8iTPaJgfOi6NaTr20zDoYJUfOM2aOHM15EYwBOKbQwHm14wcY5FYgTzi5CHewMPZytO9aIHuj3MY53sF5s3M0S94EFV5bdiLeshQdgdGwc9T0IJC1VROHs4EHSgHY1XKflaFXQQ6y2MpIVIiSYDStgRLOvN/sDDCSImmv7cxaWVuu5z0LxJKU+Y1M9LE4GHOrsWnkXUDx3a5mRR8zRXFsisj5IeiBc0cmPkRxZMBY0BIGeRLIYmJ8smnLDmVuiL5ngWxksUd5JhVqYEzxTv4I1tiSc9Y38OSTgOZwnki0GYhe55Pg1VqjCUnORLf2SWAVb5fIeYPRJ/4JnoFa1THSATTyT3BcQ++f+8DKRwGN299Hltr/+zdWCZRACZRACZSAlEAJDifwRwPBP3uIUqBEg356EvzjmcCf//wFVbAkwfl+5CMAAAAASUVORK5CYII=</Image>
+<Url type="application/x-suggestions+json" method="GET" template="https://as.wikipedia.org/w/api.php">
+ <Param name="action" value="opensearch"/>
+ <Param name="search" value="{searchTerms}"/>
+</Url>
+<Url type="text/html" method="GET" template="https://as.wikipedia.org/wiki/বিশেষ:সন্ধান">
+ <Param name="search" value="{searchTerms}"/>
+ <Param name="sourceid" value="Mozilla-search"/>
+</Url>
+<SearchForm>https://as.wikipedia.org/wiki/বিশেষ:সন্ধান</SearchForm>
+</SearchPlugin>
diff --git a/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-ast.xml b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-ast.xml
new file mode 100644
index 0000000000..0a32de3219
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-ast.xml
@@ -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/. -->
+
+<SearchPlugin xmlns="http://www.mozilla.org/2006/browser/search/">
+<ShortName>Wikipedia (ast)</ShortName>
+<InputEncoding>UTF-8</InputEncoding>
+<Image width="16" height="16">data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGAAAABgCAMAAADVRocKAAAA51BMVEUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD////7+/vl5eWxsbH9/f3Ly8tzc3P39/fe3t5cXFzz8/Pt7e3i4uI3NzcaGhoHBwcFBQX5+fnIyMhTU1MXFxcMDAzx8fHX19fFxcXCwsK7u7u1tbWenp6WlpZ8fHxXV1ctLS319fXn5+fV1dWsrKySkpJnZ2cgICDv7+/p6eng4ODQ0NC9vb24uLikpKSPj4+JiYmCgoJiYmJCQkI7OzsyMjIpKSkQEBCoqKigoKCdnZ14eHhubm5PT09LS0tERETk5OTb29unp6c0NDQkJCQOGD7BAAAAB3RSTlMA8si8ZBhlc+JuAAAAAw1JREFUaN7tmtluIjEQRYEhUxd6YYew7xAggRAgCQmB7Ov8//eM3Zg2nXkJvUjz4POAVEbyQXaVy0gOMaKRMAVAOBINcY5+UWD8OmKCIOaXhlDoNwVKNBShQImEwhQo4RAFjBIogRIogRIogRIoQWCCYXqaHJVaWrtl1IfpYp3GiczFqLHQ5kY9m0l0qVM8Txrs+8ZomkhSKpbOzlraolSP15o/EtxoU9gk2iZVujM7HnVe6eUhKaL4aYrWXWMXfd7+dIlScWxpbsjibQiLPm255sH5jYjKOoCEecge5LcTxqokuItZv5F2DID0iR21ALwctslfunNCurKEBRJkgBTZdIDOoVl0CU7FjgsZHpsi+gNoJGlisDlUkC+C8SQHejzOiqCLgXRTNYazw+vg8tsaHZ+DMd7ZlyR5Qix/uOAEgGOhlzy+EPLMMUmyOHVTyQ0wDBlXB2Dw1FzreCZJGfhyIyiDs/qWSEkiarNPxxaX3J1FWcCRLJXidtFW7MO5lmV3AhMMPS8HHsH4oBJmtEcHF+ROUEgD2E/AiVXO98AtSaoJmC4F1AUjXZAD97Bo0R491ApuBRNdVq/FGhz9hPaI48p9w1mI6rVpi1qQ9FmRuRe8iTPaJgfOi6NaTr20zDoYJUfOM2aOHM15EYwBOKbQwHm14wcY5FYgTzi5CHewMPZytO9aIHuj3MY53sF5s3M0S94EFV5bdiLeshQdgdGwc9T0IJC1VROHs4EHSgHY1XKflaFXQQ6y2MpIVIiSYDStgRLOvN/sDDCSImmv7cxaWVuu5z0LxJKU+Y1M9LE4GHOrsWnkXUDx3a5mRR8zRXFsisj5IeiBc0cmPkRxZMBY0BIGeRLIYmJ8smnLDmVuiL5ngWxksUd5JhVqYEzxTv4I1tiSc9Y38OSTgOZwnki0GYhe55Pg1VqjCUnORLf2SWAVb5fIeYPRJ/4JnoFa1THSATTyT3BcQ++f+8DKRwGN299Hltr/+zdWCZRACZRACZSAlEAJDifwRwPBP3uIUqBEg356EvzjmcCf//wFVbAkwfl+5CMAAAAASUVORK5CYII=</Image>
+<Url type="application/x-suggestions+json" method="GET" template="https://ast.wikipedia.org/w/api.php">
+ <Param name="action" value="opensearch"/>
+ <Param name="search" value="{searchTerms}"/>
+</Url>
+<Url type="text/html" method="GET" template="https://ast.wikipedia.org/wiki/Especial:Gueta">
+ <Param name="search" value="{searchTerms}"/>
+ <Param name="sourceid" value="Mozilla-search"/>
+</Url>
+<SearchForm>https://ast.wikipedia.org/wiki/Especial:Gueta</SearchForm>
+</SearchPlugin>
diff --git a/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-az.xml b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-az.xml
new file mode 100644
index 0000000000..dd87a40cc6
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-az.xml
@@ -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/. -->
+
+<SearchPlugin xmlns="http://www.mozilla.org/2006/browser/search/">
+<ShortName>Vikipediya (az)</ShortName>
+<InputEncoding>UTF-8</InputEncoding>
+<Image width="16" height="16">data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGAAAABgCAMAAADVRocKAAAA51BMVEUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD////7+/vl5eWxsbH9/f3Ly8tzc3P39/fe3t5cXFzz8/Pt7e3i4uI3NzcaGhoHBwcFBQX5+fnIyMhTU1MXFxcMDAzx8fHX19fFxcXCwsK7u7u1tbWenp6WlpZ8fHxXV1ctLS319fXn5+fV1dWsrKySkpJnZ2cgICDv7+/p6eng4ODQ0NC9vb24uLikpKSPj4+JiYmCgoJiYmJCQkI7OzsyMjIpKSkQEBCoqKigoKCdnZ14eHhubm5PT09LS0tERETk5OTb29unp6c0NDQkJCQOGD7BAAAAB3RSTlMA8si8ZBhlc+JuAAAAAw1JREFUaN7tmtluIjEQRYEhUxd6YYew7xAggRAgCQmB7Ov8//eM3Zg2nXkJvUjz4POAVEbyQXaVy0gOMaKRMAVAOBINcY5+UWD8OmKCIOaXhlDoNwVKNBShQImEwhQo4RAFjBIogRIogRIogRIoQWCCYXqaHJVaWrtl1IfpYp3GiczFqLHQ5kY9m0l0qVM8Txrs+8ZomkhSKpbOzlraolSP15o/EtxoU9gk2iZVujM7HnVe6eUhKaL4aYrWXWMXfd7+dIlScWxpbsjibQiLPm255sH5jYjKOoCEecge5LcTxqokuItZv5F2DID0iR21ALwctslfunNCurKEBRJkgBTZdIDOoVl0CU7FjgsZHpsi+gNoJGlisDlUkC+C8SQHejzOiqCLgXRTNYazw+vg8tsaHZ+DMd7ZlyR5Qix/uOAEgGOhlzy+EPLMMUmyOHVTyQ0wDBlXB2Dw1FzreCZJGfhyIyiDs/qWSEkiarNPxxaX3J1FWcCRLJXidtFW7MO5lmV3AhMMPS8HHsH4oBJmtEcHF+ROUEgD2E/AiVXO98AtSaoJmC4F1AUjXZAD97Bo0R491ApuBRNdVq/FGhz9hPaI48p9w1mI6rVpi1qQ9FmRuRe8iTPaJgfOi6NaTr20zDoYJUfOM2aOHM15EYwBOKbQwHm14wcY5FYgTzi5CHewMPZytO9aIHuj3MY53sF5s3M0S94EFV5bdiLeshQdgdGwc9T0IJC1VROHs4EHSgHY1XKflaFXQQ6y2MpIVIiSYDStgRLOvN/sDDCSImmv7cxaWVuu5z0LxJKU+Y1M9LE4GHOrsWnkXUDx3a5mRR8zRXFsisj5IeiBc0cmPkRxZMBY0BIGeRLIYmJ8smnLDmVuiL5ngWxksUd5JhVqYEzxTv4I1tiSc9Y38OSTgOZwnki0GYhe55Pg1VqjCUnORLf2SWAVb5fIeYPRJ/4JnoFa1THSATTyT3BcQ++f+8DKRwGN299Hltr/+zdWCZRACZRACZSAlEAJDifwRwPBP3uIUqBEg356EvzjmcCf//wFVbAkwfl+5CMAAAAASUVORK5CYII=</Image>
+<Url type="application/x-suggestions+json" method="GET" template="https://az.wikipedia.org/w/api.php">
+ <Param name="action" value="opensearch"/>
+ <Param name="search" value="{searchTerms}"/>
+</Url>
+<Url type="text/html" method="GET" template="https://az.wikipedia.org/wiki/Xüsusi:Axtar">
+ <Param name="search" value="{searchTerms}"/>
+ <Param name="sourceid" value="Mozilla-search"/>
+</Url>
+<SearchForm>https://az.wikipedia.org/wiki/Xüsusi:Axtar</SearchForm>
+</SearchPlugin>
diff --git a/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-be.xml b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-be.xml
new file mode 100644
index 0000000000..9aa6bd3651
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-be.xml
@@ -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/. -->
+
+<SearchPlugin xmlns="http://www.mozilla.org/2006/browser/search/">
+<ShortName>Вікіпедыя (be)</ShortName>
+<InputEncoding>UTF-8</InputEncoding>
+<Image width="16" height="16">data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGAAAABgCAMAAADVRocKAAAA51BMVEUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD////7+/vl5eWxsbH9/f3Ly8tzc3P39/fe3t5cXFzz8/Pt7e3i4uI3NzcaGhoHBwcFBQX5+fnIyMhTU1MXFxcMDAzx8fHX19fFxcXCwsK7u7u1tbWenp6WlpZ8fHxXV1ctLS319fXn5+fV1dWsrKySkpJnZ2cgICDv7+/p6eng4ODQ0NC9vb24uLikpKSPj4+JiYmCgoJiYmJCQkI7OzsyMjIpKSkQEBCoqKigoKCdnZ14eHhubm5PT09LS0tERETk5OTb29unp6c0NDQkJCQOGD7BAAAAB3RSTlMA8si8ZBhlc+JuAAAAAw1JREFUaN7tmtluIjEQRYEhUxd6YYew7xAggRAgCQmB7Ov8//eM3Zg2nXkJvUjz4POAVEbyQXaVy0gOMaKRMAVAOBINcY5+UWD8OmKCIOaXhlDoNwVKNBShQImEwhQo4RAFjBIogRIogRIogRIoQWCCYXqaHJVaWrtl1IfpYp3GiczFqLHQ5kY9m0l0qVM8Txrs+8ZomkhSKpbOzlraolSP15o/EtxoU9gk2iZVujM7HnVe6eUhKaL4aYrWXWMXfd7+dIlScWxpbsjibQiLPm255sH5jYjKOoCEecge5LcTxqokuItZv5F2DID0iR21ALwctslfunNCurKEBRJkgBTZdIDOoVl0CU7FjgsZHpsi+gNoJGlisDlUkC+C8SQHejzOiqCLgXRTNYazw+vg8tsaHZ+DMd7ZlyR5Qix/uOAEgGOhlzy+EPLMMUmyOHVTyQ0wDBlXB2Dw1FzreCZJGfhyIyiDs/qWSEkiarNPxxaX3J1FWcCRLJXidtFW7MO5lmV3AhMMPS8HHsH4oBJmtEcHF+ROUEgD2E/AiVXO98AtSaoJmC4F1AUjXZAD97Bo0R491ApuBRNdVq/FGhz9hPaI48p9w1mI6rVpi1qQ9FmRuRe8iTPaJgfOi6NaTr20zDoYJUfOM2aOHM15EYwBOKbQwHm14wcY5FYgTzi5CHewMPZytO9aIHuj3MY53sF5s3M0S94EFV5bdiLeshQdgdGwc9T0IJC1VROHs4EHSgHY1XKflaFXQQ6y2MpIVIiSYDStgRLOvN/sDDCSImmv7cxaWVuu5z0LxJKU+Y1M9LE4GHOrsWnkXUDx3a5mRR8zRXFsisj5IeiBc0cmPkRxZMBY0BIGeRLIYmJ8smnLDmVuiL5ngWxksUd5JhVqYEzxTv4I1tiSc9Y38OSTgOZwnki0GYhe55Pg1VqjCUnORLf2SWAVb5fIeYPRJ/4JnoFa1THSATTyT3BcQ++f+8DKRwGN299Hltr/+zdWCZRACZRACZSAlEAJDifwRwPBP3uIUqBEg356EvzjmcCf//wFVbAkwfl+5CMAAAAASUVORK5CYII=</Image>
+<Url type="application/x-suggestions+json" method="GET" template="https://be.wikipedia.org/w/api.php">
+ <Param name="action" value="opensearch"/>
+ <Param name="search" value="{searchTerms}"/>
+</Url>
+<Url type="text/html" method="GET" template="https://be.wikipedia.org/wiki/Адмысловае:Search">
+ <Param name="search" value="{searchTerms}"/>
+ <Param name="sourceid" value="Mozilla-search"/>
+</Url>
+<SearchForm>https://be.wikipedia.org/wiki/Адмысловае:Search</SearchForm>
+</SearchPlugin>
diff --git a/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-bg.xml b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-bg.xml
new file mode 100644
index 0000000000..4b98497add
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-bg.xml
@@ -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/. -->
+
+<SearchPlugin xmlns="http://www.mozilla.org/2006/browser/search/">
+<ShortName>Уикипедия (bg)</ShortName>
+<InputEncoding>UTF-8</InputEncoding>
+<Image width="16" height="16">data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGAAAABgCAMAAADVRocKAAAA51BMVEUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD////7+/vl5eWxsbH9/f3Ly8tzc3P39/fe3t5cXFzz8/Pt7e3i4uI3NzcaGhoHBwcFBQX5+fnIyMhTU1MXFxcMDAzx8fHX19fFxcXCwsK7u7u1tbWenp6WlpZ8fHxXV1ctLS319fXn5+fV1dWsrKySkpJnZ2cgICDv7+/p6eng4ODQ0NC9vb24uLikpKSPj4+JiYmCgoJiYmJCQkI7OzsyMjIpKSkQEBCoqKigoKCdnZ14eHhubm5PT09LS0tERETk5OTb29unp6c0NDQkJCQOGD7BAAAAB3RSTlMA8si8ZBhlc+JuAAAAAw1JREFUaN7tmtluIjEQRYEhUxd6YYew7xAggRAgCQmB7Ov8//eM3Zg2nXkJvUjz4POAVEbyQXaVy0gOMaKRMAVAOBINcY5+UWD8OmKCIOaXhlDoNwVKNBShQImEwhQo4RAFjBIogRIogRIogRIoQWCCYXqaHJVaWrtl1IfpYp3GiczFqLHQ5kY9m0l0qVM8Txrs+8ZomkhSKpbOzlraolSP15o/EtxoU9gk2iZVujM7HnVe6eUhKaL4aYrWXWMXfd7+dIlScWxpbsjibQiLPm255sH5jYjKOoCEecge5LcTxqokuItZv5F2DID0iR21ALwctslfunNCurKEBRJkgBTZdIDOoVl0CU7FjgsZHpsi+gNoJGlisDlUkC+C8SQHejzOiqCLgXRTNYazw+vg8tsaHZ+DMd7ZlyR5Qix/uOAEgGOhlzy+EPLMMUmyOHVTyQ0wDBlXB2Dw1FzreCZJGfhyIyiDs/qWSEkiarNPxxaX3J1FWcCRLJXidtFW7MO5lmV3AhMMPS8HHsH4oBJmtEcHF+ROUEgD2E/AiVXO98AtSaoJmC4F1AUjXZAD97Bo0R491ApuBRNdVq/FGhz9hPaI48p9w1mI6rVpi1qQ9FmRuRe8iTPaJgfOi6NaTr20zDoYJUfOM2aOHM15EYwBOKbQwHm14wcY5FYgTzi5CHewMPZytO9aIHuj3MY53sF5s3M0S94EFV5bdiLeshQdgdGwc9T0IJC1VROHs4EHSgHY1XKflaFXQQ6y2MpIVIiSYDStgRLOvN/sDDCSImmv7cxaWVuu5z0LxJKU+Y1M9LE4GHOrsWnkXUDx3a5mRR8zRXFsisj5IeiBc0cmPkRxZMBY0BIGeRLIYmJ8smnLDmVuiL5ngWxksUd5JhVqYEzxTv4I1tiSc9Y38OSTgOZwnki0GYhe55Pg1VqjCUnORLf2SWAVb5fIeYPRJ/4JnoFa1THSATTyT3BcQ++f+8DKRwGN299Hltr/+zdWCZRACZRACZSAlEAJDifwRwPBP3uIUqBEg356EvzjmcCf//wFVbAkwfl+5CMAAAAASUVORK5CYII=</Image>
+<Url type="application/x-suggestions+json" method="GET" template="https://bg.wikipedia.org/w/api.php">
+ <Param name="action" value="opensearch"/>
+ <Param name="search" value="{searchTerms}"/>
+</Url>
+<Url type="text/html" method="GET" template="https://bg.wikipedia.org/wiki/Специални:Търсене">
+ <Param name="search" value="{searchTerms}"/>
+ <Param name="sourceid" value="Mozilla-search"/>
+</Url>
+<SearchForm>https://bg.wikipedia.org/wiki/Специални:Търсене</SearchForm>
+</SearchPlugin>
diff --git a/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-bn.xml b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-bn.xml
new file mode 100644
index 0000000000..b564438636
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-bn.xml
@@ -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/. -->
+
+<SearchPlugin xmlns="http://www.mozilla.org/2006/browser/search/">
+<ShortName>উইকিপিডিয়া (bn)</ShortName>
+<InputEncoding>UTF-8</InputEncoding>
+<Image width="16" height="16">data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGAAAABgCAMAAADVRocKAAAA51BMVEUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD////7+/vl5eWxsbH9/f3Ly8tzc3P39/fe3t5cXFzz8/Pt7e3i4uI3NzcaGhoHBwcFBQX5+fnIyMhTU1MXFxcMDAzx8fHX19fFxcXCwsK7u7u1tbWenp6WlpZ8fHxXV1ctLS319fXn5+fV1dWsrKySkpJnZ2cgICDv7+/p6eng4ODQ0NC9vb24uLikpKSPj4+JiYmCgoJiYmJCQkI7OzsyMjIpKSkQEBCoqKigoKCdnZ14eHhubm5PT09LS0tERETk5OTb29unp6c0NDQkJCQOGD7BAAAAB3RSTlMA8si8ZBhlc+JuAAAAAw1JREFUaN7tmtluIjEQRYEhUxd6YYew7xAggRAgCQmB7Ov8//eM3Zg2nXkJvUjz4POAVEbyQXaVy0gOMaKRMAVAOBINcY5+UWD8OmKCIOaXhlDoNwVKNBShQImEwhQo4RAFjBIogRIogRIogRIoQWCCYXqaHJVaWrtl1IfpYp3GiczFqLHQ5kY9m0l0qVM8Txrs+8ZomkhSKpbOzlraolSP15o/EtxoU9gk2iZVujM7HnVe6eUhKaL4aYrWXWMXfd7+dIlScWxpbsjibQiLPm255sH5jYjKOoCEecge5LcTxqokuItZv5F2DID0iR21ALwctslfunNCurKEBRJkgBTZdIDOoVl0CU7FjgsZHpsi+gNoJGlisDlUkC+C8SQHejzOiqCLgXRTNYazw+vg8tsaHZ+DMd7ZlyR5Qix/uOAEgGOhlzy+EPLMMUmyOHVTyQ0wDBlXB2Dw1FzreCZJGfhyIyiDs/qWSEkiarNPxxaX3J1FWcCRLJXidtFW7MO5lmV3AhMMPS8HHsH4oBJmtEcHF+ROUEgD2E/AiVXO98AtSaoJmC4F1AUjXZAD97Bo0R491ApuBRNdVq/FGhz9hPaI48p9w1mI6rVpi1qQ9FmRuRe8iTPaJgfOi6NaTr20zDoYJUfOM2aOHM15EYwBOKbQwHm14wcY5FYgTzi5CHewMPZytO9aIHuj3MY53sF5s3M0S94EFV5bdiLeshQdgdGwc9T0IJC1VROHs4EHSgHY1XKflaFXQQ6y2MpIVIiSYDStgRLOvN/sDDCSImmv7cxaWVuu5z0LxJKU+Y1M9LE4GHOrsWnkXUDx3a5mRR8zRXFsisj5IeiBc0cmPkRxZMBY0BIGeRLIYmJ8smnLDmVuiL5ngWxksUd5JhVqYEzxTv4I1tiSc9Y38OSTgOZwnki0GYhe55Pg1VqjCUnORLf2SWAVb5fIeYPRJ/4JnoFa1THSATTyT3BcQ++f+8DKRwGN299Hltr/+zdWCZRACZRACZSAlEAJDifwRwPBP3uIUqBEg356EvzjmcCf//wFVbAkwfl+5CMAAAAASUVORK5CYII=</Image>
+<Url type="application/x-suggestions+json" method="GET" template="https://bn.wikipedia.org/w/api.php">
+ <Param name="action" value="opensearch"/>
+ <Param name="search" value="{searchTerms}"/>
+</Url>
+<Url type="text/html" method="GET" template="https://bn.wikipedia.org/wiki/বিশেষ:Search">
+ <Param name="search" value="{searchTerms}"/>
+ <Param name="sourceid" value="Mozilla-search"/>
+</Url>
+<SearchForm>https://bn.wikipedia.org/wiki/বিশেষ:Search</SearchForm>
+</SearchPlugin>
diff --git a/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-br.xml b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-br.xml
new file mode 100644
index 0000000000..41bf921eb4
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-br.xml
@@ -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/. -->
+
+<SearchPlugin xmlns="http://www.mozilla.org/2006/browser/search/">
+<ShortName>Wikipedia (br)</ShortName>
+<InputEncoding>UTF-8</InputEncoding>
+<Image width="16" height="16">data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGAAAABgCAMAAADVRocKAAAA51BMVEUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD////7+/vl5eWxsbH9/f3Ly8tzc3P39/fe3t5cXFzz8/Pt7e3i4uI3NzcaGhoHBwcFBQX5+fnIyMhTU1MXFxcMDAzx8fHX19fFxcXCwsK7u7u1tbWenp6WlpZ8fHxXV1ctLS319fXn5+fV1dWsrKySkpJnZ2cgICDv7+/p6eng4ODQ0NC9vb24uLikpKSPj4+JiYmCgoJiYmJCQkI7OzsyMjIpKSkQEBCoqKigoKCdnZ14eHhubm5PT09LS0tERETk5OTb29unp6c0NDQkJCQOGD7BAAAAB3RSTlMA8si8ZBhlc+JuAAAAAw1JREFUaN7tmtluIjEQRYEhUxd6YYew7xAggRAgCQmB7Ov8//eM3Zg2nXkJvUjz4POAVEbyQXaVy0gOMaKRMAVAOBINcY5+UWD8OmKCIOaXhlDoNwVKNBShQImEwhQo4RAFjBIogRIogRIogRIoQWCCYXqaHJVaWrtl1IfpYp3GiczFqLHQ5kY9m0l0qVM8Txrs+8ZomkhSKpbOzlraolSP15o/EtxoU9gk2iZVujM7HnVe6eUhKaL4aYrWXWMXfd7+dIlScWxpbsjibQiLPm255sH5jYjKOoCEecge5LcTxqokuItZv5F2DID0iR21ALwctslfunNCurKEBRJkgBTZdIDOoVl0CU7FjgsZHpsi+gNoJGlisDlUkC+C8SQHejzOiqCLgXRTNYazw+vg8tsaHZ+DMd7ZlyR5Qix/uOAEgGOhlzy+EPLMMUmyOHVTyQ0wDBlXB2Dw1FzreCZJGfhyIyiDs/qWSEkiarNPxxaX3J1FWcCRLJXidtFW7MO5lmV3AhMMPS8HHsH4oBJmtEcHF+ROUEgD2E/AiVXO98AtSaoJmC4F1AUjXZAD97Bo0R491ApuBRNdVq/FGhz9hPaI48p9w1mI6rVpi1qQ9FmRuRe8iTPaJgfOi6NaTr20zDoYJUfOM2aOHM15EYwBOKbQwHm14wcY5FYgTzi5CHewMPZytO9aIHuj3MY53sF5s3M0S94EFV5bdiLeshQdgdGwc9T0IJC1VROHs4EHSgHY1XKflaFXQQ6y2MpIVIiSYDStgRLOvN/sDDCSImmv7cxaWVuu5z0LxJKU+Y1M9LE4GHOrsWnkXUDx3a5mRR8zRXFsisj5IeiBc0cmPkRxZMBY0BIGeRLIYmJ8smnLDmVuiL5ngWxksUd5JhVqYEzxTv4I1tiSc9Y38OSTgOZwnki0GYhe55Pg1VqjCUnORLf2SWAVb5fIeYPRJ/4JnoFa1THSATTyT3BcQ++f+8DKRwGN299Hltr/+zdWCZRACZRACZSAlEAJDifwRwPBP3uIUqBEg356EvzjmcCf//wFVbAkwfl+5CMAAAAASUVORK5CYII=</Image>
+<Url type="application/x-suggestions+json" method="GET" template="https://br.wikipedia.org/w/api.php">
+ <Param name="action" value="opensearch"/>
+ <Param name="search" value="{searchTerms}"/>
+</Url>
+<Url type="text/html" method="GET" template="https://br.wikipedia.org/wiki/Dibar:Klask">
+ <Param name="search" value="{searchTerms}"/>
+ <Param name="sourceid" value="Mozilla-search"/>
+</Url>
+<SearchForm>https://br.wikipedia.org/wiki/Dibar:Klask</SearchForm>
+</SearchPlugin>
diff --git a/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-bs.xml b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-bs.xml
new file mode 100644
index 0000000000..f54aed3b54
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-bs.xml
@@ -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/. -->
+
+<SearchPlugin xmlns="http://www.mozilla.org/2006/browser/search/">
+<ShortName>Wikipedia (bs)</ShortName>
+<InputEncoding>UTF-8</InputEncoding>
+<Image width="16" height="16">data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGAAAABgCAMAAADVRocKAAAA51BMVEUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD////7+/vl5eWxsbH9/f3Ly8tzc3P39/fe3t5cXFzz8/Pt7e3i4uI3NzcaGhoHBwcFBQX5+fnIyMhTU1MXFxcMDAzx8fHX19fFxcXCwsK7u7u1tbWenp6WlpZ8fHxXV1ctLS319fXn5+fV1dWsrKySkpJnZ2cgICDv7+/p6eng4ODQ0NC9vb24uLikpKSPj4+JiYmCgoJiYmJCQkI7OzsyMjIpKSkQEBCoqKigoKCdnZ14eHhubm5PT09LS0tERETk5OTb29unp6c0NDQkJCQOGD7BAAAAB3RSTlMA8si8ZBhlc+JuAAAAAw1JREFUaN7tmtluIjEQRYEhUxd6YYew7xAggRAgCQmB7Ov8//eM3Zg2nXkJvUjz4POAVEbyQXaVy0gOMaKRMAVAOBINcY5+UWD8OmKCIOaXhlDoNwVKNBShQImEwhQo4RAFjBIogRIogRIogRIoQWCCYXqaHJVaWrtl1IfpYp3GiczFqLHQ5kY9m0l0qVM8Txrs+8ZomkhSKpbOzlraolSP15o/EtxoU9gk2iZVujM7HnVe6eUhKaL4aYrWXWMXfd7+dIlScWxpbsjibQiLPm255sH5jYjKOoCEecge5LcTxqokuItZv5F2DID0iR21ALwctslfunNCurKEBRJkgBTZdIDOoVl0CU7FjgsZHpsi+gNoJGlisDlUkC+C8SQHejzOiqCLgXRTNYazw+vg8tsaHZ+DMd7ZlyR5Qix/uOAEgGOhlzy+EPLMMUmyOHVTyQ0wDBlXB2Dw1FzreCZJGfhyIyiDs/qWSEkiarNPxxaX3J1FWcCRLJXidtFW7MO5lmV3AhMMPS8HHsH4oBJmtEcHF+ROUEgD2E/AiVXO98AtSaoJmC4F1AUjXZAD97Bo0R491ApuBRNdVq/FGhz9hPaI48p9w1mI6rVpi1qQ9FmRuRe8iTPaJgfOi6NaTr20zDoYJUfOM2aOHM15EYwBOKbQwHm14wcY5FYgTzi5CHewMPZytO9aIHuj3MY53sF5s3M0S94EFV5bdiLeshQdgdGwc9T0IJC1VROHs4EHSgHY1XKflaFXQQ6y2MpIVIiSYDStgRLOvN/sDDCSImmv7cxaWVuu5z0LxJKU+Y1M9LE4GHOrsWnkXUDx3a5mRR8zRXFsisj5IeiBc0cmPkRxZMBY0BIGeRLIYmJ8smnLDmVuiL5ngWxksUd5JhVqYEzxTv4I1tiSc9Y38OSTgOZwnki0GYhe55Pg1VqjCUnORLf2SWAVb5fIeYPRJ/4JnoFa1THSATTyT3BcQ++f+8DKRwGN299Hltr/+zdWCZRACZRACZSAlEAJDifwRwPBP3uIUqBEg356EvzjmcCf//wFVbAkwfl+5CMAAAAASUVORK5CYII=</Image>
+<Url type="application/x-suggestions+json" method="GET" template="https://bs.wikipedia.org/w/api.php">
+ <Param name="action" value="opensearch"/>
+ <Param name="search" value="{searchTerms}"/>
+</Url>
+<Url type="text/html" method="GET" template="https://bs.wikipedia.org/wiki/Posebno:Pretraga">
+ <Param name="search" value="{searchTerms}"/>
+ <Param name="sourceid" value="Mozilla-search"/>
+</Url>
+<SearchForm>https://bs.wikipedia.org/wiki/Posebno:Pretraga</SearchForm>
+</SearchPlugin>
diff --git a/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-ca.xml b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-ca.xml
new file mode 100644
index 0000000000..3b08c30c29
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-ca.xml
@@ -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/. -->
+
+<SearchPlugin xmlns="http://www.mozilla.org/2006/browser/search/">
+<ShortName>Viquipèdia (ca)</ShortName>
+<InputEncoding>UTF-8</InputEncoding>
+<Image width="16" height="16">data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGAAAABgCAMAAADVRocKAAAA51BMVEUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD////7+/vl5eWxsbH9/f3Ly8tzc3P39/fe3t5cXFzz8/Pt7e3i4uI3NzcaGhoHBwcFBQX5+fnIyMhTU1MXFxcMDAzx8fHX19fFxcXCwsK7u7u1tbWenp6WlpZ8fHxXV1ctLS319fXn5+fV1dWsrKySkpJnZ2cgICDv7+/p6eng4ODQ0NC9vb24uLikpKSPj4+JiYmCgoJiYmJCQkI7OzsyMjIpKSkQEBCoqKigoKCdnZ14eHhubm5PT09LS0tERETk5OTb29unp6c0NDQkJCQOGD7BAAAAB3RSTlMA8si8ZBhlc+JuAAAAAw1JREFUaN7tmtluIjEQRYEhUxd6YYew7xAggRAgCQmB7Ov8//eM3Zg2nXkJvUjz4POAVEbyQXaVy0gOMaKRMAVAOBINcY5+UWD8OmKCIOaXhlDoNwVKNBShQImEwhQo4RAFjBIogRIogRIogRIoQWCCYXqaHJVaWrtl1IfpYp3GiczFqLHQ5kY9m0l0qVM8Txrs+8ZomkhSKpbOzlraolSP15o/EtxoU9gk2iZVujM7HnVe6eUhKaL4aYrWXWMXfd7+dIlScWxpbsjibQiLPm255sH5jYjKOoCEecge5LcTxqokuItZv5F2DID0iR21ALwctslfunNCurKEBRJkgBTZdIDOoVl0CU7FjgsZHpsi+gNoJGlisDlUkC+C8SQHejzOiqCLgXRTNYazw+vg8tsaHZ+DMd7ZlyR5Qix/uOAEgGOhlzy+EPLMMUmyOHVTyQ0wDBlXB2Dw1FzreCZJGfhyIyiDs/qWSEkiarNPxxaX3J1FWcCRLJXidtFW7MO5lmV3AhMMPS8HHsH4oBJmtEcHF+ROUEgD2E/AiVXO98AtSaoJmC4F1AUjXZAD97Bo0R491ApuBRNdVq/FGhz9hPaI48p9w1mI6rVpi1qQ9FmRuRe8iTPaJgfOi6NaTr20zDoYJUfOM2aOHM15EYwBOKbQwHm14wcY5FYgTzi5CHewMPZytO9aIHuj3MY53sF5s3M0S94EFV5bdiLeshQdgdGwc9T0IJC1VROHs4EHSgHY1XKflaFXQQ6y2MpIVIiSYDStgRLOvN/sDDCSImmv7cxaWVuu5z0LxJKU+Y1M9LE4GHOrsWnkXUDx3a5mRR8zRXFsisj5IeiBc0cmPkRxZMBY0BIGeRLIYmJ8smnLDmVuiL5ngWxksUd5JhVqYEzxTv4I1tiSc9Y38OSTgOZwnki0GYhe55Pg1VqjCUnORLf2SWAVb5fIeYPRJ/4JnoFa1THSATTyT3BcQ++f+8DKRwGN299Hltr/+zdWCZRACZRACZSAlEAJDifwRwPBP3uIUqBEg356EvzjmcCf//wFVbAkwfl+5CMAAAAASUVORK5CYII=</Image>
+<Url type="application/x-suggestions+json" method="GET" template="https://ca.wikipedia.org/w/api.php">
+ <Param name="action" value="opensearch"/>
+ <Param name="search" value="{searchTerms}"/>
+</Url>
+<Url type="text/html" method="GET" template="https://ca.wikipedia.org/wiki/Especial:Cerca">
+ <Param name="search" value="{searchTerms}"/>
+ <Param name="sourceid" value="Mozilla-search"/>
+</Url>
+<SearchForm>https://ca.wikipedia.org/wiki/Especial:Cerca</SearchForm>
+</SearchPlugin>
diff --git a/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-cy.xml b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-cy.xml
new file mode 100644
index 0000000000..72c526eee4
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-cy.xml
@@ -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/. -->
+
+<SearchPlugin xmlns="http://www.mozilla.org/2006/browser/search/">
+<ShortName>Wicipedia (cy)</ShortName>
+<InputEncoding>UTF-8</InputEncoding>
+<Image width="16" height="16">data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGAAAABgCAMAAADVRocKAAAA51BMVEUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD////7+/vl5eWxsbH9/f3Ly8tzc3P39/fe3t5cXFzz8/Pt7e3i4uI3NzcaGhoHBwcFBQX5+fnIyMhTU1MXFxcMDAzx8fHX19fFxcXCwsK7u7u1tbWenp6WlpZ8fHxXV1ctLS319fXn5+fV1dWsrKySkpJnZ2cgICDv7+/p6eng4ODQ0NC9vb24uLikpKSPj4+JiYmCgoJiYmJCQkI7OzsyMjIpKSkQEBCoqKigoKCdnZ14eHhubm5PT09LS0tERETk5OTb29unp6c0NDQkJCQOGD7BAAAAB3RSTlMA8si8ZBhlc+JuAAAAAw1JREFUaN7tmtluIjEQRYEhUxd6YYew7xAggRAgCQmB7Ov8//eM3Zg2nXkJvUjz4POAVEbyQXaVy0gOMaKRMAVAOBINcY5+UWD8OmKCIOaXhlDoNwVKNBShQImEwhQo4RAFjBIogRIogRIogRIoQWCCYXqaHJVaWrtl1IfpYp3GiczFqLHQ5kY9m0l0qVM8Txrs+8ZomkhSKpbOzlraolSP15o/EtxoU9gk2iZVujM7HnVe6eUhKaL4aYrWXWMXfd7+dIlScWxpbsjibQiLPm255sH5jYjKOoCEecge5LcTxqokuItZv5F2DID0iR21ALwctslfunNCurKEBRJkgBTZdIDOoVl0CU7FjgsZHpsi+gNoJGlisDlUkC+C8SQHejzOiqCLgXRTNYazw+vg8tsaHZ+DMd7ZlyR5Qix/uOAEgGOhlzy+EPLMMUmyOHVTyQ0wDBlXB2Dw1FzreCZJGfhyIyiDs/qWSEkiarNPxxaX3J1FWcCRLJXidtFW7MO5lmV3AhMMPS8HHsH4oBJmtEcHF+ROUEgD2E/AiVXO98AtSaoJmC4F1AUjXZAD97Bo0R491ApuBRNdVq/FGhz9hPaI48p9w1mI6rVpi1qQ9FmRuRe8iTPaJgfOi6NaTr20zDoYJUfOM2aOHM15EYwBOKbQwHm14wcY5FYgTzi5CHewMPZytO9aIHuj3MY53sF5s3M0S94EFV5bdiLeshQdgdGwc9T0IJC1VROHs4EHSgHY1XKflaFXQQ6y2MpIVIiSYDStgRLOvN/sDDCSImmv7cxaWVuu5z0LxJKU+Y1M9LE4GHOrsWnkXUDx3a5mRR8zRXFsisj5IeiBc0cmPkRxZMBY0BIGeRLIYmJ8smnLDmVuiL5ngWxksUd5JhVqYEzxTv4I1tiSc9Y38OSTgOZwnki0GYhe55Pg1VqjCUnORLf2SWAVb5fIeYPRJ/4JnoFa1THSATTyT3BcQ++f+8DKRwGN299Hltr/+zdWCZRACZRACZSAlEAJDifwRwPBP3uIUqBEg356EvzjmcCf//wFVbAkwfl+5CMAAAAASUVORK5CYII=</Image>
+<Url type="application/x-suggestions+json" method="GET" template="https://cy.wikipedia.org/w/api.php">
+ <Param name="action" value="opensearch"/>
+ <Param name="search" value="{searchTerms}"/>
+</Url>
+<Url type="text/html" method="GET" template="https://cy.wikipedia.org/wiki/Arbennig:Search">
+ <Param name="search" value="{searchTerms}"/>
+ <Param name="sourceid" value="Mozilla-search"/>
+</Url>
+<SearchForm>https://cy.wikipedia.org/wiki/Arbennig:Search</SearchForm>
+</SearchPlugin>
diff --git a/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-cz.xml b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-cz.xml
new file mode 100644
index 0000000000..9fa115ce52
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-cz.xml
@@ -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/. -->
+
+<SearchPlugin xmlns="http://www.mozilla.org/2006/browser/search/">
+<ShortName>Wikipedie (cs)</ShortName>
+<InputEncoding>UTF-8</InputEncoding>
+<Image width="16" height="16">data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGAAAABgCAMAAADVRocKAAAA51BMVEUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD////7+/vl5eWxsbH9/f3Ly8tzc3P39/fe3t5cXFzz8/Pt7e3i4uI3NzcaGhoHBwcFBQX5+fnIyMhTU1MXFxcMDAzx8fHX19fFxcXCwsK7u7u1tbWenp6WlpZ8fHxXV1ctLS319fXn5+fV1dWsrKySkpJnZ2cgICDv7+/p6eng4ODQ0NC9vb24uLikpKSPj4+JiYmCgoJiYmJCQkI7OzsyMjIpKSkQEBCoqKigoKCdnZ14eHhubm5PT09LS0tERETk5OTb29unp6c0NDQkJCQOGD7BAAAAB3RSTlMA8si8ZBhlc+JuAAAAAw1JREFUaN7tmtluIjEQRYEhUxd6YYew7xAggRAgCQmB7Ov8//eM3Zg2nXkJvUjz4POAVEbyQXaVy0gOMaKRMAVAOBINcY5+UWD8OmKCIOaXhlDoNwVKNBShQImEwhQo4RAFjBIogRIogRIogRIoQWCCYXqaHJVaWrtl1IfpYp3GiczFqLHQ5kY9m0l0qVM8Txrs+8ZomkhSKpbOzlraolSP15o/EtxoU9gk2iZVujM7HnVe6eUhKaL4aYrWXWMXfd7+dIlScWxpbsjibQiLPm255sH5jYjKOoCEecge5LcTxqokuItZv5F2DID0iR21ALwctslfunNCurKEBRJkgBTZdIDOoVl0CU7FjgsZHpsi+gNoJGlisDlUkC+C8SQHejzOiqCLgXRTNYazw+vg8tsaHZ+DMd7ZlyR5Qix/uOAEgGOhlzy+EPLMMUmyOHVTyQ0wDBlXB2Dw1FzreCZJGfhyIyiDs/qWSEkiarNPxxaX3J1FWcCRLJXidtFW7MO5lmV3AhMMPS8HHsH4oBJmtEcHF+ROUEgD2E/AiVXO98AtSaoJmC4F1AUjXZAD97Bo0R491ApuBRNdVq/FGhz9hPaI48p9w1mI6rVpi1qQ9FmRuRe8iTPaJgfOi6NaTr20zDoYJUfOM2aOHM15EYwBOKbQwHm14wcY5FYgTzi5CHewMPZytO9aIHuj3MY53sF5s3M0S94EFV5bdiLeshQdgdGwc9T0IJC1VROHs4EHSgHY1XKflaFXQQ6y2MpIVIiSYDStgRLOvN/sDDCSImmv7cxaWVuu5z0LxJKU+Y1M9LE4GHOrsWnkXUDx3a5mRR8zRXFsisj5IeiBc0cmPkRxZMBY0BIGeRLIYmJ8smnLDmVuiL5ngWxksUd5JhVqYEzxTv4I1tiSc9Y38OSTgOZwnki0GYhe55Pg1VqjCUnORLf2SWAVb5fIeYPRJ/4JnoFa1THSATTyT3BcQ++f+8DKRwGN299Hltr/+zdWCZRACZRACZSAlEAJDifwRwPBP3uIUqBEg356EvzjmcCf//wFVbAkwfl+5CMAAAAASUVORK5CYII=</Image>
+<Url type="application/x-suggestions+json" method="GET" template="https://cs.wikipedia.org/w/api.php">
+ <Param name="action" value="opensearch"/>
+ <Param name="search" value="{searchTerms}"/>
+</Url>
+<Url type="text/html" method="GET" template="https://cs.wikipedia.org/wiki/Speciální:Hledání">
+ <Param name="search" value="{searchTerms}"/>
+ <Param name="sourceid" value="Mozilla-search"/>
+</Url>
+<SearchForm>https://cs.wikipedia.org/wiki/Speciální:Hledání</SearchForm>
+</SearchPlugin>
diff --git a/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-da.xml b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-da.xml
new file mode 100644
index 0000000000..7ac52b86f6
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-da.xml
@@ -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/. -->
+
+<SearchPlugin xmlns="http://www.mozilla.org/2006/browser/search/">
+<ShortName>Wikipedia (da)</ShortName>
+<InputEncoding>UTF-8</InputEncoding>
+<Image width="16" height="16">data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGAAAABgCAMAAADVRocKAAAA51BMVEUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD////7+/vl5eWxsbH9/f3Ly8tzc3P39/fe3t5cXFzz8/Pt7e3i4uI3NzcaGhoHBwcFBQX5+fnIyMhTU1MXFxcMDAzx8fHX19fFxcXCwsK7u7u1tbWenp6WlpZ8fHxXV1ctLS319fXn5+fV1dWsrKySkpJnZ2cgICDv7+/p6eng4ODQ0NC9vb24uLikpKSPj4+JiYmCgoJiYmJCQkI7OzsyMjIpKSkQEBCoqKigoKCdnZ14eHhubm5PT09LS0tERETk5OTb29unp6c0NDQkJCQOGD7BAAAAB3RSTlMA8si8ZBhlc+JuAAAAAw1JREFUaN7tmtluIjEQRYEhUxd6YYew7xAggRAgCQmB7Ov8//eM3Zg2nXkJvUjz4POAVEbyQXaVy0gOMaKRMAVAOBINcY5+UWD8OmKCIOaXhlDoNwVKNBShQImEwhQo4RAFjBIogRIogRIogRIoQWCCYXqaHJVaWrtl1IfpYp3GiczFqLHQ5kY9m0l0qVM8Txrs+8ZomkhSKpbOzlraolSP15o/EtxoU9gk2iZVujM7HnVe6eUhKaL4aYrWXWMXfd7+dIlScWxpbsjibQiLPm255sH5jYjKOoCEecge5LcTxqokuItZv5F2DID0iR21ALwctslfunNCurKEBRJkgBTZdIDOoVl0CU7FjgsZHpsi+gNoJGlisDlUkC+C8SQHejzOiqCLgXRTNYazw+vg8tsaHZ+DMd7ZlyR5Qix/uOAEgGOhlzy+EPLMMUmyOHVTyQ0wDBlXB2Dw1FzreCZJGfhyIyiDs/qWSEkiarNPxxaX3J1FWcCRLJXidtFW7MO5lmV3AhMMPS8HHsH4oBJmtEcHF+ROUEgD2E/AiVXO98AtSaoJmC4F1AUjXZAD97Bo0R491ApuBRNdVq/FGhz9hPaI48p9w1mI6rVpi1qQ9FmRuRe8iTPaJgfOi6NaTr20zDoYJUfOM2aOHM15EYwBOKbQwHm14wcY5FYgTzi5CHewMPZytO9aIHuj3MY53sF5s3M0S94EFV5bdiLeshQdgdGwc9T0IJC1VROHs4EHSgHY1XKflaFXQQ6y2MpIVIiSYDStgRLOvN/sDDCSImmv7cxaWVuu5z0LxJKU+Y1M9LE4GHOrsWnkXUDx3a5mRR8zRXFsisj5IeiBc0cmPkRxZMBY0BIGeRLIYmJ8smnLDmVuiL5ngWxksUd5JhVqYEzxTv4I1tiSc9Y38OSTgOZwnki0GYhe55Pg1VqjCUnORLf2SWAVb5fIeYPRJ/4JnoFa1THSATTyT3BcQ++f+8DKRwGN299Hltr/+zdWCZRACZRACZSAlEAJDifwRwPBP3uIUqBEg356EvzjmcCf//wFVbAkwfl+5CMAAAAASUVORK5CYII=</Image>
+<Url type="application/x-suggestions+json" method="GET" template="https://da.wikipedia.org/w/api.php">
+ <Param name="action" value="opensearch"/>
+ <Param name="search" value="{searchTerms}"/>
+</Url>
+<Url type="text/html" method="GET" template="https://da.wikipedia.org/wiki/Speciel:Søgning">
+ <Param name="search" value="{searchTerms}"/>
+ <Param name="sourceid" value="Mozilla-search"/>
+</Url>
+<SearchForm>https://da.wikipedia.org/wiki/Speciel:Søgning</SearchForm>
+</SearchPlugin>
diff --git a/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-de.xml b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-de.xml
new file mode 100644
index 0000000000..1052b85311
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-de.xml
@@ -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/. -->
+
+<SearchPlugin xmlns="http://www.mozilla.org/2006/browser/search/">
+<ShortName>Wikipedia (de)</ShortName>
+<InputEncoding>UTF-8</InputEncoding>
+<Image width="16" height="16">data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGAAAABgCAMAAADVRocKAAAA51BMVEUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD////7+/vl5eWxsbH9/f3Ly8tzc3P39/fe3t5cXFzz8/Pt7e3i4uI3NzcaGhoHBwcFBQX5+fnIyMhTU1MXFxcMDAzx8fHX19fFxcXCwsK7u7u1tbWenp6WlpZ8fHxXV1ctLS319fXn5+fV1dWsrKySkpJnZ2cgICDv7+/p6eng4ODQ0NC9vb24uLikpKSPj4+JiYmCgoJiYmJCQkI7OzsyMjIpKSkQEBCoqKigoKCdnZ14eHhubm5PT09LS0tERETk5OTb29unp6c0NDQkJCQOGD7BAAAAB3RSTlMA8si8ZBhlc+JuAAAAAw1JREFUaN7tmtluIjEQRYEhUxd6YYew7xAggRAgCQmB7Ov8//eM3Zg2nXkJvUjz4POAVEbyQXaVy0gOMaKRMAVAOBINcY5+UWD8OmKCIOaXhlDoNwVKNBShQImEwhQo4RAFjBIogRIogRIogRIoQWCCYXqaHJVaWrtl1IfpYp3GiczFqLHQ5kY9m0l0qVM8Txrs+8ZomkhSKpbOzlraolSP15o/EtxoU9gk2iZVujM7HnVe6eUhKaL4aYrWXWMXfd7+dIlScWxpbsjibQiLPm255sH5jYjKOoCEecge5LcTxqokuItZv5F2DID0iR21ALwctslfunNCurKEBRJkgBTZdIDOoVl0CU7FjgsZHpsi+gNoJGlisDlUkC+C8SQHejzOiqCLgXRTNYazw+vg8tsaHZ+DMd7ZlyR5Qix/uOAEgGOhlzy+EPLMMUmyOHVTyQ0wDBlXB2Dw1FzreCZJGfhyIyiDs/qWSEkiarNPxxaX3J1FWcCRLJXidtFW7MO5lmV3AhMMPS8HHsH4oBJmtEcHF+ROUEgD2E/AiVXO98AtSaoJmC4F1AUjXZAD97Bo0R491ApuBRNdVq/FGhz9hPaI48p9w1mI6rVpi1qQ9FmRuRe8iTPaJgfOi6NaTr20zDoYJUfOM2aOHM15EYwBOKbQwHm14wcY5FYgTzi5CHewMPZytO9aIHuj3MY53sF5s3M0S94EFV5bdiLeshQdgdGwc9T0IJC1VROHs4EHSgHY1XKflaFXQQ6y2MpIVIiSYDStgRLOvN/sDDCSImmv7cxaWVuu5z0LxJKU+Y1M9LE4GHOrsWnkXUDx3a5mRR8zRXFsisj5IeiBc0cmPkRxZMBY0BIGeRLIYmJ8smnLDmVuiL5ngWxksUd5JhVqYEzxTv4I1tiSc9Y38OSTgOZwnki0GYhe55Pg1VqjCUnORLf2SWAVb5fIeYPRJ/4JnoFa1THSATTyT3BcQ++f+8DKRwGN299Hltr/+zdWCZRACZRACZSAlEAJDifwRwPBP3uIUqBEg356EvzjmcCf//wFVbAkwfl+5CMAAAAASUVORK5CYII=</Image>
+<Url type="application/x-suggestions+json" method="GET" template="https://de.wikipedia.org/w/api.php">
+ <Param name="action" value="opensearch"/>
+ <Param name="search" value="{searchTerms}"/>
+</Url>
+<Url type="text/html" method="GET" template="https://de.wikipedia.org/wiki/Spezial:Suche">
+ <Param name="search" value="{searchTerms}"/>
+ <Param name="sourceid" value="Mozilla-search"/>
+</Url>
+<SearchForm>https://de.wikipedia.org/wiki/Spezial:Suche</SearchForm>
+</SearchPlugin>
diff --git a/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-dsb.xml b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-dsb.xml
new file mode 100644
index 0000000000..52ce1e97b3
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-dsb.xml
@@ -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/. -->
+
+<SearchPlugin xmlns="http://www.mozilla.org/2006/browser/search/">
+<ShortName>Wikipedija (dsb)</ShortName>
+<InputEncoding>UTF-8</InputEncoding>
+<Image width="16" height="16">data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGAAAABgCAMAAADVRocKAAAA51BMVEUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD////7+/vl5eWxsbH9/f3Ly8tzc3P39/fe3t5cXFzz8/Pt7e3i4uI3NzcaGhoHBwcFBQX5+fnIyMhTU1MXFxcMDAzx8fHX19fFxcXCwsK7u7u1tbWenp6WlpZ8fHxXV1ctLS319fXn5+fV1dWsrKySkpJnZ2cgICDv7+/p6eng4ODQ0NC9vb24uLikpKSPj4+JiYmCgoJiYmJCQkI7OzsyMjIpKSkQEBCoqKigoKCdnZ14eHhubm5PT09LS0tERETk5OTb29unp6c0NDQkJCQOGD7BAAAAB3RSTlMA8si8ZBhlc+JuAAAAAw1JREFUaN7tmtluIjEQRYEhUxd6YYew7xAggRAgCQmB7Ov8//eM3Zg2nXkJvUjz4POAVEbyQXaVy0gOMaKRMAVAOBINcY5+UWD8OmKCIOaXhlDoNwVKNBShQImEwhQo4RAFjBIogRIogRIogRIoQWCCYXqaHJVaWrtl1IfpYp3GiczFqLHQ5kY9m0l0qVM8Txrs+8ZomkhSKpbOzlraolSP15o/EtxoU9gk2iZVujM7HnVe6eUhKaL4aYrWXWMXfd7+dIlScWxpbsjibQiLPm255sH5jYjKOoCEecge5LcTxqokuItZv5F2DID0iR21ALwctslfunNCurKEBRJkgBTZdIDOoVl0CU7FjgsZHpsi+gNoJGlisDlUkC+C8SQHejzOiqCLgXRTNYazw+vg8tsaHZ+DMd7ZlyR5Qix/uOAEgGOhlzy+EPLMMUmyOHVTyQ0wDBlXB2Dw1FzreCZJGfhyIyiDs/qWSEkiarNPxxaX3J1FWcCRLJXidtFW7MO5lmV3AhMMPS8HHsH4oBJmtEcHF+ROUEgD2E/AiVXO98AtSaoJmC4F1AUjXZAD97Bo0R491ApuBRNdVq/FGhz9hPaI48p9w1mI6rVpi1qQ9FmRuRe8iTPaJgfOi6NaTr20zDoYJUfOM2aOHM15EYwBOKbQwHm14wcY5FYgTzi5CHewMPZytO9aIHuj3MY53sF5s3M0S94EFV5bdiLeshQdgdGwc9T0IJC1VROHs4EHSgHY1XKflaFXQQ6y2MpIVIiSYDStgRLOvN/sDDCSImmv7cxaWVuu5z0LxJKU+Y1M9LE4GHOrsWnkXUDx3a5mRR8zRXFsisj5IeiBc0cmPkRxZMBY0BIGeRLIYmJ8smnLDmVuiL5ngWxksUd5JhVqYEzxTv4I1tiSc9Y38OSTgOZwnki0GYhe55Pg1VqjCUnORLf2SWAVb5fIeYPRJ/4JnoFa1THSATTyT3BcQ++f+8DKRwGN299Hltr/+zdWCZRACZRACZSAlEAJDifwRwPBP3uIUqBEg356EvzjmcCf//wFVbAkwfl+5CMAAAAASUVORK5CYII=</Image>
+<Url type="application/x-suggestions+json" method="GET" template="https://dsb.wikipedia.org/w/api.php">
+ <Param name="action" value="opensearch"/>
+ <Param name="search" value="{searchTerms}"/>
+</Url>
+<Url type="text/html" method="GET" template="https://dsb.wikipedia.org/wiki/Specialne:Pytaś">
+ <Param name="search" value="{searchTerms}"/>
+ <Param name="sourceid" value="Mozilla-search"/>
+</Url>
+<SearchForm>https://dsb.wikipedia.org/wiki/Specialne:Pytaś</SearchForm>
+</SearchPlugin>
diff --git a/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-el.xml b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-el.xml
new file mode 100644
index 0000000000..db902d9813
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-el.xml
@@ -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/. -->
+
+<SearchPlugin xmlns="http://www.mozilla.org/2006/browser/search/">
+<ShortName>Βικιπαίδεια (el)</ShortName>
+<InputEncoding>UTF-8</InputEncoding>
+<Image width="16" height="16">data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGAAAABgCAMAAADVRocKAAAA51BMVEUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD////7+/vl5eWxsbH9/f3Ly8tzc3P39/fe3t5cXFzz8/Pt7e3i4uI3NzcaGhoHBwcFBQX5+fnIyMhTU1MXFxcMDAzx8fHX19fFxcXCwsK7u7u1tbWenp6WlpZ8fHxXV1ctLS319fXn5+fV1dWsrKySkpJnZ2cgICDv7+/p6eng4ODQ0NC9vb24uLikpKSPj4+JiYmCgoJiYmJCQkI7OzsyMjIpKSkQEBCoqKigoKCdnZ14eHhubm5PT09LS0tERETk5OTb29unp6c0NDQkJCQOGD7BAAAAB3RSTlMA8si8ZBhlc+JuAAAAAw1JREFUaN7tmtluIjEQRYEhUxd6YYew7xAggRAgCQmB7Ov8//eM3Zg2nXkJvUjz4POAVEbyQXaVy0gOMaKRMAVAOBINcY5+UWD8OmKCIOaXhlDoNwVKNBShQImEwhQo4RAFjBIogRIogRIogRIoQWCCYXqaHJVaWrtl1IfpYp3GiczFqLHQ5kY9m0l0qVM8Txrs+8ZomkhSKpbOzlraolSP15o/EtxoU9gk2iZVujM7HnVe6eUhKaL4aYrWXWMXfd7+dIlScWxpbsjibQiLPm255sH5jYjKOoCEecge5LcTxqokuItZv5F2DID0iR21ALwctslfunNCurKEBRJkgBTZdIDOoVl0CU7FjgsZHpsi+gNoJGlisDlUkC+C8SQHejzOiqCLgXRTNYazw+vg8tsaHZ+DMd7ZlyR5Qix/uOAEgGOhlzy+EPLMMUmyOHVTyQ0wDBlXB2Dw1FzreCZJGfhyIyiDs/qWSEkiarNPxxaX3J1FWcCRLJXidtFW7MO5lmV3AhMMPS8HHsH4oBJmtEcHF+ROUEgD2E/AiVXO98AtSaoJmC4F1AUjXZAD97Bo0R491ApuBRNdVq/FGhz9hPaI48p9w1mI6rVpi1qQ9FmRuRe8iTPaJgfOi6NaTr20zDoYJUfOM2aOHM15EYwBOKbQwHm14wcY5FYgTzi5CHewMPZytO9aIHuj3MY53sF5s3M0S94EFV5bdiLeshQdgdGwc9T0IJC1VROHs4EHSgHY1XKflaFXQQ6y2MpIVIiSYDStgRLOvN/sDDCSImmv7cxaWVuu5z0LxJKU+Y1M9LE4GHOrsWnkXUDx3a5mRR8zRXFsisj5IeiBc0cmPkRxZMBY0BIGeRLIYmJ8smnLDmVuiL5ngWxksUd5JhVqYEzxTv4I1tiSc9Y38OSTgOZwnki0GYhe55Pg1VqjCUnORLf2SWAVb5fIeYPRJ/4JnoFa1THSATTyT3BcQ++f+8DKRwGN299Hltr/+zdWCZRACZRACZSAlEAJDifwRwPBP3uIUqBEg356EvzjmcCf//wFVbAkwfl+5CMAAAAASUVORK5CYII=</Image>
+<Url type="application/x-suggestions+json" method="GET" template="https://el.wikipedia.org/w/api.php">
+ <Param name="action" value="opensearch"/>
+ <Param name="search" value="{searchTerms}"/>
+</Url>
+<Url type="text/html" method="GET" template="https://el.wikipedia.org/wiki/Ειδικό:Αναζήτηση">
+ <Param name="search" value="{searchTerms}"/>
+ <Param name="sourceid" value="Mozilla-search"/>
+</Url>
+<SearchForm>https://el.wikipedia.org/wiki/Ειδικό:Αναζήτηση</SearchForm>
+</SearchPlugin>
diff --git a/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-eo.xml b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-eo.xml
new file mode 100644
index 0000000000..b42dd74658
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-eo.xml
@@ -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/. -->
+
+<SearchPlugin xmlns="http://www.mozilla.org/2006/browser/search/">
+<ShortName>Vikipedio (eo)</ShortName>
+<InputEncoding>UTF-8</InputEncoding>
+<Image width="16" height="16">data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGAAAABgCAMAAADVRocKAAAA51BMVEUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD////7+/vl5eWxsbH9/f3Ly8tzc3P39/fe3t5cXFzz8/Pt7e3i4uI3NzcaGhoHBwcFBQX5+fnIyMhTU1MXFxcMDAzx8fHX19fFxcXCwsK7u7u1tbWenp6WlpZ8fHxXV1ctLS319fXn5+fV1dWsrKySkpJnZ2cgICDv7+/p6eng4ODQ0NC9vb24uLikpKSPj4+JiYmCgoJiYmJCQkI7OzsyMjIpKSkQEBCoqKigoKCdnZ14eHhubm5PT09LS0tERETk5OTb29unp6c0NDQkJCQOGD7BAAAAB3RSTlMA8si8ZBhlc+JuAAAAAw1JREFUaN7tmtluIjEQRYEhUxd6YYew7xAggRAgCQmB7Ov8//eM3Zg2nXkJvUjz4POAVEbyQXaVy0gOMaKRMAVAOBINcY5+UWD8OmKCIOaXhlDoNwVKNBShQImEwhQo4RAFjBIogRIogRIogRIoQWCCYXqaHJVaWrtl1IfpYp3GiczFqLHQ5kY9m0l0qVM8Txrs+8ZomkhSKpbOzlraolSP15o/EtxoU9gk2iZVujM7HnVe6eUhKaL4aYrWXWMXfd7+dIlScWxpbsjibQiLPm255sH5jYjKOoCEecge5LcTxqokuItZv5F2DID0iR21ALwctslfunNCurKEBRJkgBTZdIDOoVl0CU7FjgsZHpsi+gNoJGlisDlUkC+C8SQHejzOiqCLgXRTNYazw+vg8tsaHZ+DMd7ZlyR5Qix/uOAEgGOhlzy+EPLMMUmyOHVTyQ0wDBlXB2Dw1FzreCZJGfhyIyiDs/qWSEkiarNPxxaX3J1FWcCRLJXidtFW7MO5lmV3AhMMPS8HHsH4oBJmtEcHF+ROUEgD2E/AiVXO98AtSaoJmC4F1AUjXZAD97Bo0R491ApuBRNdVq/FGhz9hPaI48p9w1mI6rVpi1qQ9FmRuRe8iTPaJgfOi6NaTr20zDoYJUfOM2aOHM15EYwBOKbQwHm14wcY5FYgTzi5CHewMPZytO9aIHuj3MY53sF5s3M0S94EFV5bdiLeshQdgdGwc9T0IJC1VROHs4EHSgHY1XKflaFXQQ6y2MpIVIiSYDStgRLOvN/sDDCSImmv7cxaWVuu5z0LxJKU+Y1M9LE4GHOrsWnkXUDx3a5mRR8zRXFsisj5IeiBc0cmPkRxZMBY0BIGeRLIYmJ8smnLDmVuiL5ngWxksUd5JhVqYEzxTv4I1tiSc9Y38OSTgOZwnki0GYhe55Pg1VqjCUnORLf2SWAVb5fIeYPRJ/4JnoFa1THSATTyT3BcQ++f+8DKRwGN299Hltr/+zdWCZRACZRACZSAlEAJDifwRwPBP3uIUqBEg356EvzjmcCf//wFVbAkwfl+5CMAAAAASUVORK5CYII=</Image>
+<Url type="application/x-suggestions+json" method="GET" template="https://eo.wikipedia.org/w/api.php">
+ <Param name="action" value="opensearch"/>
+ <Param name="search" value="{searchTerms}"/>
+</Url>
+<Url type="text/html" method="GET" template="https://eo.wikipedia.org/wiki/Specialaĵo:Serĉi">
+ <Param name="search" value="{searchTerms}"/>
+ <Param name="sourceid" value="Mozilla-search"/>
+</Url>
+<SearchForm>https://eo.wikipedia.org/wiki/Specialaĵo:Serĉi</SearchForm>
+</SearchPlugin>
diff --git a/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-es.xml b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-es.xml
new file mode 100644
index 0000000000..41dac576b7
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-es.xml
@@ -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/. -->
+
+<SearchPlugin xmlns="http://www.mozilla.org/2006/browser/search/">
+<ShortName>Wikipedia (es)</ShortName>
+<InputEncoding>UTF-8</InputEncoding>
+<Image width="16" height="16">data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGAAAABgCAMAAADVRocKAAAA51BMVEUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD////7+/vl5eWxsbH9/f3Ly8tzc3P39/fe3t5cXFzz8/Pt7e3i4uI3NzcaGhoHBwcFBQX5+fnIyMhTU1MXFxcMDAzx8fHX19fFxcXCwsK7u7u1tbWenp6WlpZ8fHxXV1ctLS319fXn5+fV1dWsrKySkpJnZ2cgICDv7+/p6eng4ODQ0NC9vb24uLikpKSPj4+JiYmCgoJiYmJCQkI7OzsyMjIpKSkQEBCoqKigoKCdnZ14eHhubm5PT09LS0tERETk5OTb29unp6c0NDQkJCQOGD7BAAAAB3RSTlMA8si8ZBhlc+JuAAAAAw1JREFUaN7tmtluIjEQRYEhUxd6YYew7xAggRAgCQmB7Ov8//eM3Zg2nXkJvUjz4POAVEbyQXaVy0gOMaKRMAVAOBINcY5+UWD8OmKCIOaXhlDoNwVKNBShQImEwhQo4RAFjBIogRIogRIogRIoQWCCYXqaHJVaWrtl1IfpYp3GiczFqLHQ5kY9m0l0qVM8Txrs+8ZomkhSKpbOzlraolSP15o/EtxoU9gk2iZVujM7HnVe6eUhKaL4aYrWXWMXfd7+dIlScWxpbsjibQiLPm255sH5jYjKOoCEecge5LcTxqokuItZv5F2DID0iR21ALwctslfunNCurKEBRJkgBTZdIDOoVl0CU7FjgsZHpsi+gNoJGlisDlUkC+C8SQHejzOiqCLgXRTNYazw+vg8tsaHZ+DMd7ZlyR5Qix/uOAEgGOhlzy+EPLMMUmyOHVTyQ0wDBlXB2Dw1FzreCZJGfhyIyiDs/qWSEkiarNPxxaX3J1FWcCRLJXidtFW7MO5lmV3AhMMPS8HHsH4oBJmtEcHF+ROUEgD2E/AiVXO98AtSaoJmC4F1AUjXZAD97Bo0R491ApuBRNdVq/FGhz9hPaI48p9w1mI6rVpi1qQ9FmRuRe8iTPaJgfOi6NaTr20zDoYJUfOM2aOHM15EYwBOKbQwHm14wcY5FYgTzi5CHewMPZytO9aIHuj3MY53sF5s3M0S94EFV5bdiLeshQdgdGwc9T0IJC1VROHs4EHSgHY1XKflaFXQQ6y2MpIVIiSYDStgRLOvN/sDDCSImmv7cxaWVuu5z0LxJKU+Y1M9LE4GHOrsWnkXUDx3a5mRR8zRXFsisj5IeiBc0cmPkRxZMBY0BIGeRLIYmJ8smnLDmVuiL5ngWxksUd5JhVqYEzxTv4I1tiSc9Y38OSTgOZwnki0GYhe55Pg1VqjCUnORLf2SWAVb5fIeYPRJ/4JnoFa1THSATTyT3BcQ++f+8DKRwGN299Hltr/+zdWCZRACZRACZSAlEAJDifwRwPBP3uIUqBEg356EvzjmcCf//wFVbAkwfl+5CMAAAAASUVORK5CYII=</Image>
+<Url type="application/x-suggestions+json" method="GET" template="https://es.wikipedia.org/w/api.php">
+ <Param name="action" value="opensearch"/>
+ <Param name="search" value="{searchTerms}"/>
+</Url>
+<Url type="text/html" method="GET" template="https://es.wikipedia.org/wiki/Especial:Buscar">
+ <Param name="search" value="{searchTerms}"/>
+ <Param name="sourceid" value="Mozilla-search"/>
+</Url>
+<SearchForm>https://es.wikipedia.org/wiki/Especial:Buscar</SearchForm>
+</SearchPlugin>
diff --git a/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-et.xml b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-et.xml
new file mode 100644
index 0000000000..c499e90397
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-et.xml
@@ -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/. -->
+
+<SearchPlugin xmlns="http://www.mozilla.org/2006/browser/search/">
+<ShortName>Vikipeedia (et)</ShortName>
+<InputEncoding>UTF-8</InputEncoding>
+<Image width="16" height="16">data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGAAAABgCAMAAADVRocKAAAA51BMVEUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD////7+/vl5eWxsbH9/f3Ly8tzc3P39/fe3t5cXFzz8/Pt7e3i4uI3NzcaGhoHBwcFBQX5+fnIyMhTU1MXFxcMDAzx8fHX19fFxcXCwsK7u7u1tbWenp6WlpZ8fHxXV1ctLS319fXn5+fV1dWsrKySkpJnZ2cgICDv7+/p6eng4ODQ0NC9vb24uLikpKSPj4+JiYmCgoJiYmJCQkI7OzsyMjIpKSkQEBCoqKigoKCdnZ14eHhubm5PT09LS0tERETk5OTb29unp6c0NDQkJCQOGD7BAAAAB3RSTlMA8si8ZBhlc+JuAAAAAw1JREFUaN7tmtluIjEQRYEhUxd6YYew7xAggRAgCQmB7Ov8//eM3Zg2nXkJvUjz4POAVEbyQXaVy0gOMaKRMAVAOBINcY5+UWD8OmKCIOaXhlDoNwVKNBShQImEwhQo4RAFjBIogRIogRIogRIoQWCCYXqaHJVaWrtl1IfpYp3GiczFqLHQ5kY9m0l0qVM8Txrs+8ZomkhSKpbOzlraolSP15o/EtxoU9gk2iZVujM7HnVe6eUhKaL4aYrWXWMXfd7+dIlScWxpbsjibQiLPm255sH5jYjKOoCEecge5LcTxqokuItZv5F2DID0iR21ALwctslfunNCurKEBRJkgBTZdIDOoVl0CU7FjgsZHpsi+gNoJGlisDlUkC+C8SQHejzOiqCLgXRTNYazw+vg8tsaHZ+DMd7ZlyR5Qix/uOAEgGOhlzy+EPLMMUmyOHVTyQ0wDBlXB2Dw1FzreCZJGfhyIyiDs/qWSEkiarNPxxaX3J1FWcCRLJXidtFW7MO5lmV3AhMMPS8HHsH4oBJmtEcHF+ROUEgD2E/AiVXO98AtSaoJmC4F1AUjXZAD97Bo0R491ApuBRNdVq/FGhz9hPaI48p9w1mI6rVpi1qQ9FmRuRe8iTPaJgfOi6NaTr20zDoYJUfOM2aOHM15EYwBOKbQwHm14wcY5FYgTzi5CHewMPZytO9aIHuj3MY53sF5s3M0S94EFV5bdiLeshQdgdGwc9T0IJC1VROHs4EHSgHY1XKflaFXQQ6y2MpIVIiSYDStgRLOvN/sDDCSImmv7cxaWVuu5z0LxJKU+Y1M9LE4GHOrsWnkXUDx3a5mRR8zRXFsisj5IeiBc0cmPkRxZMBY0BIGeRLIYmJ8smnLDmVuiL5ngWxksUd5JhVqYEzxTv4I1tiSc9Y38OSTgOZwnki0GYhe55Pg1VqjCUnORLf2SWAVb5fIeYPRJ/4JnoFa1THSATTyT3BcQ++f+8DKRwGN299Hltr/+zdWCZRACZRACZSAlEAJDifwRwPBP3uIUqBEg356EvzjmcCf//wFVbAkwfl+5CMAAAAASUVORK5CYII=</Image>
+<Url type="application/x-suggestions+json" method="GET" template="https://et.wikipedia.org/w/api.php">
+ <Param name="action" value="opensearch"/>
+ <Param name="search" value="{searchTerms}"/>
+</Url>
+<Url type="text/html" method="GET" template="https://et.wikipedia.org/wiki/Eri:Otsimine">
+ <Param name="search" value="{searchTerms}"/>
+ <Param name="sourceid" value="Mozilla-search"/>
+</Url>
+<SearchForm>https://et.wikipedia.org/wiki/Eri:Otsimine</SearchForm>
+</SearchPlugin>
diff --git a/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-eu.xml b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-eu.xml
new file mode 100644
index 0000000000..9928360286
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-eu.xml
@@ -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/. -->
+
+<SearchPlugin xmlns="http://www.mozilla.org/2006/browser/search/">
+<ShortName>Wikipedia (eu)</ShortName>
+<InputEncoding>UTF-8</InputEncoding>
+<Image width="16" height="16">data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGAAAABgCAMAAADVRocKAAAA51BMVEUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD////7+/vl5eWxsbH9/f3Ly8tzc3P39/fe3t5cXFzz8/Pt7e3i4uI3NzcaGhoHBwcFBQX5+fnIyMhTU1MXFxcMDAzx8fHX19fFxcXCwsK7u7u1tbWenp6WlpZ8fHxXV1ctLS319fXn5+fV1dWsrKySkpJnZ2cgICDv7+/p6eng4ODQ0NC9vb24uLikpKSPj4+JiYmCgoJiYmJCQkI7OzsyMjIpKSkQEBCoqKigoKCdnZ14eHhubm5PT09LS0tERETk5OTb29unp6c0NDQkJCQOGD7BAAAAB3RSTlMA8si8ZBhlc+JuAAAAAw1JREFUaN7tmtluIjEQRYEhUxd6YYew7xAggRAgCQmB7Ov8//eM3Zg2nXkJvUjz4POAVEbyQXaVy0gOMaKRMAVAOBINcY5+UWD8OmKCIOaXhlDoNwVKNBShQImEwhQo4RAFjBIogRIogRIogRIoQWCCYXqaHJVaWrtl1IfpYp3GiczFqLHQ5kY9m0l0qVM8Txrs+8ZomkhSKpbOzlraolSP15o/EtxoU9gk2iZVujM7HnVe6eUhKaL4aYrWXWMXfd7+dIlScWxpbsjibQiLPm255sH5jYjKOoCEecge5LcTxqokuItZv5F2DID0iR21ALwctslfunNCurKEBRJkgBTZdIDOoVl0CU7FjgsZHpsi+gNoJGlisDlUkC+C8SQHejzOiqCLgXRTNYazw+vg8tsaHZ+DMd7ZlyR5Qix/uOAEgGOhlzy+EPLMMUmyOHVTyQ0wDBlXB2Dw1FzreCZJGfhyIyiDs/qWSEkiarNPxxaX3J1FWcCRLJXidtFW7MO5lmV3AhMMPS8HHsH4oBJmtEcHF+ROUEgD2E/AiVXO98AtSaoJmC4F1AUjXZAD97Bo0R491ApuBRNdVq/FGhz9hPaI48p9w1mI6rVpi1qQ9FmRuRe8iTPaJgfOi6NaTr20zDoYJUfOM2aOHM15EYwBOKbQwHm14wcY5FYgTzi5CHewMPZytO9aIHuj3MY53sF5s3M0S94EFV5bdiLeshQdgdGwc9T0IJC1VROHs4EHSgHY1XKflaFXQQ6y2MpIVIiSYDStgRLOvN/sDDCSImmv7cxaWVuu5z0LxJKU+Y1M9LE4GHOrsWnkXUDx3a5mRR8zRXFsisj5IeiBc0cmPkRxZMBY0BIGeRLIYmJ8smnLDmVuiL5ngWxksUd5JhVqYEzxTv4I1tiSc9Y38OSTgOZwnki0GYhe55Pg1VqjCUnORLf2SWAVb5fIeYPRJ/4JnoFa1THSATTyT3BcQ++f+8DKRwGN299Hltr/+zdWCZRACZRACZSAlEAJDifwRwPBP3uIUqBEg356EvzjmcCf//wFVbAkwfl+5CMAAAAASUVORK5CYII=</Image>
+<Url type="application/x-suggestions+json" method="GET" template="https://eu.wikipedia.org/w/api.php">
+ <Param name="action" value="opensearch"/>
+ <Param name="search" value="{searchTerms}"/>
+</Url>
+<Url type="text/html" method="GET" template="https://eu.wikipedia.org/wiki/Berezi:Bilatu">
+ <Param name="search" value="{searchTerms}"/>
+ <Param name="sourceid" value="Mozilla-search"/>
+</Url>
+<SearchForm>https://eu.wikipedia.org/wiki/Berezi:Bilatu</SearchForm>
+</SearchPlugin>
diff --git a/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-fa.xml b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-fa.xml
new file mode 100644
index 0000000000..757c4cc575
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-fa.xml
@@ -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/. -->
+
+<SearchPlugin xmlns="http://www.mozilla.org/2006/browser/search/">
+<ShortName>ویکی‌پدیا (fa)</ShortName>
+<InputEncoding>UTF-8</InputEncoding>
+<Image width="16" height="16">data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGAAAABgCAMAAADVRocKAAAA51BMVEUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD////7+/vl5eWxsbH9/f3Ly8tzc3P39/fe3t5cXFzz8/Pt7e3i4uI3NzcaGhoHBwcFBQX5+fnIyMhTU1MXFxcMDAzx8fHX19fFxcXCwsK7u7u1tbWenp6WlpZ8fHxXV1ctLS319fXn5+fV1dWsrKySkpJnZ2cgICDv7+/p6eng4ODQ0NC9vb24uLikpKSPj4+JiYmCgoJiYmJCQkI7OzsyMjIpKSkQEBCoqKigoKCdnZ14eHhubm5PT09LS0tERETk5OTb29unp6c0NDQkJCQOGD7BAAAAB3RSTlMA8si8ZBhlc+JuAAAAAw1JREFUaN7tmtluIjEQRYEhUxd6YYew7xAggRAgCQmB7Ov8//eM3Zg2nXkJvUjz4POAVEbyQXaVy0gOMaKRMAVAOBINcY5+UWD8OmKCIOaXhlDoNwVKNBShQImEwhQo4RAFjBIogRIogRIogRIoQWCCYXqaHJVaWrtl1IfpYp3GiczFqLHQ5kY9m0l0qVM8Txrs+8ZomkhSKpbOzlraolSP15o/EtxoU9gk2iZVujM7HnVe6eUhKaL4aYrWXWMXfd7+dIlScWxpbsjibQiLPm255sH5jYjKOoCEecge5LcTxqokuItZv5F2DID0iR21ALwctslfunNCurKEBRJkgBTZdIDOoVl0CU7FjgsZHpsi+gNoJGlisDlUkC+C8SQHejzOiqCLgXRTNYazw+vg8tsaHZ+DMd7ZlyR5Qix/uOAEgGOhlzy+EPLMMUmyOHVTyQ0wDBlXB2Dw1FzreCZJGfhyIyiDs/qWSEkiarNPxxaX3J1FWcCRLJXidtFW7MO5lmV3AhMMPS8HHsH4oBJmtEcHF+ROUEgD2E/AiVXO98AtSaoJmC4F1AUjXZAD97Bo0R491ApuBRNdVq/FGhz9hPaI48p9w1mI6rVpi1qQ9FmRuRe8iTPaJgfOi6NaTr20zDoYJUfOM2aOHM15EYwBOKbQwHm14wcY5FYgTzi5CHewMPZytO9aIHuj3MY53sF5s3M0S94EFV5bdiLeshQdgdGwc9T0IJC1VROHs4EHSgHY1XKflaFXQQ6y2MpIVIiSYDStgRLOvN/sDDCSImmv7cxaWVuu5z0LxJKU+Y1M9LE4GHOrsWnkXUDx3a5mRR8zRXFsisj5IeiBc0cmPkRxZMBY0BIGeRLIYmJ8smnLDmVuiL5ngWxksUd5JhVqYEzxTv4I1tiSc9Y38OSTgOZwnki0GYhe55Pg1VqjCUnORLf2SWAVb5fIeYPRJ/4JnoFa1THSATTyT3BcQ++f+8DKRwGN299Hltr/+zdWCZRACZRACZSAlEAJDifwRwPBP3uIUqBEg356EvzjmcCf//wFVbAkwfl+5CMAAAAASUVORK5CYII=</Image>
+<Url type="application/x-suggestions+json" method="GET" template="https://fa.wikipedia.org/w/api.php">
+ <Param name="action" value="opensearch"/>
+ <Param name="search" value="{searchTerms}"/>
+</Url>
+<Url type="text/html" method="GET" template="https://fa.wikipedia.org/wiki/ویژه:جستجو">
+ <Param name="search" value="{searchTerms}"/>
+ <Param name="sourceid" value="Mozilla-search"/>
+</Url>
+<SearchForm>https://fa.wikipedia.org/wiki/ویژه:جستجو</SearchForm>
+</SearchPlugin>
diff --git a/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-fi.xml b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-fi.xml
new file mode 100644
index 0000000000..2612d72193
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-fi.xml
@@ -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/. -->
+
+<SearchPlugin xmlns="http://www.mozilla.org/2006/browser/search/">
+<ShortName>Wikipedia (fi)</ShortName>
+<InputEncoding>UTF-8</InputEncoding>
+<Image width="16" height="16">data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGAAAABgCAMAAADVRocKAAAA51BMVEUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD////7+/vl5eWxsbH9/f3Ly8tzc3P39/fe3t5cXFzz8/Pt7e3i4uI3NzcaGhoHBwcFBQX5+fnIyMhTU1MXFxcMDAzx8fHX19fFxcXCwsK7u7u1tbWenp6WlpZ8fHxXV1ctLS319fXn5+fV1dWsrKySkpJnZ2cgICDv7+/p6eng4ODQ0NC9vb24uLikpKSPj4+JiYmCgoJiYmJCQkI7OzsyMjIpKSkQEBCoqKigoKCdnZ14eHhubm5PT09LS0tERETk5OTb29unp6c0NDQkJCQOGD7BAAAAB3RSTlMA8si8ZBhlc+JuAAAAAw1JREFUaN7tmtluIjEQRYEhUxd6YYew7xAggRAgCQmB7Ov8//eM3Zg2nXkJvUjz4POAVEbyQXaVy0gOMaKRMAVAOBINcY5+UWD8OmKCIOaXhlDoNwVKNBShQImEwhQo4RAFjBIogRIogRIogRIoQWCCYXqaHJVaWrtl1IfpYp3GiczFqLHQ5kY9m0l0qVM8Txrs+8ZomkhSKpbOzlraolSP15o/EtxoU9gk2iZVujM7HnVe6eUhKaL4aYrWXWMXfd7+dIlScWxpbsjibQiLPm255sH5jYjKOoCEecge5LcTxqokuItZv5F2DID0iR21ALwctslfunNCurKEBRJkgBTZdIDOoVl0CU7FjgsZHpsi+gNoJGlisDlUkC+C8SQHejzOiqCLgXRTNYazw+vg8tsaHZ+DMd7ZlyR5Qix/uOAEgGOhlzy+EPLMMUmyOHVTyQ0wDBlXB2Dw1FzreCZJGfhyIyiDs/qWSEkiarNPxxaX3J1FWcCRLJXidtFW7MO5lmV3AhMMPS8HHsH4oBJmtEcHF+ROUEgD2E/AiVXO98AtSaoJmC4F1AUjXZAD97Bo0R491ApuBRNdVq/FGhz9hPaI48p9w1mI6rVpi1qQ9FmRuRe8iTPaJgfOi6NaTr20zDoYJUfOM2aOHM15EYwBOKbQwHm14wcY5FYgTzi5CHewMPZytO9aIHuj3MY53sF5s3M0S94EFV5bdiLeshQdgdGwc9T0IJC1VROHs4EHSgHY1XKflaFXQQ6y2MpIVIiSYDStgRLOvN/sDDCSImmv7cxaWVuu5z0LxJKU+Y1M9LE4GHOrsWnkXUDx3a5mRR8zRXFsisj5IeiBc0cmPkRxZMBY0BIGeRLIYmJ8smnLDmVuiL5ngWxksUd5JhVqYEzxTv4I1tiSc9Y38OSTgOZwnki0GYhe55Pg1VqjCUnORLf2SWAVb5fIeYPRJ/4JnoFa1THSATTyT3BcQ++f+8DKRwGN299Hltr/+zdWCZRACZRACZSAlEAJDifwRwPBP3uIUqBEg356EvzjmcCf//wFVbAkwfl+5CMAAAAASUVORK5CYII=</Image>
+<Url type="application/x-suggestions+json" method="GET" template="https://fi.wikipedia.org/w/api.php">
+ <Param name="action" value="opensearch"/>
+ <Param name="search" value="{searchTerms}"/>
+</Url>
+<Url type="text/html" method="GET" template="https://fi.wikipedia.org/wiki/Toiminnot:Haku">
+ <Param name="search" value="{searchTerms}"/>
+ <Param name="sourceid" value="Mozilla-search"/>
+</Url>
+<SearchForm>https://fi.wikipedia.org/wiki/Toiminnot:Haku</SearchForm>
+</SearchPlugin>
diff --git a/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-fr.xml b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-fr.xml
new file mode 100644
index 0000000000..6f44da1fff
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-fr.xml
@@ -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/. -->
+
+<SearchPlugin xmlns="http://www.mozilla.org/2006/browser/search/">
+<ShortName>Wikipédia (fr)</ShortName>
+<InputEncoding>UTF-8</InputEncoding>
+<Image width="16" height="16">data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGAAAABgCAMAAADVRocKAAAA51BMVEUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD////7+/vl5eWxsbH9/f3Ly8tzc3P39/fe3t5cXFzz8/Pt7e3i4uI3NzcaGhoHBwcFBQX5+fnIyMhTU1MXFxcMDAzx8fHX19fFxcXCwsK7u7u1tbWenp6WlpZ8fHxXV1ctLS319fXn5+fV1dWsrKySkpJnZ2cgICDv7+/p6eng4ODQ0NC9vb24uLikpKSPj4+JiYmCgoJiYmJCQkI7OzsyMjIpKSkQEBCoqKigoKCdnZ14eHhubm5PT09LS0tERETk5OTb29unp6c0NDQkJCQOGD7BAAAAB3RSTlMA8si8ZBhlc+JuAAAAAw1JREFUaN7tmtluIjEQRYEhUxd6YYew7xAggRAgCQmB7Ov8//eM3Zg2nXkJvUjz4POAVEbyQXaVy0gOMaKRMAVAOBINcY5+UWD8OmKCIOaXhlDoNwVKNBShQImEwhQo4RAFjBIogRIogRIogRIoQWCCYXqaHJVaWrtl1IfpYp3GiczFqLHQ5kY9m0l0qVM8Txrs+8ZomkhSKpbOzlraolSP15o/EtxoU9gk2iZVujM7HnVe6eUhKaL4aYrWXWMXfd7+dIlScWxpbsjibQiLPm255sH5jYjKOoCEecge5LcTxqokuItZv5F2DID0iR21ALwctslfunNCurKEBRJkgBTZdIDOoVl0CU7FjgsZHpsi+gNoJGlisDlUkC+C8SQHejzOiqCLgXRTNYazw+vg8tsaHZ+DMd7ZlyR5Qix/uOAEgGOhlzy+EPLMMUmyOHVTyQ0wDBlXB2Dw1FzreCZJGfhyIyiDs/qWSEkiarNPxxaX3J1FWcCRLJXidtFW7MO5lmV3AhMMPS8HHsH4oBJmtEcHF+ROUEgD2E/AiVXO98AtSaoJmC4F1AUjXZAD97Bo0R491ApuBRNdVq/FGhz9hPaI48p9w1mI6rVpi1qQ9FmRuRe8iTPaJgfOi6NaTr20zDoYJUfOM2aOHM15EYwBOKbQwHm14wcY5FYgTzi5CHewMPZytO9aIHuj3MY53sF5s3M0S94EFV5bdiLeshQdgdGwc9T0IJC1VROHs4EHSgHY1XKflaFXQQ6y2MpIVIiSYDStgRLOvN/sDDCSImmv7cxaWVuu5z0LxJKU+Y1M9LE4GHOrsWnkXUDx3a5mRR8zRXFsisj5IeiBc0cmPkRxZMBY0BIGeRLIYmJ8smnLDmVuiL5ngWxksUd5JhVqYEzxTv4I1tiSc9Y38OSTgOZwnki0GYhe55Pg1VqjCUnORLf2SWAVb5fIeYPRJ/4JnoFa1THSATTyT3BcQ++f+8DKRwGN299Hltr/+zdWCZRACZRACZSAlEAJDifwRwPBP3uIUqBEg356EvzjmcCf//wFVbAkwfl+5CMAAAAASUVORK5CYII=</Image>
+<Url type="application/x-suggestions+json" method="GET" template="https://fr.wikipedia.org/w/api.php">
+ <Param name="action" value="opensearch"/>
+ <Param name="search" value="{searchTerms}"/>
+</Url>
+<Url type="text/html" method="GET" template="https://fr.wikipedia.org/wiki/Spécial:Recherche">
+ <Param name="search" value="{searchTerms}"/>
+ <Param name="sourceid" value="Mozilla-search"/>
+</Url>
+<SearchForm>https://fr.wikipedia.org/wiki/Spécial:Recherche</SearchForm>
+</SearchPlugin>
diff --git a/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-fy-NL.xml b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-fy-NL.xml
new file mode 100644
index 0000000000..9bfb0a97a0
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-fy-NL.xml
@@ -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/. -->
+
+<SearchPlugin xmlns="http://www.mozilla.org/2006/browser/search/">
+<ShortName>Wikipedia (fy)</ShortName>
+<InputEncoding>UTF-8</InputEncoding>
+<Image width="16" height="16">data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGAAAABgCAMAAADVRocKAAAA51BMVEUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD////7+/vl5eWxsbH9/f3Ly8tzc3P39/fe3t5cXFzz8/Pt7e3i4uI3NzcaGhoHBwcFBQX5+fnIyMhTU1MXFxcMDAzx8fHX19fFxcXCwsK7u7u1tbWenp6WlpZ8fHxXV1ctLS319fXn5+fV1dWsrKySkpJnZ2cgICDv7+/p6eng4ODQ0NC9vb24uLikpKSPj4+JiYmCgoJiYmJCQkI7OzsyMjIpKSkQEBCoqKigoKCdnZ14eHhubm5PT09LS0tERETk5OTb29unp6c0NDQkJCQOGD7BAAAAB3RSTlMA8si8ZBhlc+JuAAAAAw1JREFUaN7tmtluIjEQRYEhUxd6YYew7xAggRAgCQmB7Ov8//eM3Zg2nXkJvUjz4POAVEbyQXaVy0gOMaKRMAVAOBINcY5+UWD8OmKCIOaXhlDoNwVKNBShQImEwhQo4RAFjBIogRIogRIogRIoQWCCYXqaHJVaWrtl1IfpYp3GiczFqLHQ5kY9m0l0qVM8Txrs+8ZomkhSKpbOzlraolSP15o/EtxoU9gk2iZVujM7HnVe6eUhKaL4aYrWXWMXfd7+dIlScWxpbsjibQiLPm255sH5jYjKOoCEecge5LcTxqokuItZv5F2DID0iR21ALwctslfunNCurKEBRJkgBTZdIDOoVl0CU7FjgsZHpsi+gNoJGlisDlUkC+C8SQHejzOiqCLgXRTNYazw+vg8tsaHZ+DMd7ZlyR5Qix/uOAEgGOhlzy+EPLMMUmyOHVTyQ0wDBlXB2Dw1FzreCZJGfhyIyiDs/qWSEkiarNPxxaX3J1FWcCRLJXidtFW7MO5lmV3AhMMPS8HHsH4oBJmtEcHF+ROUEgD2E/AiVXO98AtSaoJmC4F1AUjXZAD97Bo0R491ApuBRNdVq/FGhz9hPaI48p9w1mI6rVpi1qQ9FmRuRe8iTPaJgfOi6NaTr20zDoYJUfOM2aOHM15EYwBOKbQwHm14wcY5FYgTzi5CHewMPZytO9aIHuj3MY53sF5s3M0S94EFV5bdiLeshQdgdGwc9T0IJC1VROHs4EHSgHY1XKflaFXQQ6y2MpIVIiSYDStgRLOvN/sDDCSImmv7cxaWVuu5z0LxJKU+Y1M9LE4GHOrsWnkXUDx3a5mRR8zRXFsisj5IeiBc0cmPkRxZMBY0BIGeRLIYmJ8smnLDmVuiL5ngWxksUd5JhVqYEzxTv4I1tiSc9Y38OSTgOZwnki0GYhe55Pg1VqjCUnORLf2SWAVb5fIeYPRJ/4JnoFa1THSATTyT3BcQ++f+8DKRwGN299Hltr/+zdWCZRACZRACZSAlEAJDifwRwPBP3uIUqBEg356EvzjmcCf//wFVbAkwfl+5CMAAAAASUVORK5CYII=</Image>
+<Url type="application/x-suggestions+json" method="GET" template="https://fy.wikipedia.org/w/api.php">
+ <Param name="action" value="opensearch"/>
+ <Param name="search" value="{searchTerms}"/>
+</Url>
+<Url type="text/html" method="GET" template="https://fy.wikipedia.org/wiki/Wiki:Sykje">
+ <Param name="search" value="{searchTerms}"/>
+ <Param name="sourceid" value="Mozilla-search"/>
+</Url>
+<SearchForm>https://fy.wikipedia.org/wiki/Wiki:Sykje</SearchForm>
+</SearchPlugin>
diff --git a/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-ga-IE.xml b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-ga-IE.xml
new file mode 100644
index 0000000000..d954b45615
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-ga-IE.xml
@@ -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/. -->
+
+<SearchPlugin xmlns="http://www.mozilla.org/2006/browser/search/">
+<ShortName>Vicipéid (ga)</ShortName>
+<InputEncoding>UTF-8</InputEncoding>
+<Image width="16" height="16">data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGAAAABgCAMAAADVRocKAAAA51BMVEUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD////7+/vl5eWxsbH9/f3Ly8tzc3P39/fe3t5cXFzz8/Pt7e3i4uI3NzcaGhoHBwcFBQX5+fnIyMhTU1MXFxcMDAzx8fHX19fFxcXCwsK7u7u1tbWenp6WlpZ8fHxXV1ctLS319fXn5+fV1dWsrKySkpJnZ2cgICDv7+/p6eng4ODQ0NC9vb24uLikpKSPj4+JiYmCgoJiYmJCQkI7OzsyMjIpKSkQEBCoqKigoKCdnZ14eHhubm5PT09LS0tERETk5OTb29unp6c0NDQkJCQOGD7BAAAAB3RSTlMA8si8ZBhlc+JuAAAAAw1JREFUaN7tmtluIjEQRYEhUxd6YYew7xAggRAgCQmB7Ov8//eM3Zg2nXkJvUjz4POAVEbyQXaVy0gOMaKRMAVAOBINcY5+UWD8OmKCIOaXhlDoNwVKNBShQImEwhQo4RAFjBIogRIogRIogRIoQWCCYXqaHJVaWrtl1IfpYp3GiczFqLHQ5kY9m0l0qVM8Txrs+8ZomkhSKpbOzlraolSP15o/EtxoU9gk2iZVujM7HnVe6eUhKaL4aYrWXWMXfd7+dIlScWxpbsjibQiLPm255sH5jYjKOoCEecge5LcTxqokuItZv5F2DID0iR21ALwctslfunNCurKEBRJkgBTZdIDOoVl0CU7FjgsZHpsi+gNoJGlisDlUkC+C8SQHejzOiqCLgXRTNYazw+vg8tsaHZ+DMd7ZlyR5Qix/uOAEgGOhlzy+EPLMMUmyOHVTyQ0wDBlXB2Dw1FzreCZJGfhyIyiDs/qWSEkiarNPxxaX3J1FWcCRLJXidtFW7MO5lmV3AhMMPS8HHsH4oBJmtEcHF+ROUEgD2E/AiVXO98AtSaoJmC4F1AUjXZAD97Bo0R491ApuBRNdVq/FGhz9hPaI48p9w1mI6rVpi1qQ9FmRuRe8iTPaJgfOi6NaTr20zDoYJUfOM2aOHM15EYwBOKbQwHm14wcY5FYgTzi5CHewMPZytO9aIHuj3MY53sF5s3M0S94EFV5bdiLeshQdgdGwc9T0IJC1VROHs4EHSgHY1XKflaFXQQ6y2MpIVIiSYDStgRLOvN/sDDCSImmv7cxaWVuu5z0LxJKU+Y1M9LE4GHOrsWnkXUDx3a5mRR8zRXFsisj5IeiBc0cmPkRxZMBY0BIGeRLIYmJ8smnLDmVuiL5ngWxksUd5JhVqYEzxTv4I1tiSc9Y38OSTgOZwnki0GYhe55Pg1VqjCUnORLf2SWAVb5fIeYPRJ/4JnoFa1THSATTyT3BcQ++f+8DKRwGN299Hltr/+zdWCZRACZRACZSAlEAJDifwRwPBP3uIUqBEg356EvzjmcCf//wFVbAkwfl+5CMAAAAASUVORK5CYII=</Image>
+<Url type="application/x-suggestions+json" method="GET" template="https://ga.wikipedia.org/w/api.php">
+ <Param name="action" value="opensearch"/>
+ <Param name="search" value="{searchTerms}"/>
+</Url>
+<Url type="text/html" method="GET" template="https://ga.wikipedia.org/wiki/Speisialta:Search">
+ <Param name="search" value="{searchTerms}"/>
+ <Param name="sourceid" value="Mozilla-search"/>
+</Url>
+<SearchForm>https://ga.wikipedia.org/wiki/Speisialta:Search</SearchForm>
+</SearchPlugin>
diff --git a/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-gd.xml b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-gd.xml
new file mode 100644
index 0000000000..4b87ed7450
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-gd.xml
@@ -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/. -->
+
+<SearchPlugin xmlns="http://www.mozilla.org/2006/browser/search/">
+<ShortName>Wikipedia (gd)</ShortName>
+<InputEncoding>UTF-8</InputEncoding>
+<Image width="16" height="16">data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGAAAABgCAMAAADVRocKAAAA51BMVEUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD////7+/vl5eWxsbH9/f3Ly8tzc3P39/fe3t5cXFzz8/Pt7e3i4uI3NzcaGhoHBwcFBQX5+fnIyMhTU1MXFxcMDAzx8fHX19fFxcXCwsK7u7u1tbWenp6WlpZ8fHxXV1ctLS319fXn5+fV1dWsrKySkpJnZ2cgICDv7+/p6eng4ODQ0NC9vb24uLikpKSPj4+JiYmCgoJiYmJCQkI7OzsyMjIpKSkQEBCoqKigoKCdnZ14eHhubm5PT09LS0tERETk5OTb29unp6c0NDQkJCQOGD7BAAAAB3RSTlMA8si8ZBhlc+JuAAAAAw1JREFUaN7tmtluIjEQRYEhUxd6YYew7xAggRAgCQmB7Ov8//eM3Zg2nXkJvUjz4POAVEbyQXaVy0gOMaKRMAVAOBINcY5+UWD8OmKCIOaXhlDoNwVKNBShQImEwhQo4RAFjBIogRIogRIogRIoQWCCYXqaHJVaWrtl1IfpYp3GiczFqLHQ5kY9m0l0qVM8Txrs+8ZomkhSKpbOzlraolSP15o/EtxoU9gk2iZVujM7HnVe6eUhKaL4aYrWXWMXfd7+dIlScWxpbsjibQiLPm255sH5jYjKOoCEecge5LcTxqokuItZv5F2DID0iR21ALwctslfunNCurKEBRJkgBTZdIDOoVl0CU7FjgsZHpsi+gNoJGlisDlUkC+C8SQHejzOiqCLgXRTNYazw+vg8tsaHZ+DMd7ZlyR5Qix/uOAEgGOhlzy+EPLMMUmyOHVTyQ0wDBlXB2Dw1FzreCZJGfhyIyiDs/qWSEkiarNPxxaX3J1FWcCRLJXidtFW7MO5lmV3AhMMPS8HHsH4oBJmtEcHF+ROUEgD2E/AiVXO98AtSaoJmC4F1AUjXZAD97Bo0R491ApuBRNdVq/FGhz9hPaI48p9w1mI6rVpi1qQ9FmRuRe8iTPaJgfOi6NaTr20zDoYJUfOM2aOHM15EYwBOKbQwHm14wcY5FYgTzi5CHewMPZytO9aIHuj3MY53sF5s3M0S94EFV5bdiLeshQdgdGwc9T0IJC1VROHs4EHSgHY1XKflaFXQQ6y2MpIVIiSYDStgRLOvN/sDDCSImmv7cxaWVuu5z0LxJKU+Y1M9LE4GHOrsWnkXUDx3a5mRR8zRXFsisj5IeiBc0cmPkRxZMBY0BIGeRLIYmJ8smnLDmVuiL5ngWxksUd5JhVqYEzxTv4I1tiSc9Y38OSTgOZwnki0GYhe55Pg1VqjCUnORLf2SWAVb5fIeYPRJ/4JnoFa1THSATTyT3BcQ++f+8DKRwGN299Hltr/+zdWCZRACZRACZSAlEAJDifwRwPBP3uIUqBEg356EvzjmcCf//wFVbAkwfl+5CMAAAAASUVORK5CYII=</Image>
+<Url type="application/x-suggestions+json" method="GET" template="https://gd.wikipedia.org/w/api.php">
+ <Param name="action" value="opensearch"/>
+ <Param name="search" value="{searchTerms}"/>
+</Url>
+<Url type="text/html" method="GET" template="https://gd.wikipedia.org/wiki/Sònraichte:Search">
+ <Param name="search" value="{searchTerms}"/>
+ <Param name="sourceid" value="Mozilla-search"/>
+</Url>
+<SearchForm>https://gd.wikipedia.org/wiki/Sònraichte:Search</SearchForm>
+</SearchPlugin>
diff --git a/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-gl.xml b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-gl.xml
new file mode 100644
index 0000000000..6b354639dc
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-gl.xml
@@ -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/. -->
+
+<SearchPlugin xmlns="http://www.mozilla.org/2006/browser/search/">
+<ShortName>Wikipedia (gl)</ShortName>
+<InputEncoding>UTF-8</InputEncoding>
+<Image width="16" height="16">data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGAAAABgCAMAAADVRocKAAAA51BMVEUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD////7+/vl5eWxsbH9/f3Ly8tzc3P39/fe3t5cXFzz8/Pt7e3i4uI3NzcaGhoHBwcFBQX5+fnIyMhTU1MXFxcMDAzx8fHX19fFxcXCwsK7u7u1tbWenp6WlpZ8fHxXV1ctLS319fXn5+fV1dWsrKySkpJnZ2cgICDv7+/p6eng4ODQ0NC9vb24uLikpKSPj4+JiYmCgoJiYmJCQkI7OzsyMjIpKSkQEBCoqKigoKCdnZ14eHhubm5PT09LS0tERETk5OTb29unp6c0NDQkJCQOGD7BAAAAB3RSTlMA8si8ZBhlc+JuAAAAAw1JREFUaN7tmtluIjEQRYEhUxd6YYew7xAggRAgCQmB7Ov8//eM3Zg2nXkJvUjz4POAVEbyQXaVy0gOMaKRMAVAOBINcY5+UWD8OmKCIOaXhlDoNwVKNBShQImEwhQo4RAFjBIogRIogRIogRIoQWCCYXqaHJVaWrtl1IfpYp3GiczFqLHQ5kY9m0l0qVM8Txrs+8ZomkhSKpbOzlraolSP15o/EtxoU9gk2iZVujM7HnVe6eUhKaL4aYrWXWMXfd7+dIlScWxpbsjibQiLPm255sH5jYjKOoCEecge5LcTxqokuItZv5F2DID0iR21ALwctslfunNCurKEBRJkgBTZdIDOoVl0CU7FjgsZHpsi+gNoJGlisDlUkC+C8SQHejzOiqCLgXRTNYazw+vg8tsaHZ+DMd7ZlyR5Qix/uOAEgGOhlzy+EPLMMUmyOHVTyQ0wDBlXB2Dw1FzreCZJGfhyIyiDs/qWSEkiarNPxxaX3J1FWcCRLJXidtFW7MO5lmV3AhMMPS8HHsH4oBJmtEcHF+ROUEgD2E/AiVXO98AtSaoJmC4F1AUjXZAD97Bo0R491ApuBRNdVq/FGhz9hPaI48p9w1mI6rVpi1qQ9FmRuRe8iTPaJgfOi6NaTr20zDoYJUfOM2aOHM15EYwBOKbQwHm14wcY5FYgTzi5CHewMPZytO9aIHuj3MY53sF5s3M0S94EFV5bdiLeshQdgdGwc9T0IJC1VROHs4EHSgHY1XKflaFXQQ6y2MpIVIiSYDStgRLOvN/sDDCSImmv7cxaWVuu5z0LxJKU+Y1M9LE4GHOrsWnkXUDx3a5mRR8zRXFsisj5IeiBc0cmPkRxZMBY0BIGeRLIYmJ8smnLDmVuiL5ngWxksUd5JhVqYEzxTv4I1tiSc9Y38OSTgOZwnki0GYhe55Pg1VqjCUnORLf2SWAVb5fIeYPRJ/4JnoFa1THSATTyT3BcQ++f+8DKRwGN299Hltr/+zdWCZRACZRACZSAlEAJDifwRwPBP3uIUqBEg356EvzjmcCf//wFVbAkwfl+5CMAAAAASUVORK5CYII=</Image>
+<Url type="application/x-suggestions+json" method="GET" template="https://gl.wikipedia.org/w/api.php">
+ <Param name="action" value="opensearch"/>
+ <Param name="search" value="{searchTerms}"/>
+</Url>
+<Url type="text/html" method="GET" template="https://gl.wikipedia.org/wiki/Especial:Procurar">
+ <Param name="search" value="{searchTerms}"/>
+ <Param name="sourceid" value="Mozilla-search"/>
+</Url>
+<SearchForm>https://gl.wikipedia.org/wiki/Especial:Procurar</SearchForm>
+</SearchPlugin>
diff --git a/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-gn.xml b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-gn.xml
new file mode 100644
index 0000000000..17a12cf997
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-gn.xml
@@ -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/. -->
+
+<SearchPlugin xmlns="http://www.mozilla.org/2006/browser/search/">
+<ShortName>Vikipetã (gn)</ShortName>
+<InputEncoding>UTF-8</InputEncoding>
+<Image width="16" height="16">data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGAAAABgCAMAAADVRocKAAAA51BMVEUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD////7+/vl5eWxsbH9/f3Ly8tzc3P39/fe3t5cXFzz8/Pt7e3i4uI3NzcaGhoHBwcFBQX5+fnIyMhTU1MXFxcMDAzx8fHX19fFxcXCwsK7u7u1tbWenp6WlpZ8fHxXV1ctLS319fXn5+fV1dWsrKySkpJnZ2cgICDv7+/p6eng4ODQ0NC9vb24uLikpKSPj4+JiYmCgoJiYmJCQkI7OzsyMjIpKSkQEBCoqKigoKCdnZ14eHhubm5PT09LS0tERETk5OTb29unp6c0NDQkJCQOGD7BAAAAB3RSTlMA8si8ZBhlc+JuAAAAAw1JREFUaN7tmtluIjEQRYEhUxd6YYew7xAggRAgCQmB7Ov8//eM3Zg2nXkJvUjz4POAVEbyQXaVy0gOMaKRMAVAOBINcY5+UWD8OmKCIOaXhlDoNwVKNBShQImEwhQo4RAFjBIogRIogRIogRIoQWCCYXqaHJVaWrtl1IfpYp3GiczFqLHQ5kY9m0l0qVM8Txrs+8ZomkhSKpbOzlraolSP15o/EtxoU9gk2iZVujM7HnVe6eUhKaL4aYrWXWMXfd7+dIlScWxpbsjibQiLPm255sH5jYjKOoCEecge5LcTxqokuItZv5F2DID0iR21ALwctslfunNCurKEBRJkgBTZdIDOoVl0CU7FjgsZHpsi+gNoJGlisDlUkC+C8SQHejzOiqCLgXRTNYazw+vg8tsaHZ+DMd7ZlyR5Qix/uOAEgGOhlzy+EPLMMUmyOHVTyQ0wDBlXB2Dw1FzreCZJGfhyIyiDs/qWSEkiarNPxxaX3J1FWcCRLJXidtFW7MO5lmV3AhMMPS8HHsH4oBJmtEcHF+ROUEgD2E/AiVXO98AtSaoJmC4F1AUjXZAD97Bo0R491ApuBRNdVq/FGhz9hPaI48p9w1mI6rVpi1qQ9FmRuRe8iTPaJgfOi6NaTr20zDoYJUfOM2aOHM15EYwBOKbQwHm14wcY5FYgTzi5CHewMPZytO9aIHuj3MY53sF5s3M0S94EFV5bdiLeshQdgdGwc9T0IJC1VROHs4EHSgHY1XKflaFXQQ6y2MpIVIiSYDStgRLOvN/sDDCSImmv7cxaWVuu5z0LxJKU+Y1M9LE4GHOrsWnkXUDx3a5mRR8zRXFsisj5IeiBc0cmPkRxZMBY0BIGeRLIYmJ8smnLDmVuiL5ngWxksUd5JhVqYEzxTv4I1tiSc9Y38OSTgOZwnki0GYhe55Pg1VqjCUnORLf2SWAVb5fIeYPRJ/4JnoFa1THSATTyT3BcQ++f+8DKRwGN299Hltr/+zdWCZRACZRACZSAlEAJDifwRwPBP3uIUqBEg356EvzjmcCf//wFVbAkwfl+5CMAAAAASUVORK5CYII=</Image>
+<Url type="application/x-suggestions+json" method="GET" template="https://gn.wikipedia.org/w/api.php">
+ <Param name="action" value="opensearch"/>
+ <Param name="search" value="{searchTerms}"/>
+</Url>
+<Url type="text/html" method="GET" template="https://gn.wikipedia.org/wiki/Mba'echĩchĩ:Buscar">
+ <Param name="search" value="{searchTerms}"/>
+ <Param name="sourceid" value="Mozilla-search"/>
+</Url>
+<SearchForm>https://gn.wikipedia.org/wiki/Mba'echĩchĩ:Buscar</SearchForm>
+</SearchPlugin>
diff --git a/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-gu.xml b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-gu.xml
new file mode 100644
index 0000000000..0fd505d003
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-gu.xml
@@ -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/. -->
+
+<SearchPlugin xmlns="http://www.mozilla.org/2006/browser/search/">
+<ShortName>વિકિપીડિયા (gu)</ShortName>
+<InputEncoding>UTF-8</InputEncoding>
+<Image width="16" height="16">data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGAAAABgCAMAAADVRocKAAAA51BMVEUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD////7+/vl5eWxsbH9/f3Ly8tzc3P39/fe3t5cXFzz8/Pt7e3i4uI3NzcaGhoHBwcFBQX5+fnIyMhTU1MXFxcMDAzx8fHX19fFxcXCwsK7u7u1tbWenp6WlpZ8fHxXV1ctLS319fXn5+fV1dWsrKySkpJnZ2cgICDv7+/p6eng4ODQ0NC9vb24uLikpKSPj4+JiYmCgoJiYmJCQkI7OzsyMjIpKSkQEBCoqKigoKCdnZ14eHhubm5PT09LS0tERETk5OTb29unp6c0NDQkJCQOGD7BAAAAB3RSTlMA8si8ZBhlc+JuAAAAAw1JREFUaN7tmtluIjEQRYEhUxd6YYew7xAggRAgCQmB7Ov8//eM3Zg2nXkJvUjz4POAVEbyQXaVy0gOMaKRMAVAOBINcY5+UWD8OmKCIOaXhlDoNwVKNBShQImEwhQo4RAFjBIogRIogRIogRIoQWCCYXqaHJVaWrtl1IfpYp3GiczFqLHQ5kY9m0l0qVM8Txrs+8ZomkhSKpbOzlraolSP15o/EtxoU9gk2iZVujM7HnVe6eUhKaL4aYrWXWMXfd7+dIlScWxpbsjibQiLPm255sH5jYjKOoCEecge5LcTxqokuItZv5F2DID0iR21ALwctslfunNCurKEBRJkgBTZdIDOoVl0CU7FjgsZHpsi+gNoJGlisDlUkC+C8SQHejzOiqCLgXRTNYazw+vg8tsaHZ+DMd7ZlyR5Qix/uOAEgGOhlzy+EPLMMUmyOHVTyQ0wDBlXB2Dw1FzreCZJGfhyIyiDs/qWSEkiarNPxxaX3J1FWcCRLJXidtFW7MO5lmV3AhMMPS8HHsH4oBJmtEcHF+ROUEgD2E/AiVXO98AtSaoJmC4F1AUjXZAD97Bo0R491ApuBRNdVq/FGhz9hPaI48p9w1mI6rVpi1qQ9FmRuRe8iTPaJgfOi6NaTr20zDoYJUfOM2aOHM15EYwBOKbQwHm14wcY5FYgTzi5CHewMPZytO9aIHuj3MY53sF5s3M0S94EFV5bdiLeshQdgdGwc9T0IJC1VROHs4EHSgHY1XKflaFXQQ6y2MpIVIiSYDStgRLOvN/sDDCSImmv7cxaWVuu5z0LxJKU+Y1M9LE4GHOrsWnkXUDx3a5mRR8zRXFsisj5IeiBc0cmPkRxZMBY0BIGeRLIYmJ8smnLDmVuiL5ngWxksUd5JhVqYEzxTv4I1tiSc9Y38OSTgOZwnki0GYhe55Pg1VqjCUnORLf2SWAVb5fIeYPRJ/4JnoFa1THSATTyT3BcQ++f+8DKRwGN299Hltr/+zdWCZRACZRACZSAlEAJDifwRwPBP3uIUqBEg356EvzjmcCf//wFVbAkwfl+5CMAAAAASUVORK5CYII=</Image>
+<Url type="application/x-suggestions+json" method="GET" template="https://gu.wikipedia.org/w/api.php">
+ <Param name="action" value="opensearch"/>
+ <Param name="search" value="{searchTerms}"/>
+</Url>
+<Url type="text/html" method="GET" template="https://gu.wikipedia.org/wiki/વિશેષ:શોધ">
+ <Param name="search" value="{searchTerms}"/>
+ <Param name="sourceid" value="Mozilla-search"/>
+</Url>
+<SearchForm>https://gu.wikipedia.org/wiki/વિશેષ:શોધ</SearchForm>
+</SearchPlugin>
diff --git a/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-he.xml b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-he.xml
new file mode 100644
index 0000000000..2611582d7c
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-he.xml
@@ -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/. -->
+
+<SearchPlugin xmlns="http://www.mozilla.org/2006/browser/search/">
+<ShortName>ויקיפדיה</ShortName>
+<InputEncoding>UTF-8</InputEncoding>
+<Image width="16" height="16">data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGAAAABgCAMAAADVRocKAAAA51BMVEUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD////7+/vl5eWxsbH9/f3Ly8tzc3P39/fe3t5cXFzz8/Pt7e3i4uI3NzcaGhoHBwcFBQX5+fnIyMhTU1MXFxcMDAzx8fHX19fFxcXCwsK7u7u1tbWenp6WlpZ8fHxXV1ctLS319fXn5+fV1dWsrKySkpJnZ2cgICDv7+/p6eng4ODQ0NC9vb24uLikpKSPj4+JiYmCgoJiYmJCQkI7OzsyMjIpKSkQEBCoqKigoKCdnZ14eHhubm5PT09LS0tERETk5OTb29unp6c0NDQkJCQOGD7BAAAAB3RSTlMA8si8ZBhlc+JuAAAAAw1JREFUaN7tmtluIjEQRYEhUxd6YYew7xAggRAgCQmB7Ov8//eM3Zg2nXkJvUjz4POAVEbyQXaVy0gOMaKRMAVAOBINcY5+UWD8OmKCIOaXhlDoNwVKNBShQImEwhQo4RAFjBIogRIogRIogRIoQWCCYXqaHJVaWrtl1IfpYp3GiczFqLHQ5kY9m0l0qVM8Txrs+8ZomkhSKpbOzlraolSP15o/EtxoU9gk2iZVujM7HnVe6eUhKaL4aYrWXWMXfd7+dIlScWxpbsjibQiLPm255sH5jYjKOoCEecge5LcTxqokuItZv5F2DID0iR21ALwctslfunNCurKEBRJkgBTZdIDOoVl0CU7FjgsZHpsi+gNoJGlisDlUkC+C8SQHejzOiqCLgXRTNYazw+vg8tsaHZ+DMd7ZlyR5Qix/uOAEgGOhlzy+EPLMMUmyOHVTyQ0wDBlXB2Dw1FzreCZJGfhyIyiDs/qWSEkiarNPxxaX3J1FWcCRLJXidtFW7MO5lmV3AhMMPS8HHsH4oBJmtEcHF+ROUEgD2E/AiVXO98AtSaoJmC4F1AUjXZAD97Bo0R491ApuBRNdVq/FGhz9hPaI48p9w1mI6rVpi1qQ9FmRuRe8iTPaJgfOi6NaTr20zDoYJUfOM2aOHM15EYwBOKbQwHm14wcY5FYgTzi5CHewMPZytO9aIHuj3MY53sF5s3M0S94EFV5bdiLeshQdgdGwc9T0IJC1VROHs4EHSgHY1XKflaFXQQ6y2MpIVIiSYDStgRLOvN/sDDCSImmv7cxaWVuu5z0LxJKU+Y1M9LE4GHOrsWnkXUDx3a5mRR8zRXFsisj5IeiBc0cmPkRxZMBY0BIGeRLIYmJ8smnLDmVuiL5ngWxksUd5JhVqYEzxTv4I1tiSc9Y38OSTgOZwnki0GYhe55Pg1VqjCUnORLf2SWAVb5fIeYPRJ/4JnoFa1THSATTyT3BcQ++f+8DKRwGN299Hltr/+zdWCZRACZRACZSAlEAJDifwRwPBP3uIUqBEg356EvzjmcCf//wFVbAkwfl+5CMAAAAASUVORK5CYII=</Image>
+<Url type="application/x-suggestions+json" method="GET" template="https://he.wikipedia.org/w/api.php">
+ <Param name="action" value="opensearch"/>
+ <Param name="search" value="{searchTerms}"/>
+</Url>
+<Url type="text/html" method="GET" template="https://he.wikipedia.org/wiki/מיוחד:חיפוש">
+ <Param name="search" value="{searchTerms}"/>
+ <Param name="sourceid" value="Mozilla-search"/>
+</Url>
+<SearchForm>https://he.wikipedia.org/wiki/מיוחד:חיפוש</SearchForm>
+</SearchPlugin>
diff --git a/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-hi.xml b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-hi.xml
new file mode 100644
index 0000000000..e3a28a278c
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-hi.xml
@@ -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/. -->
+
+<SearchPlugin xmlns="http://www.mozilla.org/2006/browser/search/">
+<ShortName>विकिपीडिया (hi)</ShortName>
+<InputEncoding>UTF-8</InputEncoding>
+<Image width="16" height="16">data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGAAAABgCAMAAADVRocKAAAA51BMVEUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD////7+/vl5eWxsbH9/f3Ly8tzc3P39/fe3t5cXFzz8/Pt7e3i4uI3NzcaGhoHBwcFBQX5+fnIyMhTU1MXFxcMDAzx8fHX19fFxcXCwsK7u7u1tbWenp6WlpZ8fHxXV1ctLS319fXn5+fV1dWsrKySkpJnZ2cgICDv7+/p6eng4ODQ0NC9vb24uLikpKSPj4+JiYmCgoJiYmJCQkI7OzsyMjIpKSkQEBCoqKigoKCdnZ14eHhubm5PT09LS0tERETk5OTb29unp6c0NDQkJCQOGD7BAAAAB3RSTlMA8si8ZBhlc+JuAAAAAw1JREFUaN7tmtluIjEQRYEhUxd6YYew7xAggRAgCQmB7Ov8//eM3Zg2nXkJvUjz4POAVEbyQXaVy0gOMaKRMAVAOBINcY5+UWD8OmKCIOaXhlDoNwVKNBShQImEwhQo4RAFjBIogRIogRIogRIoQWCCYXqaHJVaWrtl1IfpYp3GiczFqLHQ5kY9m0l0qVM8Txrs+8ZomkhSKpbOzlraolSP15o/EtxoU9gk2iZVujM7HnVe6eUhKaL4aYrWXWMXfd7+dIlScWxpbsjibQiLPm255sH5jYjKOoCEecge5LcTxqokuItZv5F2DID0iR21ALwctslfunNCurKEBRJkgBTZdIDOoVl0CU7FjgsZHpsi+gNoJGlisDlUkC+C8SQHejzOiqCLgXRTNYazw+vg8tsaHZ+DMd7ZlyR5Qix/uOAEgGOhlzy+EPLMMUmyOHVTyQ0wDBlXB2Dw1FzreCZJGfhyIyiDs/qWSEkiarNPxxaX3J1FWcCRLJXidtFW7MO5lmV3AhMMPS8HHsH4oBJmtEcHF+ROUEgD2E/AiVXO98AtSaoJmC4F1AUjXZAD97Bo0R491ApuBRNdVq/FGhz9hPaI48p9w1mI6rVpi1qQ9FmRuRe8iTPaJgfOi6NaTr20zDoYJUfOM2aOHM15EYwBOKbQwHm14wcY5FYgTzi5CHewMPZytO9aIHuj3MY53sF5s3M0S94EFV5bdiLeshQdgdGwc9T0IJC1VROHs4EHSgHY1XKflaFXQQ6y2MpIVIiSYDStgRLOvN/sDDCSImmv7cxaWVuu5z0LxJKU+Y1M9LE4GHOrsWnkXUDx3a5mRR8zRXFsisj5IeiBc0cmPkRxZMBY0BIGeRLIYmJ8smnLDmVuiL5ngWxksUd5JhVqYEzxTv4I1tiSc9Y38OSTgOZwnki0GYhe55Pg1VqjCUnORLf2SWAVb5fIeYPRJ/4JnoFa1THSATTyT3BcQ++f+8DKRwGN299Hltr/+zdWCZRACZRACZSAlEAJDifwRwPBP3uIUqBEg356EvzjmcCf//wFVbAkwfl+5CMAAAAASUVORK5CYII=</Image>
+<Url type="application/x-suggestions+json" method="GET" template="https://hi.wikipedia.org/w/api.php">
+ <Param name="action" value="opensearch"/>
+ <Param name="search" value="{searchTerms}"/>
+</Url>
+<Url type="text/html" method="GET" template="https://hi.wikipedia.org/wiki/विशेष:खोज">
+ <Param name="search" value="{searchTerms}"/>
+ <Param name="sourceid" value="Mozilla-search"/>
+</Url>
+<SearchForm>https://hi.wikipedia.org/wiki/विशेष:खोज</SearchForm>
+</SearchPlugin>
diff --git a/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-hr.xml b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-hr.xml
new file mode 100644
index 0000000000..02e514dbd7
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-hr.xml
@@ -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/. -->
+
+<SearchPlugin xmlns="http://www.mozilla.org/2006/browser/search/">
+<ShortName>Wikipedija (hr)</ShortName>
+<InputEncoding>UTF-8</InputEncoding>
+<Image width="16" height="16">data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGAAAABgCAMAAADVRocKAAAA51BMVEUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD////7+/vl5eWxsbH9/f3Ly8tzc3P39/fe3t5cXFzz8/Pt7e3i4uI3NzcaGhoHBwcFBQX5+fnIyMhTU1MXFxcMDAzx8fHX19fFxcXCwsK7u7u1tbWenp6WlpZ8fHxXV1ctLS319fXn5+fV1dWsrKySkpJnZ2cgICDv7+/p6eng4ODQ0NC9vb24uLikpKSPj4+JiYmCgoJiYmJCQkI7OzsyMjIpKSkQEBCoqKigoKCdnZ14eHhubm5PT09LS0tERETk5OTb29unp6c0NDQkJCQOGD7BAAAAB3RSTlMA8si8ZBhlc+JuAAAAAw1JREFUaN7tmtluIjEQRYEhUxd6YYew7xAggRAgCQmB7Ov8//eM3Zg2nXkJvUjz4POAVEbyQXaVy0gOMaKRMAVAOBINcY5+UWD8OmKCIOaXhlDoNwVKNBShQImEwhQo4RAFjBIogRIogRIogRIoQWCCYXqaHJVaWrtl1IfpYp3GiczFqLHQ5kY9m0l0qVM8Txrs+8ZomkhSKpbOzlraolSP15o/EtxoU9gk2iZVujM7HnVe6eUhKaL4aYrWXWMXfd7+dIlScWxpbsjibQiLPm255sH5jYjKOoCEecge5LcTxqokuItZv5F2DID0iR21ALwctslfunNCurKEBRJkgBTZdIDOoVl0CU7FjgsZHpsi+gNoJGlisDlUkC+C8SQHejzOiqCLgXRTNYazw+vg8tsaHZ+DMd7ZlyR5Qix/uOAEgGOhlzy+EPLMMUmyOHVTyQ0wDBlXB2Dw1FzreCZJGfhyIyiDs/qWSEkiarNPxxaX3J1FWcCRLJXidtFW7MO5lmV3AhMMPS8HHsH4oBJmtEcHF+ROUEgD2E/AiVXO98AtSaoJmC4F1AUjXZAD97Bo0R491ApuBRNdVq/FGhz9hPaI48p9w1mI6rVpi1qQ9FmRuRe8iTPaJgfOi6NaTr20zDoYJUfOM2aOHM15EYwBOKbQwHm14wcY5FYgTzi5CHewMPZytO9aIHuj3MY53sF5s3M0S94EFV5bdiLeshQdgdGwc9T0IJC1VROHs4EHSgHY1XKflaFXQQ6y2MpIVIiSYDStgRLOvN/sDDCSImmv7cxaWVuu5z0LxJKU+Y1M9LE4GHOrsWnkXUDx3a5mRR8zRXFsisj5IeiBc0cmPkRxZMBY0BIGeRLIYmJ8smnLDmVuiL5ngWxksUd5JhVqYEzxTv4I1tiSc9Y38OSTgOZwnki0GYhe55Pg1VqjCUnORLf2SWAVb5fIeYPRJ/4JnoFa1THSATTyT3BcQ++f+8DKRwGN299Hltr/+zdWCZRACZRACZSAlEAJDifwRwPBP3uIUqBEg356EvzjmcCf//wFVbAkwfl+5CMAAAAASUVORK5CYII=</Image>
+<Url type="application/x-suggestions+json" method="GET" template="https://hr.wikipedia.org/w/api.php">
+ <Param name="action" value="opensearch"/>
+ <Param name="search" value="{searchTerms}"/>
+</Url>
+<Url type="text/html" method="GET" template="https://hr.wikipedia.org/wiki/Posebno:Traži">
+ <Param name="search" value="{searchTerms}"/>
+ <Param name="sourceid" value="Mozilla-search"/>
+</Url>
+<SearchForm>https://hr.wikipedia.org/wiki/Posebno:Traži</SearchForm>
+</SearchPlugin>
diff --git a/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-hsb.xml b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-hsb.xml
new file mode 100644
index 0000000000..f72d268f9b
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-hsb.xml
@@ -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/. -->
+
+<SearchPlugin xmlns="http://www.mozilla.org/2006/browser/search/">
+<ShortName>Wikipedija (hsb)</ShortName>
+<InputEncoding>UTF-8</InputEncoding>
+<Image width="16" height="16">data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGAAAABgCAMAAADVRocKAAAA51BMVEUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD////7+/vl5eWxsbH9/f3Ly8tzc3P39/fe3t5cXFzz8/Pt7e3i4uI3NzcaGhoHBwcFBQX5+fnIyMhTU1MXFxcMDAzx8fHX19fFxcXCwsK7u7u1tbWenp6WlpZ8fHxXV1ctLS319fXn5+fV1dWsrKySkpJnZ2cgICDv7+/p6eng4ODQ0NC9vb24uLikpKSPj4+JiYmCgoJiYmJCQkI7OzsyMjIpKSkQEBCoqKigoKCdnZ14eHhubm5PT09LS0tERETk5OTb29unp6c0NDQkJCQOGD7BAAAAB3RSTlMA8si8ZBhlc+JuAAAAAw1JREFUaN7tmtluIjEQRYEhUxd6YYew7xAggRAgCQmB7Ov8//eM3Zg2nXkJvUjz4POAVEbyQXaVy0gOMaKRMAVAOBINcY5+UWD8OmKCIOaXhlDoNwVKNBShQImEwhQo4RAFjBIogRIogRIogRIoQWCCYXqaHJVaWrtl1IfpYp3GiczFqLHQ5kY9m0l0qVM8Txrs+8ZomkhSKpbOzlraolSP15o/EtxoU9gk2iZVujM7HnVe6eUhKaL4aYrWXWMXfd7+dIlScWxpbsjibQiLPm255sH5jYjKOoCEecge5LcTxqokuItZv5F2DID0iR21ALwctslfunNCurKEBRJkgBTZdIDOoVl0CU7FjgsZHpsi+gNoJGlisDlUkC+C8SQHejzOiqCLgXRTNYazw+vg8tsaHZ+DMd7ZlyR5Qix/uOAEgGOhlzy+EPLMMUmyOHVTyQ0wDBlXB2Dw1FzreCZJGfhyIyiDs/qWSEkiarNPxxaX3J1FWcCRLJXidtFW7MO5lmV3AhMMPS8HHsH4oBJmtEcHF+ROUEgD2E/AiVXO98AtSaoJmC4F1AUjXZAD97Bo0R491ApuBRNdVq/FGhz9hPaI48p9w1mI6rVpi1qQ9FmRuRe8iTPaJgfOi6NaTr20zDoYJUfOM2aOHM15EYwBOKbQwHm14wcY5FYgTzi5CHewMPZytO9aIHuj3MY53sF5s3M0S94EFV5bdiLeshQdgdGwc9T0IJC1VROHs4EHSgHY1XKflaFXQQ6y2MpIVIiSYDStgRLOvN/sDDCSImmv7cxaWVuu5z0LxJKU+Y1M9LE4GHOrsWnkXUDx3a5mRR8zRXFsisj5IeiBc0cmPkRxZMBY0BIGeRLIYmJ8smnLDmVuiL5ngWxksUd5JhVqYEzxTv4I1tiSc9Y38OSTgOZwnki0GYhe55Pg1VqjCUnORLf2SWAVb5fIeYPRJ/4JnoFa1THSATTyT3BcQ++f+8DKRwGN299Hltr/+zdWCZRACZRACZSAlEAJDifwRwPBP3uIUqBEg356EvzjmcCf//wFVbAkwfl+5CMAAAAASUVORK5CYII=</Image>
+<Url type="application/x-suggestions+json" method="GET" template="https://hsb.wikipedia.org/w/api.php">
+ <Param name="action" value="opensearch"/>
+ <Param name="search" value="{searchTerms}"/>
+</Url>
+<Url type="text/html" method="GET" template="https://hsb.wikipedia.org/wiki/Specialnje:Pytać">
+ <Param name="search" value="{searchTerms}"/>
+ <Param name="sourceid" value="Mozilla-search"/>
+</Url>
+<SearchForm>https://hsb.wikipedia.org/wiki/Specialnje:Pytać</SearchForm>
+</SearchPlugin>
diff --git a/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-hu.xml b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-hu.xml
new file mode 100644
index 0000000000..7d39f2c500
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-hu.xml
@@ -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/. -->
+
+<SearchPlugin xmlns="http://www.mozilla.org/2006/browser/search/">
+<ShortName>Wikipédia (hu)</ShortName>
+<InputEncoding>UTF-8</InputEncoding>
+<Image width="16" height="16">data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGAAAABgCAMAAADVRocKAAAA51BMVEUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD////7+/vl5eWxsbH9/f3Ly8tzc3P39/fe3t5cXFzz8/Pt7e3i4uI3NzcaGhoHBwcFBQX5+fnIyMhTU1MXFxcMDAzx8fHX19fFxcXCwsK7u7u1tbWenp6WlpZ8fHxXV1ctLS319fXn5+fV1dWsrKySkpJnZ2cgICDv7+/p6eng4ODQ0NC9vb24uLikpKSPj4+JiYmCgoJiYmJCQkI7OzsyMjIpKSkQEBCoqKigoKCdnZ14eHhubm5PT09LS0tERETk5OTb29unp6c0NDQkJCQOGD7BAAAAB3RSTlMA8si8ZBhlc+JuAAAAAw1JREFUaN7tmtluIjEQRYEhUxd6YYew7xAggRAgCQmB7Ov8//eM3Zg2nXkJvUjz4POAVEbyQXaVy0gOMaKRMAVAOBINcY5+UWD8OmKCIOaXhlDoNwVKNBShQImEwhQo4RAFjBIogRIogRIogRIoQWCCYXqaHJVaWrtl1IfpYp3GiczFqLHQ5kY9m0l0qVM8Txrs+8ZomkhSKpbOzlraolSP15o/EtxoU9gk2iZVujM7HnVe6eUhKaL4aYrWXWMXfd7+dIlScWxpbsjibQiLPm255sH5jYjKOoCEecge5LcTxqokuItZv5F2DID0iR21ALwctslfunNCurKEBRJkgBTZdIDOoVl0CU7FjgsZHpsi+gNoJGlisDlUkC+C8SQHejzOiqCLgXRTNYazw+vg8tsaHZ+DMd7ZlyR5Qix/uOAEgGOhlzy+EPLMMUmyOHVTyQ0wDBlXB2Dw1FzreCZJGfhyIyiDs/qWSEkiarNPxxaX3J1FWcCRLJXidtFW7MO5lmV3AhMMPS8HHsH4oBJmtEcHF+ROUEgD2E/AiVXO98AtSaoJmC4F1AUjXZAD97Bo0R491ApuBRNdVq/FGhz9hPaI48p9w1mI6rVpi1qQ9FmRuRe8iTPaJgfOi6NaTr20zDoYJUfOM2aOHM15EYwBOKbQwHm14wcY5FYgTzi5CHewMPZytO9aIHuj3MY53sF5s3M0S94EFV5bdiLeshQdgdGwc9T0IJC1VROHs4EHSgHY1XKflaFXQQ6y2MpIVIiSYDStgRLOvN/sDDCSImmv7cxaWVuu5z0LxJKU+Y1M9LE4GHOrsWnkXUDx3a5mRR8zRXFsisj5IeiBc0cmPkRxZMBY0BIGeRLIYmJ8smnLDmVuiL5ngWxksUd5JhVqYEzxTv4I1tiSc9Y38OSTgOZwnki0GYhe55Pg1VqjCUnORLf2SWAVb5fIeYPRJ/4JnoFa1THSATTyT3BcQ++f+8DKRwGN299Hltr/+zdWCZRACZRACZSAlEAJDifwRwPBP3uIUqBEg356EvzjmcCf//wFVbAkwfl+5CMAAAAASUVORK5CYII=</Image>
+<Url type="application/x-suggestions+json" method="GET" template="https://hu.wikipedia.org/w/api.php">
+ <Param name="action" value="opensearch"/>
+ <Param name="search" value="{searchTerms}"/>
+</Url>
+<Url type="text/html" method="GET" template="https://hu.wikipedia.org/wiki/Speciális:Keresés">
+ <Param name="search" value="{searchTerms}"/>
+ <Param name="sourceid" value="Mozilla-search"/>
+</Url>
+<SearchForm>https://hu.wikipedia.org/wiki/Speciális:Keresés</SearchForm>
+</SearchPlugin>
diff --git a/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-hy-AM.xml b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-hy-AM.xml
new file mode 100644
index 0000000000..bff51bbe49
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-hy-AM.xml
@@ -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/. -->
+
+<SearchPlugin xmlns="http://www.mozilla.org/2006/browser/search/">
+<ShortName>Վիքիպեդիա (hy)</ShortName>
+<InputEncoding>UTF-8</InputEncoding>
+<Image width="16" height="16">data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGAAAABgCAMAAADVRocKAAAA51BMVEUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD////7+/vl5eWxsbH9/f3Ly8tzc3P39/fe3t5cXFzz8/Pt7e3i4uI3NzcaGhoHBwcFBQX5+fnIyMhTU1MXFxcMDAzx8fHX19fFxcXCwsK7u7u1tbWenp6WlpZ8fHxXV1ctLS319fXn5+fV1dWsrKySkpJnZ2cgICDv7+/p6eng4ODQ0NC9vb24uLikpKSPj4+JiYmCgoJiYmJCQkI7OzsyMjIpKSkQEBCoqKigoKCdnZ14eHhubm5PT09LS0tERETk5OTb29unp6c0NDQkJCQOGD7BAAAAB3RSTlMA8si8ZBhlc+JuAAAAAw1JREFUaN7tmtluIjEQRYEhUxd6YYew7xAggRAgCQmB7Ov8//eM3Zg2nXkJvUjz4POAVEbyQXaVy0gOMaKRMAVAOBINcY5+UWD8OmKCIOaXhlDoNwVKNBShQImEwhQo4RAFjBIogRIogRIogRIoQWCCYXqaHJVaWrtl1IfpYp3GiczFqLHQ5kY9m0l0qVM8Txrs+8ZomkhSKpbOzlraolSP15o/EtxoU9gk2iZVujM7HnVe6eUhKaL4aYrWXWMXfd7+dIlScWxpbsjibQiLPm255sH5jYjKOoCEecge5LcTxqokuItZv5F2DID0iR21ALwctslfunNCurKEBRJkgBTZdIDOoVl0CU7FjgsZHpsi+gNoJGlisDlUkC+C8SQHejzOiqCLgXRTNYazw+vg8tsaHZ+DMd7ZlyR5Qix/uOAEgGOhlzy+EPLMMUmyOHVTyQ0wDBlXB2Dw1FzreCZJGfhyIyiDs/qWSEkiarNPxxaX3J1FWcCRLJXidtFW7MO5lmV3AhMMPS8HHsH4oBJmtEcHF+ROUEgD2E/AiVXO98AtSaoJmC4F1AUjXZAD97Bo0R491ApuBRNdVq/FGhz9hPaI48p9w1mI6rVpi1qQ9FmRuRe8iTPaJgfOi6NaTr20zDoYJUfOM2aOHM15EYwBOKbQwHm14wcY5FYgTzi5CHewMPZytO9aIHuj3MY53sF5s3M0S94EFV5bdiLeshQdgdGwc9T0IJC1VROHs4EHSgHY1XKflaFXQQ6y2MpIVIiSYDStgRLOvN/sDDCSImmv7cxaWVuu5z0LxJKU+Y1M9LE4GHOrsWnkXUDx3a5mRR8zRXFsisj5IeiBc0cmPkRxZMBY0BIGeRLIYmJ8smnLDmVuiL5ngWxksUd5JhVqYEzxTv4I1tiSc9Y38OSTgOZwnki0GYhe55Pg1VqjCUnORLf2SWAVb5fIeYPRJ/4JnoFa1THSATTyT3BcQ++f+8DKRwGN299Hltr/+zdWCZRACZRACZSAlEAJDifwRwPBP3uIUqBEg356EvzjmcCf//wFVbAkwfl+5CMAAAAASUVORK5CYII=</Image>
+<Url type="application/x-suggestions+json" method="GET" template="https://hy.wikipedia.org/w/api.php">
+ <Param name="action" value="opensearch"/>
+ <Param name="search" value="{searchTerms}"/>
+</Url>
+<Url type="text/html" method="GET" template="https://hy.wikipedia.org/wiki/Սպասարկող:Որոնել">
+ <Param name="search" value="{searchTerms}"/>
+ <Param name="sourceid" value="Mozilla-search"/>
+</Url>
+<SearchForm>https://hy.wikipedia.org/wiki/Սպասարկող:Որոնել</SearchForm>
+</SearchPlugin>
diff --git a/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-ia.xml b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-ia.xml
new file mode 100644
index 0000000000..4994148c75
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-ia.xml
@@ -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/. -->
+
+<SearchPlugin xmlns="http://www.mozilla.org/2006/browser/search/">
+<ShortName>Wikipedia (ia)</ShortName>
+<InputEncoding>UTF-8</InputEncoding>
+<Image width="16" height="16">data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGAAAABgCAMAAADVRocKAAAA51BMVEUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD////7+/vl5eWxsbH9/f3Ly8tzc3P39/fe3t5cXFzz8/Pt7e3i4uI3NzcaGhoHBwcFBQX5+fnIyMhTU1MXFxcMDAzx8fHX19fFxcXCwsK7u7u1tbWenp6WlpZ8fHxXV1ctLS319fXn5+fV1dWsrKySkpJnZ2cgICDv7+/p6eng4ODQ0NC9vb24uLikpKSPj4+JiYmCgoJiYmJCQkI7OzsyMjIpKSkQEBCoqKigoKCdnZ14eHhubm5PT09LS0tERETk5OTb29unp6c0NDQkJCQOGD7BAAAAB3RSTlMA8si8ZBhlc+JuAAAAAw1JREFUaN7tmtluIjEQRYEhUxd6YYew7xAggRAgCQmB7Ov8//eM3Zg2nXkJvUjz4POAVEbyQXaVy0gOMaKRMAVAOBINcY5+UWD8OmKCIOaXhlDoNwVKNBShQImEwhQo4RAFjBIogRIogRIogRIoQWCCYXqaHJVaWrtl1IfpYp3GiczFqLHQ5kY9m0l0qVM8Txrs+8ZomkhSKpbOzlraolSP15o/EtxoU9gk2iZVujM7HnVe6eUhKaL4aYrWXWMXfd7+dIlScWxpbsjibQiLPm255sH5jYjKOoCEecge5LcTxqokuItZv5F2DID0iR21ALwctslfunNCurKEBRJkgBTZdIDOoVl0CU7FjgsZHpsi+gNoJGlisDlUkC+C8SQHejzOiqCLgXRTNYazw+vg8tsaHZ+DMd7ZlyR5Qix/uOAEgGOhlzy+EPLMMUmyOHVTyQ0wDBlXB2Dw1FzreCZJGfhyIyiDs/qWSEkiarNPxxaX3J1FWcCRLJXidtFW7MO5lmV3AhMMPS8HHsH4oBJmtEcHF+ROUEgD2E/AiVXO98AtSaoJmC4F1AUjXZAD97Bo0R491ApuBRNdVq/FGhz9hPaI48p9w1mI6rVpi1qQ9FmRuRe8iTPaJgfOi6NaTr20zDoYJUfOM2aOHM15EYwBOKbQwHm14wcY5FYgTzi5CHewMPZytO9aIHuj3MY53sF5s3M0S94EFV5bdiLeshQdgdGwc9T0IJC1VROHs4EHSgHY1XKflaFXQQ6y2MpIVIiSYDStgRLOvN/sDDCSImmv7cxaWVuu5z0LxJKU+Y1M9LE4GHOrsWnkXUDx3a5mRR8zRXFsisj5IeiBc0cmPkRxZMBY0BIGeRLIYmJ8smnLDmVuiL5ngWxksUd5JhVqYEzxTv4I1tiSc9Y38OSTgOZwnki0GYhe55Pg1VqjCUnORLf2SWAVb5fIeYPRJ/4JnoFa1THSATTyT3BcQ++f+8DKRwGN299Hltr/+zdWCZRACZRACZSAlEAJDifwRwPBP3uIUqBEg356EvzjmcCf//wFVbAkwfl+5CMAAAAASUVORK5CYII=</Image>
+<Url type="application/x-suggestions+json" method="GET" template="https://ia.wikipedia.org/w/api.php">
+ <Param name="action" value="opensearch"/>
+ <Param name="search" value="{searchTerms}"/>
+</Url>
+<Url type="text/html" method="GET" template="https://ia.wikipedia.org/wiki/Special:Recerca">
+ <Param name="search" value="{searchTerms}"/>
+ <Param name="sourceid" value="Mozilla-search"/>
+</Url>
+<SearchForm>https://ia.wikipedia.org/wiki/Special:Recerca</SearchForm>
+</SearchPlugin>
diff --git a/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-id.xml b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-id.xml
new file mode 100644
index 0000000000..0e82cbcb8f
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-id.xml
@@ -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/. -->
+
+<SearchPlugin xmlns="http://www.mozilla.org/2006/browser/search/">
+<ShortName>Wikipedia (id)</ShortName>
+<InputEncoding>UTF-8</InputEncoding>
+<Image width="16" height="16">data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGAAAABgCAMAAADVRocKAAAA51BMVEUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD////7+/vl5eWxsbH9/f3Ly8tzc3P39/fe3t5cXFzz8/Pt7e3i4uI3NzcaGhoHBwcFBQX5+fnIyMhTU1MXFxcMDAzx8fHX19fFxcXCwsK7u7u1tbWenp6WlpZ8fHxXV1ctLS319fXn5+fV1dWsrKySkpJnZ2cgICDv7+/p6eng4ODQ0NC9vb24uLikpKSPj4+JiYmCgoJiYmJCQkI7OzsyMjIpKSkQEBCoqKigoKCdnZ14eHhubm5PT09LS0tERETk5OTb29unp6c0NDQkJCQOGD7BAAAAB3RSTlMA8si8ZBhlc+JuAAAAAw1JREFUaN7tmtluIjEQRYEhUxd6YYew7xAggRAgCQmB7Ov8//eM3Zg2nXkJvUjz4POAVEbyQXaVy0gOMaKRMAVAOBINcY5+UWD8OmKCIOaXhlDoNwVKNBShQImEwhQo4RAFjBIogRIogRIogRIoQWCCYXqaHJVaWrtl1IfpYp3GiczFqLHQ5kY9m0l0qVM8Txrs+8ZomkhSKpbOzlraolSP15o/EtxoU9gk2iZVujM7HnVe6eUhKaL4aYrWXWMXfd7+dIlScWxpbsjibQiLPm255sH5jYjKOoCEecge5LcTxqokuItZv5F2DID0iR21ALwctslfunNCurKEBRJkgBTZdIDOoVl0CU7FjgsZHpsi+gNoJGlisDlUkC+C8SQHejzOiqCLgXRTNYazw+vg8tsaHZ+DMd7ZlyR5Qix/uOAEgGOhlzy+EPLMMUmyOHVTyQ0wDBlXB2Dw1FzreCZJGfhyIyiDs/qWSEkiarNPxxaX3J1FWcCRLJXidtFW7MO5lmV3AhMMPS8HHsH4oBJmtEcHF+ROUEgD2E/AiVXO98AtSaoJmC4F1AUjXZAD97Bo0R491ApuBRNdVq/FGhz9hPaI48p9w1mI6rVpi1qQ9FmRuRe8iTPaJgfOi6NaTr20zDoYJUfOM2aOHM15EYwBOKbQwHm14wcY5FYgTzi5CHewMPZytO9aIHuj3MY53sF5s3M0S94EFV5bdiLeshQdgdGwc9T0IJC1VROHs4EHSgHY1XKflaFXQQ6y2MpIVIiSYDStgRLOvN/sDDCSImmv7cxaWVuu5z0LxJKU+Y1M9LE4GHOrsWnkXUDx3a5mRR8zRXFsisj5IeiBc0cmPkRxZMBY0BIGeRLIYmJ8smnLDmVuiL5ngWxksUd5JhVqYEzxTv4I1tiSc9Y38OSTgOZwnki0GYhe55Pg1VqjCUnORLf2SWAVb5fIeYPRJ/4JnoFa1THSATTyT3BcQ++f+8DKRwGN299Hltr/+zdWCZRACZRACZSAlEAJDifwRwPBP3uIUqBEg356EvzjmcCf//wFVbAkwfl+5CMAAAAASUVORK5CYII=</Image>
+<Url type="application/x-suggestions+json" method="GET" template="https://id.wikipedia.org/w/api.php">
+ <Param name="action" value="opensearch"/>
+ <Param name="search" value="{searchTerms}"/>
+</Url>
+<Url type="text/html" method="GET" template="https://id.wikipedia.org/wiki/Istimewa:Pencarian">
+ <Param name="search" value="{searchTerms}"/>
+ <Param name="sourceid" value="Mozilla-search"/>
+</Url>
+<SearchForm>https://id.wikipedia.org/wiki/Istimewa:Pencarian</SearchForm>
+</SearchPlugin>
diff --git a/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-is.xml b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-is.xml
new file mode 100644
index 0000000000..093f45cc77
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-is.xml
@@ -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/. -->
+
+<SearchPlugin xmlns="http://www.mozilla.org/2006/browser/search/">
+<ShortName>Wikipedia (is)</ShortName>
+<InputEncoding>UTF-8</InputEncoding>
+<Image width="16" height="16">data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGAAAABgCAMAAADVRocKAAAA51BMVEUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD////7+/vl5eWxsbH9/f3Ly8tzc3P39/fe3t5cXFzz8/Pt7e3i4uI3NzcaGhoHBwcFBQX5+fnIyMhTU1MXFxcMDAzx8fHX19fFxcXCwsK7u7u1tbWenp6WlpZ8fHxXV1ctLS319fXn5+fV1dWsrKySkpJnZ2cgICDv7+/p6eng4ODQ0NC9vb24uLikpKSPj4+JiYmCgoJiYmJCQkI7OzsyMjIpKSkQEBCoqKigoKCdnZ14eHhubm5PT09LS0tERETk5OTb29unp6c0NDQkJCQOGD7BAAAAB3RSTlMA8si8ZBhlc+JuAAAAAw1JREFUaN7tmtluIjEQRYEhUxd6YYew7xAggRAgCQmB7Ov8//eM3Zg2nXkJvUjz4POAVEbyQXaVy0gOMaKRMAVAOBINcY5+UWD8OmKCIOaXhlDoNwVKNBShQImEwhQo4RAFjBIogRIogRIogRIoQWCCYXqaHJVaWrtl1IfpYp3GiczFqLHQ5kY9m0l0qVM8Txrs+8ZomkhSKpbOzlraolSP15o/EtxoU9gk2iZVujM7HnVe6eUhKaL4aYrWXWMXfd7+dIlScWxpbsjibQiLPm255sH5jYjKOoCEecge5LcTxqokuItZv5F2DID0iR21ALwctslfunNCurKEBRJkgBTZdIDOoVl0CU7FjgsZHpsi+gNoJGlisDlUkC+C8SQHejzOiqCLgXRTNYazw+vg8tsaHZ+DMd7ZlyR5Qix/uOAEgGOhlzy+EPLMMUmyOHVTyQ0wDBlXB2Dw1FzreCZJGfhyIyiDs/qWSEkiarNPxxaX3J1FWcCRLJXidtFW7MO5lmV3AhMMPS8HHsH4oBJmtEcHF+ROUEgD2E/AiVXO98AtSaoJmC4F1AUjXZAD97Bo0R491ApuBRNdVq/FGhz9hPaI48p9w1mI6rVpi1qQ9FmRuRe8iTPaJgfOi6NaTr20zDoYJUfOM2aOHM15EYwBOKbQwHm14wcY5FYgTzi5CHewMPZytO9aIHuj3MY53sF5s3M0S94EFV5bdiLeshQdgdGwc9T0IJC1VROHs4EHSgHY1XKflaFXQQ6y2MpIVIiSYDStgRLOvN/sDDCSImmv7cxaWVuu5z0LxJKU+Y1M9LE4GHOrsWnkXUDx3a5mRR8zRXFsisj5IeiBc0cmPkRxZMBY0BIGeRLIYmJ8smnLDmVuiL5ngWxksUd5JhVqYEzxTv4I1tiSc9Y38OSTgOZwnki0GYhe55Pg1VqjCUnORLf2SWAVb5fIeYPRJ/4JnoFa1THSATTyT3BcQ++f+8DKRwGN299Hltr/+zdWCZRACZRACZSAlEAJDifwRwPBP3uIUqBEg356EvzjmcCf//wFVbAkwfl+5CMAAAAASUVORK5CYII=</Image>
+<Url type="application/x-suggestions+json" method="GET" template="https://is.wikipedia.org/w/api.php">
+ <Param name="action" value="opensearch"/>
+ <Param name="search" value="{searchTerms}"/>
+</Url>
+<Url type="text/html" method="GET" template="https://is.wikipedia.org/wiki/Kerfissíða:Leit">
+ <Param name="search" value="{searchTerms}"/>
+ <Param name="sourceid" value="Mozilla-search"/>
+</Url>
+<SearchForm>https://is.wikipedia.org/wiki/Kerfissíða:Leit</SearchForm>
+</SearchPlugin>
diff --git a/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-it.xml b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-it.xml
new file mode 100644
index 0000000000..a04aeb42f8
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-it.xml
@@ -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/. -->
+
+<SearchPlugin xmlns="http://www.mozilla.org/2006/browser/search/">
+<ShortName>Wikipedia (it)</ShortName>
+<InputEncoding>UTF-8</InputEncoding>
+<Image width="16" height="16">data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGAAAABgCAMAAADVRocKAAAA51BMVEUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD////7+/vl5eWxsbH9/f3Ly8tzc3P39/fe3t5cXFzz8/Pt7e3i4uI3NzcaGhoHBwcFBQX5+fnIyMhTU1MXFxcMDAzx8fHX19fFxcXCwsK7u7u1tbWenp6WlpZ8fHxXV1ctLS319fXn5+fV1dWsrKySkpJnZ2cgICDv7+/p6eng4ODQ0NC9vb24uLikpKSPj4+JiYmCgoJiYmJCQkI7OzsyMjIpKSkQEBCoqKigoKCdnZ14eHhubm5PT09LS0tERETk5OTb29unp6c0NDQkJCQOGD7BAAAAB3RSTlMA8si8ZBhlc+JuAAAAAw1JREFUaN7tmtluIjEQRYEhUxd6YYew7xAggRAgCQmB7Ov8//eM3Zg2nXkJvUjz4POAVEbyQXaVy0gOMaKRMAVAOBINcY5+UWD8OmKCIOaXhlDoNwVKNBShQImEwhQo4RAFjBIogRIogRIogRIoQWCCYXqaHJVaWrtl1IfpYp3GiczFqLHQ5kY9m0l0qVM8Txrs+8ZomkhSKpbOzlraolSP15o/EtxoU9gk2iZVujM7HnVe6eUhKaL4aYrWXWMXfd7+dIlScWxpbsjibQiLPm255sH5jYjKOoCEecge5LcTxqokuItZv5F2DID0iR21ALwctslfunNCurKEBRJkgBTZdIDOoVl0CU7FjgsZHpsi+gNoJGlisDlUkC+C8SQHejzOiqCLgXRTNYazw+vg8tsaHZ+DMd7ZlyR5Qix/uOAEgGOhlzy+EPLMMUmyOHVTyQ0wDBlXB2Dw1FzreCZJGfhyIyiDs/qWSEkiarNPxxaX3J1FWcCRLJXidtFW7MO5lmV3AhMMPS8HHsH4oBJmtEcHF+ROUEgD2E/AiVXO98AtSaoJmC4F1AUjXZAD97Bo0R491ApuBRNdVq/FGhz9hPaI48p9w1mI6rVpi1qQ9FmRuRe8iTPaJgfOi6NaTr20zDoYJUfOM2aOHM15EYwBOKbQwHm14wcY5FYgTzi5CHewMPZytO9aIHuj3MY53sF5s3M0S94EFV5bdiLeshQdgdGwc9T0IJC1VROHs4EHSgHY1XKflaFXQQ6y2MpIVIiSYDStgRLOvN/sDDCSImmv7cxaWVuu5z0LxJKU+Y1M9LE4GHOrsWnkXUDx3a5mRR8zRXFsisj5IeiBc0cmPkRxZMBY0BIGeRLIYmJ8smnLDmVuiL5ngWxksUd5JhVqYEzxTv4I1tiSc9Y38OSTgOZwnki0GYhe55Pg1VqjCUnORLf2SWAVb5fIeYPRJ/4JnoFa1THSATTyT3BcQ++f+8DKRwGN299Hltr/+zdWCZRACZRACZSAlEAJDifwRwPBP3uIUqBEg356EvzjmcCf//wFVbAkwfl+5CMAAAAASUVORK5CYII=</Image>
+<Url type="application/x-suggestions+json" method="GET" template="https://it.wikipedia.org/w/api.php">
+ <Param name="action" value="opensearch"/>
+ <Param name="search" value="{searchTerms}"/>
+</Url>
+<Url type="text/html" method="GET" template="https://it.wikipedia.org/wiki/Speciale:Ricerca">
+ <Param name="search" value="{searchTerms}"/>
+ <Param name="sourceid" value="Mozilla-search"/>
+</Url>
+<SearchForm>https://it.wikipedia.org/wiki/Speciale:Ricerca</SearchForm>
+</SearchPlugin>
diff --git a/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-ja.xml b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-ja.xml
new file mode 100644
index 0000000000..c27327138b
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-ja.xml
@@ -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/. -->
+
+<SearchPlugin xmlns="http://www.mozilla.org/2006/browser/search/">
+<ShortName>Wikipedia (ja)</ShortName>
+<InputEncoding>UTF-8</InputEncoding>
+<Image width="16" height="16">data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGAAAABgCAMAAADVRocKAAAA51BMVEUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD////7+/vl5eWxsbH9/f3Ly8tzc3P39/fe3t5cXFzz8/Pt7e3i4uI3NzcaGhoHBwcFBQX5+fnIyMhTU1MXFxcMDAzx8fHX19fFxcXCwsK7u7u1tbWenp6WlpZ8fHxXV1ctLS319fXn5+fV1dWsrKySkpJnZ2cgICDv7+/p6eng4ODQ0NC9vb24uLikpKSPj4+JiYmCgoJiYmJCQkI7OzsyMjIpKSkQEBCoqKigoKCdnZ14eHhubm5PT09LS0tERETk5OTb29unp6c0NDQkJCQOGD7BAAAAB3RSTlMA8si8ZBhlc+JuAAAAAw1JREFUaN7tmtluIjEQRYEhUxd6YYew7xAggRAgCQmB7Ov8//eM3Zg2nXkJvUjz4POAVEbyQXaVy0gOMaKRMAVAOBINcY5+UWD8OmKCIOaXhlDoNwVKNBShQImEwhQo4RAFjBIogRIogRIogRIoQWCCYXqaHJVaWrtl1IfpYp3GiczFqLHQ5kY9m0l0qVM8Txrs+8ZomkhSKpbOzlraolSP15o/EtxoU9gk2iZVujM7HnVe6eUhKaL4aYrWXWMXfd7+dIlScWxpbsjibQiLPm255sH5jYjKOoCEecge5LcTxqokuItZv5F2DID0iR21ALwctslfunNCurKEBRJkgBTZdIDOoVl0CU7FjgsZHpsi+gNoJGlisDlUkC+C8SQHejzOiqCLgXRTNYazw+vg8tsaHZ+DMd7ZlyR5Qix/uOAEgGOhlzy+EPLMMUmyOHVTyQ0wDBlXB2Dw1FzreCZJGfhyIyiDs/qWSEkiarNPxxaX3J1FWcCRLJXidtFW7MO5lmV3AhMMPS8HHsH4oBJmtEcHF+ROUEgD2E/AiVXO98AtSaoJmC4F1AUjXZAD97Bo0R491ApuBRNdVq/FGhz9hPaI48p9w1mI6rVpi1qQ9FmRuRe8iTPaJgfOi6NaTr20zDoYJUfOM2aOHM15EYwBOKbQwHm14wcY5FYgTzi5CHewMPZytO9aIHuj3MY53sF5s3M0S94EFV5bdiLeshQdgdGwc9T0IJC1VROHs4EHSgHY1XKflaFXQQ6y2MpIVIiSYDStgRLOvN/sDDCSImmv7cxaWVuu5z0LxJKU+Y1M9LE4GHOrsWnkXUDx3a5mRR8zRXFsisj5IeiBc0cmPkRxZMBY0BIGeRLIYmJ8smnLDmVuiL5ngWxksUd5JhVqYEzxTv4I1tiSc9Y38OSTgOZwnki0GYhe55Pg1VqjCUnORLf2SWAVb5fIeYPRJ/4JnoFa1THSATTyT3BcQ++f+8DKRwGN299Hltr/+zdWCZRACZRACZSAlEAJDifwRwPBP3uIUqBEg356EvzjmcCf//wFVbAkwfl+5CMAAAAASUVORK5CYII=</Image>
+<Url type="application/x-suggestions+json" method="GET" template="https://ja.wikipedia.org/wiki">
+ <Param name="action" value="opensearch"/>
+ <Param name="search" value="{searchTerms}"/>
+</Url>
+<Url type="text/html" method="GET" template="https://ja.wikipedia.org/wiki/特別:検索">
+ <Param name="search" value="{searchTerms}"/>
+ <Param name="sourceid" value="Mozilla-search"/>
+</Url>
+<SearchForm>https://ja.wikipedia.org/wiki/特別:検索</SearchForm>
+</SearchPlugin>
diff --git a/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-ka.xml b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-ka.xml
new file mode 100644
index 0000000000..15afd0174f
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-ka.xml
@@ -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/. -->
+
+<SearchPlugin xmlns="http://www.mozilla.org/2006/browser/search/">
+<ShortName>ვიკიპედია (ka)</ShortName>
+<InputEncoding>UTF-8</InputEncoding>
+<Image width="16" height="16">data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGAAAABgCAMAAADVRocKAAAA51BMVEUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD////7+/vl5eWxsbH9/f3Ly8tzc3P39/fe3t5cXFzz8/Pt7e3i4uI3NzcaGhoHBwcFBQX5+fnIyMhTU1MXFxcMDAzx8fHX19fFxcXCwsK7u7u1tbWenp6WlpZ8fHxXV1ctLS319fXn5+fV1dWsrKySkpJnZ2cgICDv7+/p6eng4ODQ0NC9vb24uLikpKSPj4+JiYmCgoJiYmJCQkI7OzsyMjIpKSkQEBCoqKigoKCdnZ14eHhubm5PT09LS0tERETk5OTb29unp6c0NDQkJCQOGD7BAAAAB3RSTlMA8si8ZBhlc+JuAAAAAw1JREFUaN7tmtluIjEQRYEhUxd6YYew7xAggRAgCQmB7Ov8//eM3Zg2nXkJvUjz4POAVEbyQXaVy0gOMaKRMAVAOBINcY5+UWD8OmKCIOaXhlDoNwVKNBShQImEwhQo4RAFjBIogRIogRIogRIoQWCCYXqaHJVaWrtl1IfpYp3GiczFqLHQ5kY9m0l0qVM8Txrs+8ZomkhSKpbOzlraolSP15o/EtxoU9gk2iZVujM7HnVe6eUhKaL4aYrWXWMXfd7+dIlScWxpbsjibQiLPm255sH5jYjKOoCEecge5LcTxqokuItZv5F2DID0iR21ALwctslfunNCurKEBRJkgBTZdIDOoVl0CU7FjgsZHpsi+gNoJGlisDlUkC+C8SQHejzOiqCLgXRTNYazw+vg8tsaHZ+DMd7ZlyR5Qix/uOAEgGOhlzy+EPLMMUmyOHVTyQ0wDBlXB2Dw1FzreCZJGfhyIyiDs/qWSEkiarNPxxaX3J1FWcCRLJXidtFW7MO5lmV3AhMMPS8HHsH4oBJmtEcHF+ROUEgD2E/AiVXO98AtSaoJmC4F1AUjXZAD97Bo0R491ApuBRNdVq/FGhz9hPaI48p9w1mI6rVpi1qQ9FmRuRe8iTPaJgfOi6NaTr20zDoYJUfOM2aOHM15EYwBOKbQwHm14wcY5FYgTzi5CHewMPZytO9aIHuj3MY53sF5s3M0S94EFV5bdiLeshQdgdGwc9T0IJC1VROHs4EHSgHY1XKflaFXQQ6y2MpIVIiSYDStgRLOvN/sDDCSImmv7cxaWVuu5z0LxJKU+Y1M9LE4GHOrsWnkXUDx3a5mRR8zRXFsisj5IeiBc0cmPkRxZMBY0BIGeRLIYmJ8smnLDmVuiL5ngWxksUd5JhVqYEzxTv4I1tiSc9Y38OSTgOZwnki0GYhe55Pg1VqjCUnORLf2SWAVb5fIeYPRJ/4JnoFa1THSATTyT3BcQ++f+8DKRwGN299Hltr/+zdWCZRACZRACZSAlEAJDifwRwPBP3uIUqBEg356EvzjmcCf//wFVbAkwfl+5CMAAAAASUVORK5CYII=</Image>
+<Url type="application/x-suggestions+json" method="GET" template="https://ka.wikipedia.org/w/api.php">
+ <Param name="action" value="opensearch"/>
+ <Param name="search" value="{searchTerms}"/>
+</Url>
+<Url type="text/html" method="GET" template="https://ka.wikipedia.org/wiki/სპეციალური:ძიება">
+ <Param name="search" value="{searchTerms}"/>
+ <Param name="sourceid" value="Mozilla-search"/>
+</Url>
+<SearchForm>https://ka.wikipedia.org/wiki/სპეციალური:ძიება</SearchForm>
+</SearchPlugin>
diff --git a/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-kab.xml b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-kab.xml
new file mode 100644
index 0000000000..7ef24e7aba
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-kab.xml
@@ -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/. -->
+
+<SearchPlugin xmlns="http://www.mozilla.org/2006/browser/search/">
+<ShortName>Wikipedia (kab)</ShortName>
+<InputEncoding>UTF-8</InputEncoding>
+<Image width="16" height="16">data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGAAAABgCAMAAADVRocKAAAA51BMVEUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD////7+/vl5eWxsbH9/f3Ly8tzc3P39/fe3t5cXFzz8/Pt7e3i4uI3NzcaGhoHBwcFBQX5+fnIyMhTU1MXFxcMDAzx8fHX19fFxcXCwsK7u7u1tbWenp6WlpZ8fHxXV1ctLS319fXn5+fV1dWsrKySkpJnZ2cgICDv7+/p6eng4ODQ0NC9vb24uLikpKSPj4+JiYmCgoJiYmJCQkI7OzsyMjIpKSkQEBCoqKigoKCdnZ14eHhubm5PT09LS0tERETk5OTb29unp6c0NDQkJCQOGD7BAAAAB3RSTlMA8si8ZBhlc+JuAAAAAw1JREFUaN7tmtluIjEQRYEhUxd6YYew7xAggRAgCQmB7Ov8//eM3Zg2nXkJvUjz4POAVEbyQXaVy0gOMaKRMAVAOBINcY5+UWD8OmKCIOaXhlDoNwVKNBShQImEwhQo4RAFjBIogRIogRIogRIoQWCCYXqaHJVaWrtl1IfpYp3GiczFqLHQ5kY9m0l0qVM8Txrs+8ZomkhSKpbOzlraolSP15o/EtxoU9gk2iZVujM7HnVe6eUhKaL4aYrWXWMXfd7+dIlScWxpbsjibQiLPm255sH5jYjKOoCEecge5LcTxqokuItZv5F2DID0iR21ALwctslfunNCurKEBRJkgBTZdIDOoVl0CU7FjgsZHpsi+gNoJGlisDlUkC+C8SQHejzOiqCLgXRTNYazw+vg8tsaHZ+DMd7ZlyR5Qix/uOAEgGOhlzy+EPLMMUmyOHVTyQ0wDBlXB2Dw1FzreCZJGfhyIyiDs/qWSEkiarNPxxaX3J1FWcCRLJXidtFW7MO5lmV3AhMMPS8HHsH4oBJmtEcHF+ROUEgD2E/AiVXO98AtSaoJmC4F1AUjXZAD97Bo0R491ApuBRNdVq/FGhz9hPaI48p9w1mI6rVpi1qQ9FmRuRe8iTPaJgfOi6NaTr20zDoYJUfOM2aOHM15EYwBOKbQwHm14wcY5FYgTzi5CHewMPZytO9aIHuj3MY53sF5s3M0S94EFV5bdiLeshQdgdGwc9T0IJC1VROHs4EHSgHY1XKflaFXQQ6y2MpIVIiSYDStgRLOvN/sDDCSImmv7cxaWVuu5z0LxJKU+Y1M9LE4GHOrsWnkXUDx3a5mRR8zRXFsisj5IeiBc0cmPkRxZMBY0BIGeRLIYmJ8smnLDmVuiL5ngWxksUd5JhVqYEzxTv4I1tiSc9Y38OSTgOZwnki0GYhe55Pg1VqjCUnORLf2SWAVb5fIeYPRJ/4JnoFa1THSATTyT3BcQ++f+8DKRwGN299Hltr/+zdWCZRACZRACZSAlEAJDifwRwPBP3uIUqBEg356EvzjmcCf//wFVbAkwfl+5CMAAAAASUVORK5CYII=</Image>
+<Url type="application/x-suggestions+json" method="GET" template="https://kab.wikipedia.org/w/api.php">
+ <Param name="action" value="opensearch"/>
+ <Param name="search" value="{searchTerms}"/>
+</Url>
+<Url type="text/html" method="GET" template="https://kab.wikipedia.org/wiki/Uslig:Search">
+ <Param name="search" value="{searchTerms}"/>
+ <Param name="sourceid" value="Mozilla-search"/>
+</Url>
+<SearchForm>https://kab.wikipedia.org/wiki/Uslig:Search</SearchForm>
+</SearchPlugin>
diff --git a/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-kk.xml b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-kk.xml
new file mode 100644
index 0000000000..328edd40c0
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-kk.xml
@@ -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/. -->
+
+<SearchPlugin xmlns="http://www.mozilla.org/2006/browser/search/">
+<ShortName>Уикипедия (kk)</ShortName>
+<InputEncoding>UTF-8</InputEncoding>
+<Image width="16" height="16">data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGAAAABgCAMAAADVRocKAAAA51BMVEUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD////7+/vl5eWxsbH9/f3Ly8tzc3P39/fe3t5cXFzz8/Pt7e3i4uI3NzcaGhoHBwcFBQX5+fnIyMhTU1MXFxcMDAzx8fHX19fFxcXCwsK7u7u1tbWenp6WlpZ8fHxXV1ctLS319fXn5+fV1dWsrKySkpJnZ2cgICDv7+/p6eng4ODQ0NC9vb24uLikpKSPj4+JiYmCgoJiYmJCQkI7OzsyMjIpKSkQEBCoqKigoKCdnZ14eHhubm5PT09LS0tERETk5OTb29unp6c0NDQkJCQOGD7BAAAAB3RSTlMA8si8ZBhlc+JuAAAAAw1JREFUaN7tmtluIjEQRYEhUxd6YYew7xAggRAgCQmB7Ov8//eM3Zg2nXkJvUjz4POAVEbyQXaVy0gOMaKRMAVAOBINcY5+UWD8OmKCIOaXhlDoNwVKNBShQImEwhQo4RAFjBIogRIogRIogRIoQWCCYXqaHJVaWrtl1IfpYp3GiczFqLHQ5kY9m0l0qVM8Txrs+8ZomkhSKpbOzlraolSP15o/EtxoU9gk2iZVujM7HnVe6eUhKaL4aYrWXWMXfd7+dIlScWxpbsjibQiLPm255sH5jYjKOoCEecge5LcTxqokuItZv5F2DID0iR21ALwctslfunNCurKEBRJkgBTZdIDOoVl0CU7FjgsZHpsi+gNoJGlisDlUkC+C8SQHejzOiqCLgXRTNYazw+vg8tsaHZ+DMd7ZlyR5Qix/uOAEgGOhlzy+EPLMMUmyOHVTyQ0wDBlXB2Dw1FzreCZJGfhyIyiDs/qWSEkiarNPxxaX3J1FWcCRLJXidtFW7MO5lmV3AhMMPS8HHsH4oBJmtEcHF+ROUEgD2E/AiVXO98AtSaoJmC4F1AUjXZAD97Bo0R491ApuBRNdVq/FGhz9hPaI48p9w1mI6rVpi1qQ9FmRuRe8iTPaJgfOi6NaTr20zDoYJUfOM2aOHM15EYwBOKbQwHm14wcY5FYgTzi5CHewMPZytO9aIHuj3MY53sF5s3M0S94EFV5bdiLeshQdgdGwc9T0IJC1VROHs4EHSgHY1XKflaFXQQ6y2MpIVIiSYDStgRLOvN/sDDCSImmv7cxaWVuu5z0LxJKU+Y1M9LE4GHOrsWnkXUDx3a5mRR8zRXFsisj5IeiBc0cmPkRxZMBY0BIGeRLIYmJ8smnLDmVuiL5ngWxksUd5JhVqYEzxTv4I1tiSc9Y38OSTgOZwnki0GYhe55Pg1VqjCUnORLf2SWAVb5fIeYPRJ/4JnoFa1THSATTyT3BcQ++f+8DKRwGN299Hltr/+zdWCZRACZRACZSAlEAJDifwRwPBP3uIUqBEg356EvzjmcCf//wFVbAkwfl+5CMAAAAASUVORK5CYII=</Image>
+<Url type="application/x-suggestions+json" method="GET" template="https://kk.wikipedia.org/w/api.php">
+ <Param name="action" value="opensearch"/>
+ <Param name="search" value="{searchTerms}"/>
+</Url>
+<Url type="text/html" method="GET" template="https://kk.wikipedia.org/wiki/Арнайы:Іздеу">
+ <Param name="search" value="{searchTerms}"/>
+ <Param name="sourceid" value="Mozilla-search"/>
+</Url>
+<SearchForm>https://kk.wikipedia.org/wiki/Арнайы:Іздеу</SearchForm>
+</SearchPlugin>
diff --git a/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-km.xml b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-km.xml
new file mode 100644
index 0000000000..a69f99b34d
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-km.xml
@@ -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/. -->
+
+<SearchPlugin xmlns="http://www.mozilla.org/2006/browser/search/">
+<ShortName>វិគីភីឌា (km)</ShortName>
+<InputEncoding>UTF-8</InputEncoding>
+<Image width="16" height="16">data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGAAAABgCAMAAADVRocKAAAA51BMVEUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD////7+/vl5eWxsbH9/f3Ly8tzc3P39/fe3t5cXFzz8/Pt7e3i4uI3NzcaGhoHBwcFBQX5+fnIyMhTU1MXFxcMDAzx8fHX19fFxcXCwsK7u7u1tbWenp6WlpZ8fHxXV1ctLS319fXn5+fV1dWsrKySkpJnZ2cgICDv7+/p6eng4ODQ0NC9vb24uLikpKSPj4+JiYmCgoJiYmJCQkI7OzsyMjIpKSkQEBCoqKigoKCdnZ14eHhubm5PT09LS0tERETk5OTb29unp6c0NDQkJCQOGD7BAAAAB3RSTlMA8si8ZBhlc+JuAAAAAw1JREFUaN7tmtluIjEQRYEhUxd6YYew7xAggRAgCQmB7Ov8//eM3Zg2nXkJvUjz4POAVEbyQXaVy0gOMaKRMAVAOBINcY5+UWD8OmKCIOaXhlDoNwVKNBShQImEwhQo4RAFjBIogRIogRIogRIoQWCCYXqaHJVaWrtl1IfpYp3GiczFqLHQ5kY9m0l0qVM8Txrs+8ZomkhSKpbOzlraolSP15o/EtxoU9gk2iZVujM7HnVe6eUhKaL4aYrWXWMXfd7+dIlScWxpbsjibQiLPm255sH5jYjKOoCEecge5LcTxqokuItZv5F2DID0iR21ALwctslfunNCurKEBRJkgBTZdIDOoVl0CU7FjgsZHpsi+gNoJGlisDlUkC+C8SQHejzOiqCLgXRTNYazw+vg8tsaHZ+DMd7ZlyR5Qix/uOAEgGOhlzy+EPLMMUmyOHVTyQ0wDBlXB2Dw1FzreCZJGfhyIyiDs/qWSEkiarNPxxaX3J1FWcCRLJXidtFW7MO5lmV3AhMMPS8HHsH4oBJmtEcHF+ROUEgD2E/AiVXO98AtSaoJmC4F1AUjXZAD97Bo0R491ApuBRNdVq/FGhz9hPaI48p9w1mI6rVpi1qQ9FmRuRe8iTPaJgfOi6NaTr20zDoYJUfOM2aOHM15EYwBOKbQwHm14wcY5FYgTzi5CHewMPZytO9aIHuj3MY53sF5s3M0S94EFV5bdiLeshQdgdGwc9T0IJC1VROHs4EHSgHY1XKflaFXQQ6y2MpIVIiSYDStgRLOvN/sDDCSImmv7cxaWVuu5z0LxJKU+Y1M9LE4GHOrsWnkXUDx3a5mRR8zRXFsisj5IeiBc0cmPkRxZMBY0BIGeRLIYmJ8smnLDmVuiL5ngWxksUd5JhVqYEzxTv4I1tiSc9Y38OSTgOZwnki0GYhe55Pg1VqjCUnORLf2SWAVb5fIeYPRJ/4JnoFa1THSATTyT3BcQ++f+8DKRwGN299Hltr/+zdWCZRACZRACZSAlEAJDifwRwPBP3uIUqBEg356EvzjmcCf//wFVbAkwfl+5CMAAAAASUVORK5CYII=</Image>
+<Url type="application/x-suggestions+json" method="GET" template="https://km.wikipedia.org/w/api.php">
+ <Param name="action" value="opensearch"/>
+ <Param name="search" value="{searchTerms}"/>
+</Url>
+<Url type="text/html" method="GET" template="https://km.wikipedia.org/wiki/ពិសេស:ស្វែងរក">
+ <Param name="search" value="{searchTerms}"/>
+ <Param name="sourceid" value="Mozilla-search"/>
+</Url>
+<SearchForm>https://km.wikipedia.org/wiki/ពិសេស:ស្វែងរក</SearchForm>
+</SearchPlugin>
diff --git a/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-kn.xml b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-kn.xml
new file mode 100644
index 0000000000..155b515fed
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-kn.xml
@@ -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/. -->
+
+<SearchPlugin xmlns="http://www.mozilla.org/2006/browser/search/">
+<ShortName>ವಿಕಿಪೀಡಿಯ (kn)</ShortName>
+<InputEncoding>UTF-8</InputEncoding>
+<Image width="16" height="16">data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGAAAABgCAMAAADVRocKAAAA51BMVEUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD////7+/vl5eWxsbH9/f3Ly8tzc3P39/fe3t5cXFzz8/Pt7e3i4uI3NzcaGhoHBwcFBQX5+fnIyMhTU1MXFxcMDAzx8fHX19fFxcXCwsK7u7u1tbWenp6WlpZ8fHxXV1ctLS319fXn5+fV1dWsrKySkpJnZ2cgICDv7+/p6eng4ODQ0NC9vb24uLikpKSPj4+JiYmCgoJiYmJCQkI7OzsyMjIpKSkQEBCoqKigoKCdnZ14eHhubm5PT09LS0tERETk5OTb29unp6c0NDQkJCQOGD7BAAAAB3RSTlMA8si8ZBhlc+JuAAAAAw1JREFUaN7tmtluIjEQRYEhUxd6YYew7xAggRAgCQmB7Ov8//eM3Zg2nXkJvUjz4POAVEbyQXaVy0gOMaKRMAVAOBINcY5+UWD8OmKCIOaXhlDoNwVKNBShQImEwhQo4RAFjBIogRIogRIogRIoQWCCYXqaHJVaWrtl1IfpYp3GiczFqLHQ5kY9m0l0qVM8Txrs+8ZomkhSKpbOzlraolSP15o/EtxoU9gk2iZVujM7HnVe6eUhKaL4aYrWXWMXfd7+dIlScWxpbsjibQiLPm255sH5jYjKOoCEecge5LcTxqokuItZv5F2DID0iR21ALwctslfunNCurKEBRJkgBTZdIDOoVl0CU7FjgsZHpsi+gNoJGlisDlUkC+C8SQHejzOiqCLgXRTNYazw+vg8tsaHZ+DMd7ZlyR5Qix/uOAEgGOhlzy+EPLMMUmyOHVTyQ0wDBlXB2Dw1FzreCZJGfhyIyiDs/qWSEkiarNPxxaX3J1FWcCRLJXidtFW7MO5lmV3AhMMPS8HHsH4oBJmtEcHF+ROUEgD2E/AiVXO98AtSaoJmC4F1AUjXZAD97Bo0R491ApuBRNdVq/FGhz9hPaI48p9w1mI6rVpi1qQ9FmRuRe8iTPaJgfOi6NaTr20zDoYJUfOM2aOHM15EYwBOKbQwHm14wcY5FYgTzi5CHewMPZytO9aIHuj3MY53sF5s3M0S94EFV5bdiLeshQdgdGwc9T0IJC1VROHs4EHSgHY1XKflaFXQQ6y2MpIVIiSYDStgRLOvN/sDDCSImmv7cxaWVuu5z0LxJKU+Y1M9LE4GHOrsWnkXUDx3a5mRR8zRXFsisj5IeiBc0cmPkRxZMBY0BIGeRLIYmJ8smnLDmVuiL5ngWxksUd5JhVqYEzxTv4I1tiSc9Y38OSTgOZwnki0GYhe55Pg1VqjCUnORLf2SWAVb5fIeYPRJ/4JnoFa1THSATTyT3BcQ++f+8DKRwGN299Hltr/+zdWCZRACZRACZSAlEAJDifwRwPBP3uIUqBEg356EvzjmcCf//wFVbAkwfl+5CMAAAAASUVORK5CYII=</Image>
+<Url type="application/x-suggestions+json" method="GET" template="https://kn.wikipedia.org/w/api.php">
+ <Param name="action" value="opensearch"/>
+ <Param name="search" value="{searchTerms}"/>
+</Url>
+<Url type="text/html" method="GET" template="https://kn.wikipedia.org/wiki/ವಿಶೇಷ:Search">
+ <Param name="search" value="{searchTerms}"/>
+ <Param name="sourceid" value="Mozilla-search"/>
+</Url>
+<SearchForm>https://kn.wikipedia.org/wiki/ವಿಶೇಷ:Search</SearchForm>
+</SearchPlugin>
diff --git a/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-lij.xml b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-lij.xml
new file mode 100644
index 0000000000..1b75c36c79
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-lij.xml
@@ -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/. -->
+
+<SearchPlugin xmlns="http://www.mozilla.org/2006/browser/search/">
+<ShortName>Wikipedia (lij)</ShortName>
+<InputEncoding>UTF-8</InputEncoding>
+<Image width="16" height="16">data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGAAAABgCAMAAADVRocKAAAA51BMVEUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD////7+/vl5eWxsbH9/f3Ly8tzc3P39/fe3t5cXFzz8/Pt7e3i4uI3NzcaGhoHBwcFBQX5+fnIyMhTU1MXFxcMDAzx8fHX19fFxcXCwsK7u7u1tbWenp6WlpZ8fHxXV1ctLS319fXn5+fV1dWsrKySkpJnZ2cgICDv7+/p6eng4ODQ0NC9vb24uLikpKSPj4+JiYmCgoJiYmJCQkI7OzsyMjIpKSkQEBCoqKigoKCdnZ14eHhubm5PT09LS0tERETk5OTb29unp6c0NDQkJCQOGD7BAAAAB3RSTlMA8si8ZBhlc+JuAAAAAw1JREFUaN7tmtluIjEQRYEhUxd6YYew7xAggRAgCQmB7Ov8//eM3Zg2nXkJvUjz4POAVEbyQXaVy0gOMaKRMAVAOBINcY5+UWD8OmKCIOaXhlDoNwVKNBShQImEwhQo4RAFjBIogRIogRIogRIoQWCCYXqaHJVaWrtl1IfpYp3GiczFqLHQ5kY9m0l0qVM8Txrs+8ZomkhSKpbOzlraolSP15o/EtxoU9gk2iZVujM7HnVe6eUhKaL4aYrWXWMXfd7+dIlScWxpbsjibQiLPm255sH5jYjKOoCEecge5LcTxqokuItZv5F2DID0iR21ALwctslfunNCurKEBRJkgBTZdIDOoVl0CU7FjgsZHpsi+gNoJGlisDlUkC+C8SQHejzOiqCLgXRTNYazw+vg8tsaHZ+DMd7ZlyR5Qix/uOAEgGOhlzy+EPLMMUmyOHVTyQ0wDBlXB2Dw1FzreCZJGfhyIyiDs/qWSEkiarNPxxaX3J1FWcCRLJXidtFW7MO5lmV3AhMMPS8HHsH4oBJmtEcHF+ROUEgD2E/AiVXO98AtSaoJmC4F1AUjXZAD97Bo0R491ApuBRNdVq/FGhz9hPaI48p9w1mI6rVpi1qQ9FmRuRe8iTPaJgfOi6NaTr20zDoYJUfOM2aOHM15EYwBOKbQwHm14wcY5FYgTzi5CHewMPZytO9aIHuj3MY53sF5s3M0S94EFV5bdiLeshQdgdGwc9T0IJC1VROHs4EHSgHY1XKflaFXQQ6y2MpIVIiSYDStgRLOvN/sDDCSImmv7cxaWVuu5z0LxJKU+Y1M9LE4GHOrsWnkXUDx3a5mRR8zRXFsisj5IeiBc0cmPkRxZMBY0BIGeRLIYmJ8smnLDmVuiL5ngWxksUd5JhVqYEzxTv4I1tiSc9Y38OSTgOZwnki0GYhe55Pg1VqjCUnORLf2SWAVb5fIeYPRJ/4JnoFa1THSATTyT3BcQ++f+8DKRwGN299Hltr/+zdWCZRACZRACZSAlEAJDifwRwPBP3uIUqBEg356EvzjmcCf//wFVbAkwfl+5CMAAAAASUVORK5CYII=</Image>
+<Url type="application/x-suggestions+json" method="GET" template="https://lij.wikipedia.org/w/api.php">
+ <Param name="action" value="opensearch"/>
+ <Param name="search" value="{searchTerms}"/>
+</Url>
+<Url type="text/html" method="GET" template="https://lij.wikipedia.org/wiki/Speçiale:Riçerca">
+ <Param name="search" value="{searchTerms}"/>
+ <Param name="sourceid" value="Mozilla-search"/>
+</Url>
+<SearchForm>https://lij.wikipedia.org/wiki/Speçiale:Riçerca</SearchForm>
+</SearchPlugin>
diff --git a/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-lo.xml b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-lo.xml
new file mode 100644
index 0000000000..64b236617b
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-lo.xml
@@ -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/. -->
+
+<SearchPlugin xmlns="http://www.mozilla.org/2006/browser/search/">
+<ShortName>ວິກິພີເດຍ (lo)</ShortName>
+<InputEncoding>UTF-8</InputEncoding>
+<Image width="16" height="16">data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGAAAABgCAMAAADVRocKAAAA51BMVEUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD////7+/vl5eWxsbH9/f3Ly8tzc3P39/fe3t5cXFzz8/Pt7e3i4uI3NzcaGhoHBwcFBQX5+fnIyMhTU1MXFxcMDAzx8fHX19fFxcXCwsK7u7u1tbWenp6WlpZ8fHxXV1ctLS319fXn5+fV1dWsrKySkpJnZ2cgICDv7+/p6eng4ODQ0NC9vb24uLikpKSPj4+JiYmCgoJiYmJCQkI7OzsyMjIpKSkQEBCoqKigoKCdnZ14eHhubm5PT09LS0tERETk5OTb29unp6c0NDQkJCQOGD7BAAAAB3RSTlMA8si8ZBhlc+JuAAAAAw1JREFUaN7tmtluIjEQRYEhUxd6YYew7xAggRAgCQmB7Ov8//eM3Zg2nXkJvUjz4POAVEbyQXaVy0gOMaKRMAVAOBINcY5+UWD8OmKCIOaXhlDoNwVKNBShQImEwhQo4RAFjBIogRIogRIogRIoQWCCYXqaHJVaWrtl1IfpYp3GiczFqLHQ5kY9m0l0qVM8Txrs+8ZomkhSKpbOzlraolSP15o/EtxoU9gk2iZVujM7HnVe6eUhKaL4aYrWXWMXfd7+dIlScWxpbsjibQiLPm255sH5jYjKOoCEecge5LcTxqokuItZv5F2DID0iR21ALwctslfunNCurKEBRJkgBTZdIDOoVl0CU7FjgsZHpsi+gNoJGlisDlUkC+C8SQHejzOiqCLgXRTNYazw+vg8tsaHZ+DMd7ZlyR5Qix/uOAEgGOhlzy+EPLMMUmyOHVTyQ0wDBlXB2Dw1FzreCZJGfhyIyiDs/qWSEkiarNPxxaX3J1FWcCRLJXidtFW7MO5lmV3AhMMPS8HHsH4oBJmtEcHF+ROUEgD2E/AiVXO98AtSaoJmC4F1AUjXZAD97Bo0R491ApuBRNdVq/FGhz9hPaI48p9w1mI6rVpi1qQ9FmRuRe8iTPaJgfOi6NaTr20zDoYJUfOM2aOHM15EYwBOKbQwHm14wcY5FYgTzi5CHewMPZytO9aIHuj3MY53sF5s3M0S94EFV5bdiLeshQdgdGwc9T0IJC1VROHs4EHSgHY1XKflaFXQQ6y2MpIVIiSYDStgRLOvN/sDDCSImmv7cxaWVuu5z0LxJKU+Y1M9LE4GHOrsWnkXUDx3a5mRR8zRXFsisj5IeiBc0cmPkRxZMBY0BIGeRLIYmJ8smnLDmVuiL5ngWxksUd5JhVqYEzxTv4I1tiSc9Y38OSTgOZwnki0GYhe55Pg1VqjCUnORLf2SWAVb5fIeYPRJ/4JnoFa1THSATTyT3BcQ++f+8DKRwGN299Hltr/+zdWCZRACZRACZSAlEAJDifwRwPBP3uIUqBEg356EvzjmcCf//wFVbAkwfl+5CMAAAAASUVORK5CYII=</Image>
+<Url type="application/x-suggestions+json" method="GET" template="https://lo.wikipedia.org/w/api.php">
+ <Param name="action" value="opensearch"/>
+ <Param name="search" value="{searchTerms}"/>
+</Url>
+<Url type="text/html" method="GET" template="https://lo.wikipedia.org/wiki/ພິເສດ:ຊອກຫາ">
+ <Param name="search" value="{searchTerms}"/>
+ <Param name="sourceid" value="Mozilla-search"/>
+</Url>
+<SearchForm>https://lo.wikipedia.org/wiki/ພິເສດ:ຊອກຫາ</SearchForm>
+</SearchPlugin>
diff --git a/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-lt.xml b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-lt.xml
new file mode 100644
index 0000000000..8430cb6591
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-lt.xml
@@ -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/. -->
+
+<SearchPlugin xmlns="http://www.mozilla.org/2006/browser/search/">
+<ShortName>Wikipedia (lt)</ShortName>
+<InputEncoding>UTF-8</InputEncoding>
+<Image width="16" height="16">data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGAAAABgCAMAAADVRocKAAAA51BMVEUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD////7+/vl5eWxsbH9/f3Ly8tzc3P39/fe3t5cXFzz8/Pt7e3i4uI3NzcaGhoHBwcFBQX5+fnIyMhTU1MXFxcMDAzx8fHX19fFxcXCwsK7u7u1tbWenp6WlpZ8fHxXV1ctLS319fXn5+fV1dWsrKySkpJnZ2cgICDv7+/p6eng4ODQ0NC9vb24uLikpKSPj4+JiYmCgoJiYmJCQkI7OzsyMjIpKSkQEBCoqKigoKCdnZ14eHhubm5PT09LS0tERETk5OTb29unp6c0NDQkJCQOGD7BAAAAB3RSTlMA8si8ZBhlc+JuAAAAAw1JREFUaN7tmtluIjEQRYEhUxd6YYew7xAggRAgCQmB7Ov8//eM3Zg2nXkJvUjz4POAVEbyQXaVy0gOMaKRMAVAOBINcY5+UWD8OmKCIOaXhlDoNwVKNBShQImEwhQo4RAFjBIogRIogRIogRIoQWCCYXqaHJVaWrtl1IfpYp3GiczFqLHQ5kY9m0l0qVM8Txrs+8ZomkhSKpbOzlraolSP15o/EtxoU9gk2iZVujM7HnVe6eUhKaL4aYrWXWMXfd7+dIlScWxpbsjibQiLPm255sH5jYjKOoCEecge5LcTxqokuItZv5F2DID0iR21ALwctslfunNCurKEBRJkgBTZdIDOoVl0CU7FjgsZHpsi+gNoJGlisDlUkC+C8SQHejzOiqCLgXRTNYazw+vg8tsaHZ+DMd7ZlyR5Qix/uOAEgGOhlzy+EPLMMUmyOHVTyQ0wDBlXB2Dw1FzreCZJGfhyIyiDs/qWSEkiarNPxxaX3J1FWcCRLJXidtFW7MO5lmV3AhMMPS8HHsH4oBJmtEcHF+ROUEgD2E/AiVXO98AtSaoJmC4F1AUjXZAD97Bo0R491ApuBRNdVq/FGhz9hPaI48p9w1mI6rVpi1qQ9FmRuRe8iTPaJgfOi6NaTr20zDoYJUfOM2aOHM15EYwBOKbQwHm14wcY5FYgTzi5CHewMPZytO9aIHuj3MY53sF5s3M0S94EFV5bdiLeshQdgdGwc9T0IJC1VROHs4EHSgHY1XKflaFXQQ6y2MpIVIiSYDStgRLOvN/sDDCSImmv7cxaWVuu5z0LxJKU+Y1M9LE4GHOrsWnkXUDx3a5mRR8zRXFsisj5IeiBc0cmPkRxZMBY0BIGeRLIYmJ8smnLDmVuiL5ngWxksUd5JhVqYEzxTv4I1tiSc9Y38OSTgOZwnki0GYhe55Pg1VqjCUnORLf2SWAVb5fIeYPRJ/4JnoFa1THSATTyT3BcQ++f+8DKRwGN299Hltr/+zdWCZRACZRACZSAlEAJDifwRwPBP3uIUqBEg356EvzjmcCf//wFVbAkwfl+5CMAAAAASUVORK5CYII=</Image>
+<Url type="application/x-suggestions+json" method="GET" template="https://lt.wikipedia.org/w/api.php">
+ <Param name="action" value="opensearch"/>
+ <Param name="search" value="{searchTerms}"/>
+</Url>
+<Url type="text/html" method="GET" template="https://lt.wikipedia.org/wiki/Specialus:Paieška">
+ <Param name="search" value="{searchTerms}"/>
+ <Param name="sourceid" value="Mozilla-search"/>
+</Url>
+<SearchForm>https://lt.wikipedia.org/wiki/Specialus:Paieška</SearchForm>
+</SearchPlugin>
diff --git a/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-ltg.xml b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-ltg.xml
new file mode 100644
index 0000000000..384d206107
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-ltg.xml
@@ -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/. -->
+
+<SearchPlugin xmlns="http://www.mozilla.org/2006/browser/search/">
+<ShortName>Vikipedeja (ltg)</ShortName>
+<InputEncoding>UTF-8</InputEncoding>
+<Image width="16" height="16">data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGAAAABgCAMAAADVRocKAAAA51BMVEUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD////7+/vl5eWxsbH9/f3Ly8tzc3P39/fe3t5cXFzz8/Pt7e3i4uI3NzcaGhoHBwcFBQX5+fnIyMhTU1MXFxcMDAzx8fHX19fFxcXCwsK7u7u1tbWenp6WlpZ8fHxXV1ctLS319fXn5+fV1dWsrKySkpJnZ2cgICDv7+/p6eng4ODQ0NC9vb24uLikpKSPj4+JiYmCgoJiYmJCQkI7OzsyMjIpKSkQEBCoqKigoKCdnZ14eHhubm5PT09LS0tERETk5OTb29unp6c0NDQkJCQOGD7BAAAAB3RSTlMA8si8ZBhlc+JuAAAAAw1JREFUaN7tmtluIjEQRYEhUxd6YYew7xAggRAgCQmB7Ov8//eM3Zg2nXkJvUjz4POAVEbyQXaVy0gOMaKRMAVAOBINcY5+UWD8OmKCIOaXhlDoNwVKNBShQImEwhQo4RAFjBIogRIogRIogRIoQWCCYXqaHJVaWrtl1IfpYp3GiczFqLHQ5kY9m0l0qVM8Txrs+8ZomkhSKpbOzlraolSP15o/EtxoU9gk2iZVujM7HnVe6eUhKaL4aYrWXWMXfd7+dIlScWxpbsjibQiLPm255sH5jYjKOoCEecge5LcTxqokuItZv5F2DID0iR21ALwctslfunNCurKEBRJkgBTZdIDOoVl0CU7FjgsZHpsi+gNoJGlisDlUkC+C8SQHejzOiqCLgXRTNYazw+vg8tsaHZ+DMd7ZlyR5Qix/uOAEgGOhlzy+EPLMMUmyOHVTyQ0wDBlXB2Dw1FzreCZJGfhyIyiDs/qWSEkiarNPxxaX3J1FWcCRLJXidtFW7MO5lmV3AhMMPS8HHsH4oBJmtEcHF+ROUEgD2E/AiVXO98AtSaoJmC4F1AUjXZAD97Bo0R491ApuBRNdVq/FGhz9hPaI48p9w1mI6rVpi1qQ9FmRuRe8iTPaJgfOi6NaTr20zDoYJUfOM2aOHM15EYwBOKbQwHm14wcY5FYgTzi5CHewMPZytO9aIHuj3MY53sF5s3M0S94EFV5bdiLeshQdgdGwc9T0IJC1VROHs4EHSgHY1XKflaFXQQ6y2MpIVIiSYDStgRLOvN/sDDCSImmv7cxaWVuu5z0LxJKU+Y1M9LE4GHOrsWnkXUDx3a5mRR8zRXFsisj5IeiBc0cmPkRxZMBY0BIGeRLIYmJ8smnLDmVuiL5ngWxksUd5JhVqYEzxTv4I1tiSc9Y38OSTgOZwnki0GYhe55Pg1VqjCUnORLf2SWAVb5fIeYPRJ/4JnoFa1THSATTyT3BcQ++f+8DKRwGN299Hltr/+zdWCZRACZRACZSAlEAJDifwRwPBP3uIUqBEg356EvzjmcCf//wFVbAkwfl+5CMAAAAASUVORK5CYII=</Image>
+<Url type="application/x-suggestions+json" method="GET" template="https://ltg.wikipedia.org/w/api.php">
+ <Param name="action" value="opensearch"/>
+ <Param name="search" value="{searchTerms}"/>
+</Url>
+<Url type="text/html" method="GET" template="https://ltg.wikipedia.org/wiki/Seviškuo:Search">
+ <Param name="search" value="{searchTerms}"/>
+ <Param name="sourceid" value="Mozilla-search"/>
+</Url>
+<SearchForm>https://ltg.wikipedia.org/wiki/Seviškuo:Search</SearchForm>
+</SearchPlugin>
diff --git a/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-lv.xml b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-lv.xml
new file mode 100644
index 0000000000..e25485901a
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-lv.xml
@@ -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/. -->
+
+<SearchPlugin xmlns="http://www.mozilla.org/2006/browser/search/">
+<ShortName>Vikipēdija (lv)</ShortName>
+<InputEncoding>UTF-8</InputEncoding>
+<Image width="16" height="16">data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGAAAABgCAMAAADVRocKAAAA51BMVEUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD////7+/vl5eWxsbH9/f3Ly8tzc3P39/fe3t5cXFzz8/Pt7e3i4uI3NzcaGhoHBwcFBQX5+fnIyMhTU1MXFxcMDAzx8fHX19fFxcXCwsK7u7u1tbWenp6WlpZ8fHxXV1ctLS319fXn5+fV1dWsrKySkpJnZ2cgICDv7+/p6eng4ODQ0NC9vb24uLikpKSPj4+JiYmCgoJiYmJCQkI7OzsyMjIpKSkQEBCoqKigoKCdnZ14eHhubm5PT09LS0tERETk5OTb29unp6c0NDQkJCQOGD7BAAAAB3RSTlMA8si8ZBhlc+JuAAAAAw1JREFUaN7tmtluIjEQRYEhUxd6YYew7xAggRAgCQmB7Ov8//eM3Zg2nXkJvUjz4POAVEbyQXaVy0gOMaKRMAVAOBINcY5+UWD8OmKCIOaXhlDoNwVKNBShQImEwhQo4RAFjBIogRIogRIogRIoQWCCYXqaHJVaWrtl1IfpYp3GiczFqLHQ5kY9m0l0qVM8Txrs+8ZomkhSKpbOzlraolSP15o/EtxoU9gk2iZVujM7HnVe6eUhKaL4aYrWXWMXfd7+dIlScWxpbsjibQiLPm255sH5jYjKOoCEecge5LcTxqokuItZv5F2DID0iR21ALwctslfunNCurKEBRJkgBTZdIDOoVl0CU7FjgsZHpsi+gNoJGlisDlUkC+C8SQHejzOiqCLgXRTNYazw+vg8tsaHZ+DMd7ZlyR5Qix/uOAEgGOhlzy+EPLMMUmyOHVTyQ0wDBlXB2Dw1FzreCZJGfhyIyiDs/qWSEkiarNPxxaX3J1FWcCRLJXidtFW7MO5lmV3AhMMPS8HHsH4oBJmtEcHF+ROUEgD2E/AiVXO98AtSaoJmC4F1AUjXZAD97Bo0R491ApuBRNdVq/FGhz9hPaI48p9w1mI6rVpi1qQ9FmRuRe8iTPaJgfOi6NaTr20zDoYJUfOM2aOHM15EYwBOKbQwHm14wcY5FYgTzi5CHewMPZytO9aIHuj3MY53sF5s3M0S94EFV5bdiLeshQdgdGwc9T0IJC1VROHs4EHSgHY1XKflaFXQQ6y2MpIVIiSYDStgRLOvN/sDDCSImmv7cxaWVuu5z0LxJKU+Y1M9LE4GHOrsWnkXUDx3a5mRR8zRXFsisj5IeiBc0cmPkRxZMBY0BIGeRLIYmJ8smnLDmVuiL5ngWxksUd5JhVqYEzxTv4I1tiSc9Y38OSTgOZwnki0GYhe55Pg1VqjCUnORLf2SWAVb5fIeYPRJ/4JnoFa1THSATTyT3BcQ++f+8DKRwGN299Hltr/+zdWCZRACZRACZSAlEAJDifwRwPBP3uIUqBEg356EvzjmcCf//wFVbAkwfl+5CMAAAAASUVORK5CYII=</Image>
+<Url type="application/x-suggestions+json" method="GET" template="https://lv.wikipedia.org/w/api.php">
+ <Param name="action" value="opensearch"/>
+ <Param name="search" value="{searchTerms}"/>
+</Url>
+<Url type="text/html" method="GET" template="https://lv.wikipedia.org/wiki/Special:Search">
+ <Param name="search" value="{searchTerms}"/>
+ <Param name="sourceid" value="Mozilla-search"/>
+</Url>
+<SearchForm>https://lv.wikipedia.org/wiki/Special:Search</SearchForm>
+</SearchPlugin>
diff --git a/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-ml.xml b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-ml.xml
new file mode 100644
index 0000000000..1d8a5df23c
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-ml.xml
@@ -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/. -->
+
+<SearchPlugin xmlns="http://www.mozilla.org/2006/browser/search/">
+<ShortName>വിക്കിപീഡിയ (ml)</ShortName>
+<InputEncoding>UTF-8</InputEncoding>
+<Image width="16" height="16">data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGAAAABgCAMAAADVRocKAAAA51BMVEUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD////7+/vl5eWxsbH9/f3Ly8tzc3P39/fe3t5cXFzz8/Pt7e3i4uI3NzcaGhoHBwcFBQX5+fnIyMhTU1MXFxcMDAzx8fHX19fFxcXCwsK7u7u1tbWenp6WlpZ8fHxXV1ctLS319fXn5+fV1dWsrKySkpJnZ2cgICDv7+/p6eng4ODQ0NC9vb24uLikpKSPj4+JiYmCgoJiYmJCQkI7OzsyMjIpKSkQEBCoqKigoKCdnZ14eHhubm5PT09LS0tERETk5OTb29unp6c0NDQkJCQOGD7BAAAAB3RSTlMA8si8ZBhlc+JuAAAAAw1JREFUaN7tmtluIjEQRYEhUxd6YYew7xAggRAgCQmB7Ov8//eM3Zg2nXkJvUjz4POAVEbyQXaVy0gOMaKRMAVAOBINcY5+UWD8OmKCIOaXhlDoNwVKNBShQImEwhQo4RAFjBIogRIogRIogRIoQWCCYXqaHJVaWrtl1IfpYp3GiczFqLHQ5kY9m0l0qVM8Txrs+8ZomkhSKpbOzlraolSP15o/EtxoU9gk2iZVujM7HnVe6eUhKaL4aYrWXWMXfd7+dIlScWxpbsjibQiLPm255sH5jYjKOoCEecge5LcTxqokuItZv5F2DID0iR21ALwctslfunNCurKEBRJkgBTZdIDOoVl0CU7FjgsZHpsi+gNoJGlisDlUkC+C8SQHejzOiqCLgXRTNYazw+vg8tsaHZ+DMd7ZlyR5Qix/uOAEgGOhlzy+EPLMMUmyOHVTyQ0wDBlXB2Dw1FzreCZJGfhyIyiDs/qWSEkiarNPxxaX3J1FWcCRLJXidtFW7MO5lmV3AhMMPS8HHsH4oBJmtEcHF+ROUEgD2E/AiVXO98AtSaoJmC4F1AUjXZAD97Bo0R491ApuBRNdVq/FGhz9hPaI48p9w1mI6rVpi1qQ9FmRuRe8iTPaJgfOi6NaTr20zDoYJUfOM2aOHM15EYwBOKbQwHm14wcY5FYgTzi5CHewMPZytO9aIHuj3MY53sF5s3M0S94EFV5bdiLeshQdgdGwc9T0IJC1VROHs4EHSgHY1XKflaFXQQ6y2MpIVIiSYDStgRLOvN/sDDCSImmv7cxaWVuu5z0LxJKU+Y1M9LE4GHOrsWnkXUDx3a5mRR8zRXFsisj5IeiBc0cmPkRxZMBY0BIGeRLIYmJ8smnLDmVuiL5ngWxksUd5JhVqYEzxTv4I1tiSc9Y38OSTgOZwnki0GYhe55Pg1VqjCUnORLf2SWAVb5fIeYPRJ/4JnoFa1THSATTyT3BcQ++f+8DKRwGN299Hltr/+zdWCZRACZRACZSAlEAJDifwRwPBP3uIUqBEg356EvzjmcCf//wFVbAkwfl+5CMAAAAASUVORK5CYII=</Image>
+<Url type="application/x-suggestions+json" method="GET" template="https://ml.wikipedia.org/w/api.php">
+ <Param name="action" value="opensearch"/>
+ <Param name="search" value="{searchTerms}"/>
+</Url>
+<Url type="text/html" method="GET" template="https://ml.wikipedia.org/wiki/പ്രത്യേകം:അന്വേഷണം">
+ <Param name="search" value="{searchTerms}"/>
+ <Param name="sourceid" value="Mozilla-search"/>
+</Url>
+<SearchForm>https://ml.wikipedia.org/wiki/പ്രത്യേകം:അന്വേഷണം</SearchForm>
+</SearchPlugin>
diff --git a/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-mr.xml b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-mr.xml
new file mode 100644
index 0000000000..a73dac3d99
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-mr.xml
@@ -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/. -->
+
+<SearchPlugin xmlns="http://www.mozilla.org/2006/browser/search/">
+<ShortName>विकिपीडिया (mr)</ShortName>
+<InputEncoding>UTF-8</InputEncoding>
+<Image width="16" height="16">data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGAAAABgCAMAAADVRocKAAAA51BMVEUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD////7+/vl5eWxsbH9/f3Ly8tzc3P39/fe3t5cXFzz8/Pt7e3i4uI3NzcaGhoHBwcFBQX5+fnIyMhTU1MXFxcMDAzx8fHX19fFxcXCwsK7u7u1tbWenp6WlpZ8fHxXV1ctLS319fXn5+fV1dWsrKySkpJnZ2cgICDv7+/p6eng4ODQ0NC9vb24uLikpKSPj4+JiYmCgoJiYmJCQkI7OzsyMjIpKSkQEBCoqKigoKCdnZ14eHhubm5PT09LS0tERETk5OTb29unp6c0NDQkJCQOGD7BAAAAB3RSTlMA8si8ZBhlc+JuAAAAAw1JREFUaN7tmtluIjEQRYEhUxd6YYew7xAggRAgCQmB7Ov8//eM3Zg2nXkJvUjz4POAVEbyQXaVy0gOMaKRMAVAOBINcY5+UWD8OmKCIOaXhlDoNwVKNBShQImEwhQo4RAFjBIogRIogRIogRIoQWCCYXqaHJVaWrtl1IfpYp3GiczFqLHQ5kY9m0l0qVM8Txrs+8ZomkhSKpbOzlraolSP15o/EtxoU9gk2iZVujM7HnVe6eUhKaL4aYrWXWMXfd7+dIlScWxpbsjibQiLPm255sH5jYjKOoCEecge5LcTxqokuItZv5F2DID0iR21ALwctslfunNCurKEBRJkgBTZdIDOoVl0CU7FjgsZHpsi+gNoJGlisDlUkC+C8SQHejzOiqCLgXRTNYazw+vg8tsaHZ+DMd7ZlyR5Qix/uOAEgGOhlzy+EPLMMUmyOHVTyQ0wDBlXB2Dw1FzreCZJGfhyIyiDs/qWSEkiarNPxxaX3J1FWcCRLJXidtFW7MO5lmV3AhMMPS8HHsH4oBJmtEcHF+ROUEgD2E/AiVXO98AtSaoJmC4F1AUjXZAD97Bo0R491ApuBRNdVq/FGhz9hPaI48p9w1mI6rVpi1qQ9FmRuRe8iTPaJgfOi6NaTr20zDoYJUfOM2aOHM15EYwBOKbQwHm14wcY5FYgTzi5CHewMPZytO9aIHuj3MY53sF5s3M0S94EFV5bdiLeshQdgdGwc9T0IJC1VROHs4EHSgHY1XKflaFXQQ6y2MpIVIiSYDStgRLOvN/sDDCSImmv7cxaWVuu5z0LxJKU+Y1M9LE4GHOrsWnkXUDx3a5mRR8zRXFsisj5IeiBc0cmPkRxZMBY0BIGeRLIYmJ8smnLDmVuiL5ngWxksUd5JhVqYEzxTv4I1tiSc9Y38OSTgOZwnki0GYhe55Pg1VqjCUnORLf2SWAVb5fIeYPRJ/4JnoFa1THSATTyT3BcQ++f+8DKRwGN299Hltr/+zdWCZRACZRACZSAlEAJDifwRwPBP3uIUqBEg356EvzjmcCf//wFVbAkwfl+5CMAAAAASUVORK5CYII=</Image>
+<Url type="application/x-suggestions+json" method="GET" template="https://mr.wikipedia.org/w/api.php">
+ <Param name="action" value="opensearch"/>
+ <Param name="search" value="{searchTerms}"/>
+</Url>
+<Url type="text/html" method="GET" template="https://mr.wikipedia.org/wiki/विशेष:शोधा">
+ <Param name="search" value="{searchTerms}"/>
+ <Param name="sourceid" value="Mozilla-search"/>
+</Url>
+<SearchForm>https://mr.wikipedia.org/wiki/विशेष:शोधा</SearchForm>
+</SearchPlugin>
diff --git a/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-ms.xml b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-ms.xml
new file mode 100644
index 0000000000..5b892124cf
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-ms.xml
@@ -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/. -->
+
+<SearchPlugin xmlns="http://www.mozilla.org/2006/browser/search/">
+<ShortName>Wikipedia (ms)</ShortName>
+<InputEncoding>UTF-8</InputEncoding>
+<Image width="16" height="16">data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGAAAABgCAMAAADVRocKAAAA51BMVEUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD////7+/vl5eWxsbH9/f3Ly8tzc3P39/fe3t5cXFzz8/Pt7e3i4uI3NzcaGhoHBwcFBQX5+fnIyMhTU1MXFxcMDAzx8fHX19fFxcXCwsK7u7u1tbWenp6WlpZ8fHxXV1ctLS319fXn5+fV1dWsrKySkpJnZ2cgICDv7+/p6eng4ODQ0NC9vb24uLikpKSPj4+JiYmCgoJiYmJCQkI7OzsyMjIpKSkQEBCoqKigoKCdnZ14eHhubm5PT09LS0tERETk5OTb29unp6c0NDQkJCQOGD7BAAAAB3RSTlMA8si8ZBhlc+JuAAAAAw1JREFUaN7tmtluIjEQRYEhUxd6YYew7xAggRAgCQmB7Ov8//eM3Zg2nXkJvUjz4POAVEbyQXaVy0gOMaKRMAVAOBINcY5+UWD8OmKCIOaXhlDoNwVKNBShQImEwhQo4RAFjBIogRIogRIogRIoQWCCYXqaHJVaWrtl1IfpYp3GiczFqLHQ5kY9m0l0qVM8Txrs+8ZomkhSKpbOzlraolSP15o/EtxoU9gk2iZVujM7HnVe6eUhKaL4aYrWXWMXfd7+dIlScWxpbsjibQiLPm255sH5jYjKOoCEecge5LcTxqokuItZv5F2DID0iR21ALwctslfunNCurKEBRJkgBTZdIDOoVl0CU7FjgsZHpsi+gNoJGlisDlUkC+C8SQHejzOiqCLgXRTNYazw+vg8tsaHZ+DMd7ZlyR5Qix/uOAEgGOhlzy+EPLMMUmyOHVTyQ0wDBlXB2Dw1FzreCZJGfhyIyiDs/qWSEkiarNPxxaX3J1FWcCRLJXidtFW7MO5lmV3AhMMPS8HHsH4oBJmtEcHF+ROUEgD2E/AiVXO98AtSaoJmC4F1AUjXZAD97Bo0R491ApuBRNdVq/FGhz9hPaI48p9w1mI6rVpi1qQ9FmRuRe8iTPaJgfOi6NaTr20zDoYJUfOM2aOHM15EYwBOKbQwHm14wcY5FYgTzi5CHewMPZytO9aIHuj3MY53sF5s3M0S94EFV5bdiLeshQdgdGwc9T0IJC1VROHs4EHSgHY1XKflaFXQQ6y2MpIVIiSYDStgRLOvN/sDDCSImmv7cxaWVuu5z0LxJKU+Y1M9LE4GHOrsWnkXUDx3a5mRR8zRXFsisj5IeiBc0cmPkRxZMBY0BIGeRLIYmJ8smnLDmVuiL5ngWxksUd5JhVqYEzxTv4I1tiSc9Y38OSTgOZwnki0GYhe55Pg1VqjCUnORLf2SWAVb5fIeYPRJ/4JnoFa1THSATTyT3BcQ++f+8DKRwGN299Hltr/+zdWCZRACZRACZSAlEAJDifwRwPBP3uIUqBEg356EvzjmcCf//wFVbAkwfl+5CMAAAAASUVORK5CYII=</Image>
+<Url type="application/x-suggestions+json" method="GET" template="https://ms.wikipedia.org/w/api.php">
+ <Param name="action" value="opensearch"/>
+ <Param name="search" value="{searchTerms}"/>
+</Url>
+<Url type="text/html" method="GET" template="https://ms.wikipedia.org/wiki/Khas:Gelintar">
+ <Param name="search" value="{searchTerms}"/>
+ <Param name="sourceid" value="Mozilla-search"/>
+</Url>
+<SearchForm>https://ms.wikipedia.org/wiki/Khas:Gelintar</SearchForm>
+</SearchPlugin>
diff --git a/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-my.xml b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-my.xml
new file mode 100644
index 0000000000..cc781dee19
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-my.xml
@@ -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/. -->
+
+<SearchPlugin xmlns="http://www.mozilla.org/2006/browser/search/">
+<ShortName>Wikipedia (my)</ShortName>
+<InputEncoding>UTF-8</InputEncoding>
+<Image width="16" height="16">data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGAAAABgCAMAAADVRocKAAAA51BMVEUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD////7+/vl5eWxsbH9/f3Ly8tzc3P39/fe3t5cXFzz8/Pt7e3i4uI3NzcaGhoHBwcFBQX5+fnIyMhTU1MXFxcMDAzx8fHX19fFxcXCwsK7u7u1tbWenp6WlpZ8fHxXV1ctLS319fXn5+fV1dWsrKySkpJnZ2cgICDv7+/p6eng4ODQ0NC9vb24uLikpKSPj4+JiYmCgoJiYmJCQkI7OzsyMjIpKSkQEBCoqKigoKCdnZ14eHhubm5PT09LS0tERETk5OTb29unp6c0NDQkJCQOGD7BAAAAB3RSTlMA8si8ZBhlc+JuAAAAAw1JREFUaN7tmtluIjEQRYEhUxd6YYew7xAggRAgCQmB7Ov8//eM3Zg2nXkJvUjz4POAVEbyQXaVy0gOMaKRMAVAOBINcY5+UWD8OmKCIOaXhlDoNwVKNBShQImEwhQo4RAFjBIogRIogRIogRIoQWCCYXqaHJVaWrtl1IfpYp3GiczFqLHQ5kY9m0l0qVM8Txrs+8ZomkhSKpbOzlraolSP15o/EtxoU9gk2iZVujM7HnVe6eUhKaL4aYrWXWMXfd7+dIlScWxpbsjibQiLPm255sH5jYjKOoCEecge5LcTxqokuItZv5F2DID0iR21ALwctslfunNCurKEBRJkgBTZdIDOoVl0CU7FjgsZHpsi+gNoJGlisDlUkC+C8SQHejzOiqCLgXRTNYazw+vg8tsaHZ+DMd7ZlyR5Qix/uOAEgGOhlzy+EPLMMUmyOHVTyQ0wDBlXB2Dw1FzreCZJGfhyIyiDs/qWSEkiarNPxxaX3J1FWcCRLJXidtFW7MO5lmV3AhMMPS8HHsH4oBJmtEcHF+ROUEgD2E/AiVXO98AtSaoJmC4F1AUjXZAD97Bo0R491ApuBRNdVq/FGhz9hPaI48p9w1mI6rVpi1qQ9FmRuRe8iTPaJgfOi6NaTr20zDoYJUfOM2aOHM15EYwBOKbQwHm14wcY5FYgTzi5CHewMPZytO9aIHuj3MY53sF5s3M0S94EFV5bdiLeshQdgdGwc9T0IJC1VROHs4EHSgHY1XKflaFXQQ6y2MpIVIiSYDStgRLOvN/sDDCSImmv7cxaWVuu5z0LxJKU+Y1M9LE4GHOrsWnkXUDx3a5mRR8zRXFsisj5IeiBc0cmPkRxZMBY0BIGeRLIYmJ8smnLDmVuiL5ngWxksUd5JhVqYEzxTv4I1tiSc9Y38OSTgOZwnki0GYhe55Pg1VqjCUnORLf2SWAVb5fIeYPRJ/4JnoFa1THSATTyT3BcQ++f+8DKRwGN299Hltr/+zdWCZRACZRACZSAlEAJDifwRwPBP3uIUqBEg356EvzjmcCf//wFVbAkwfl+5CMAAAAASUVORK5CYII=</Image>
+<Url type="application/x-suggestions+json" method="GET" template="https://my.wikipedia.org/w/api.php">
+ <Param name="action" value="opensearch"/>
+ <Param name="search" value="{searchTerms}"/>
+</Url>
+<Url type="text/html" method="GET" template="https://my.wikipedia.org/wiki/Special:Search">
+ <Param name="search" value="{searchTerms}"/>
+ <Param name="sourceid" value="Mozilla-search"/>
+</Url>
+<SearchForm>https://my.wikipedia.org/wiki/Special:Search</SearchForm>
+</SearchPlugin>
diff --git a/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-ne.xml b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-ne.xml
new file mode 100644
index 0000000000..93118b3057
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-ne.xml
@@ -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/. -->
+
+<SearchPlugin xmlns="http://www.mozilla.org/2006/browser/search/">
+<ShortName>विकिपीडिया (ne)</ShortName>
+<InputEncoding>UTF-8</InputEncoding>
+<Image width="16" height="16">data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGAAAABgCAMAAADVRocKAAAA51BMVEUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD////7+/vl5eWxsbH9/f3Ly8tzc3P39/fe3t5cXFzz8/Pt7e3i4uI3NzcaGhoHBwcFBQX5+fnIyMhTU1MXFxcMDAzx8fHX19fFxcXCwsK7u7u1tbWenp6WlpZ8fHxXV1ctLS319fXn5+fV1dWsrKySkpJnZ2cgICDv7+/p6eng4ODQ0NC9vb24uLikpKSPj4+JiYmCgoJiYmJCQkI7OzsyMjIpKSkQEBCoqKigoKCdnZ14eHhubm5PT09LS0tERETk5OTb29unp6c0NDQkJCQOGD7BAAAAB3RSTlMA8si8ZBhlc+JuAAAAAw1JREFUaN7tmtluIjEQRYEhUxd6YYew7xAggRAgCQmB7Ov8//eM3Zg2nXkJvUjz4POAVEbyQXaVy0gOMaKRMAVAOBINcY5+UWD8OmKCIOaXhlDoNwVKNBShQImEwhQo4RAFjBIogRIogRIogRIoQWCCYXqaHJVaWrtl1IfpYp3GiczFqLHQ5kY9m0l0qVM8Txrs+8ZomkhSKpbOzlraolSP15o/EtxoU9gk2iZVujM7HnVe6eUhKaL4aYrWXWMXfd7+dIlScWxpbsjibQiLPm255sH5jYjKOoCEecge5LcTxqokuItZv5F2DID0iR21ALwctslfunNCurKEBRJkgBTZdIDOoVl0CU7FjgsZHpsi+gNoJGlisDlUkC+C8SQHejzOiqCLgXRTNYazw+vg8tsaHZ+DMd7ZlyR5Qix/uOAEgGOhlzy+EPLMMUmyOHVTyQ0wDBlXB2Dw1FzreCZJGfhyIyiDs/qWSEkiarNPxxaX3J1FWcCRLJXidtFW7MO5lmV3AhMMPS8HHsH4oBJmtEcHF+ROUEgD2E/AiVXO98AtSaoJmC4F1AUjXZAD97Bo0R491ApuBRNdVq/FGhz9hPaI48p9w1mI6rVpi1qQ9FmRuRe8iTPaJgfOi6NaTr20zDoYJUfOM2aOHM15EYwBOKbQwHm14wcY5FYgTzi5CHewMPZytO9aIHuj3MY53sF5s3M0S94EFV5bdiLeshQdgdGwc9T0IJC1VROHs4EHSgHY1XKflaFXQQ6y2MpIVIiSYDStgRLOvN/sDDCSImmv7cxaWVuu5z0LxJKU+Y1M9LE4GHOrsWnkXUDx3a5mRR8zRXFsisj5IeiBc0cmPkRxZMBY0BIGeRLIYmJ8smnLDmVuiL5ngWxksUd5JhVqYEzxTv4I1tiSc9Y38OSTgOZwnki0GYhe55Pg1VqjCUnORLf2SWAVb5fIeYPRJ/4JnoFa1THSATTyT3BcQ++f+8DKRwGN299Hltr/+zdWCZRACZRACZSAlEAJDifwRwPBP3uIUqBEg356EvzjmcCf//wFVbAkwfl+5CMAAAAASUVORK5CYII=</Image>
+<Url type="application/x-suggestions+json" method="GET" template="https://ne.wikipedia.org/w/api.php">
+ <Param name="action" value="opensearch"/>
+ <Param name="search" value="{searchTerms}"/>
+</Url>
+<Url type="text/html" method="GET" template="https://ne.wikipedia.org/wiki/विशेष:Search">
+ <Param name="search" value="{searchTerms}"/>
+ <Param name="sourceid" value="Mozilla-search"/>
+</Url>
+<SearchForm>https://ne.wikipedia.org/wiki/विशेष:Search</SearchForm>
+</SearchPlugin>
diff --git a/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-nl.xml b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-nl.xml
new file mode 100644
index 0000000000..36b41dd48a
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-nl.xml
@@ -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/. -->
+
+<SearchPlugin xmlns="http://www.mozilla.org/2006/browser/search/">
+<ShortName>Wikipedia (nl)</ShortName>
+<InputEncoding>UTF-8</InputEncoding>
+<Image width="16" height="16">data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGAAAABgCAMAAADVRocKAAAA51BMVEUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD////7+/vl5eWxsbH9/f3Ly8tzc3P39/fe3t5cXFzz8/Pt7e3i4uI3NzcaGhoHBwcFBQX5+fnIyMhTU1MXFxcMDAzx8fHX19fFxcXCwsK7u7u1tbWenp6WlpZ8fHxXV1ctLS319fXn5+fV1dWsrKySkpJnZ2cgICDv7+/p6eng4ODQ0NC9vb24uLikpKSPj4+JiYmCgoJiYmJCQkI7OzsyMjIpKSkQEBCoqKigoKCdnZ14eHhubm5PT09LS0tERETk5OTb29unp6c0NDQkJCQOGD7BAAAAB3RSTlMA8si8ZBhlc+JuAAAAAw1JREFUaN7tmtluIjEQRYEhUxd6YYew7xAggRAgCQmB7Ov8//eM3Zg2nXkJvUjz4POAVEbyQXaVy0gOMaKRMAVAOBINcY5+UWD8OmKCIOaXhlDoNwVKNBShQImEwhQo4RAFjBIogRIogRIogRIoQWCCYXqaHJVaWrtl1IfpYp3GiczFqLHQ5kY9m0l0qVM8Txrs+8ZomkhSKpbOzlraolSP15o/EtxoU9gk2iZVujM7HnVe6eUhKaL4aYrWXWMXfd7+dIlScWxpbsjibQiLPm255sH5jYjKOoCEecge5LcTxqokuItZv5F2DID0iR21ALwctslfunNCurKEBRJkgBTZdIDOoVl0CU7FjgsZHpsi+gNoJGlisDlUkC+C8SQHejzOiqCLgXRTNYazw+vg8tsaHZ+DMd7ZlyR5Qix/uOAEgGOhlzy+EPLMMUmyOHVTyQ0wDBlXB2Dw1FzreCZJGfhyIyiDs/qWSEkiarNPxxaX3J1FWcCRLJXidtFW7MO5lmV3AhMMPS8HHsH4oBJmtEcHF+ROUEgD2E/AiVXO98AtSaoJmC4F1AUjXZAD97Bo0R491ApuBRNdVq/FGhz9hPaI48p9w1mI6rVpi1qQ9FmRuRe8iTPaJgfOi6NaTr20zDoYJUfOM2aOHM15EYwBOKbQwHm14wcY5FYgTzi5CHewMPZytO9aIHuj3MY53sF5s3M0S94EFV5bdiLeshQdgdGwc9T0IJC1VROHs4EHSgHY1XKflaFXQQ6y2MpIVIiSYDStgRLOvN/sDDCSImmv7cxaWVuu5z0LxJKU+Y1M9LE4GHOrsWnkXUDx3a5mRR8zRXFsisj5IeiBc0cmPkRxZMBY0BIGeRLIYmJ8smnLDmVuiL5ngWxksUd5JhVqYEzxTv4I1tiSc9Y38OSTgOZwnki0GYhe55Pg1VqjCUnORLf2SWAVb5fIeYPRJ/4JnoFa1THSATTyT3BcQ++f+8DKRwGN299Hltr/+zdWCZRACZRACZSAlEAJDifwRwPBP3uIUqBEg356EvzjmcCf//wFVbAkwfl+5CMAAAAASUVORK5CYII=</Image>
+<Url type="application/x-suggestions+json" method="GET" template="https://nl.wikipedia.org/w/api.php">
+ <Param name="action" value="opensearch"/>
+ <Param name="search" value="{searchTerms}"/>
+</Url>
+<Url type="text/html" method="GET" template="https://nl.wikipedia.org/wiki/Speciaal:Zoeken">
+ <Param name="search" value="{searchTerms}"/>
+ <Param name="sourceid" value="Mozilla-search"/>
+</Url>
+<SearchForm>https://nl.wikipedia.org/wiki/Speciaal:Zoeken</SearchForm>
+</SearchPlugin>
diff --git a/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-oc.xml b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-oc.xml
new file mode 100644
index 0000000000..6493a0b1ed
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-oc.xml
@@ -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/. -->
+
+<SearchPlugin xmlns="http://www.mozilla.org/2006/browser/search/">
+<ShortName>Wikipèdia (oc)</ShortName>
+<InputEncoding>UTF-8</InputEncoding>
+<Image width="16" height="16">data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGAAAABgCAMAAADVRocKAAAA51BMVEUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD////7+/vl5eWxsbH9/f3Ly8tzc3P39/fe3t5cXFzz8/Pt7e3i4uI3NzcaGhoHBwcFBQX5+fnIyMhTU1MXFxcMDAzx8fHX19fFxcXCwsK7u7u1tbWenp6WlpZ8fHxXV1ctLS319fXn5+fV1dWsrKySkpJnZ2cgICDv7+/p6eng4ODQ0NC9vb24uLikpKSPj4+JiYmCgoJiYmJCQkI7OzsyMjIpKSkQEBCoqKigoKCdnZ14eHhubm5PT09LS0tERETk5OTb29unp6c0NDQkJCQOGD7BAAAAB3RSTlMA8si8ZBhlc+JuAAAAAw1JREFUaN7tmtluIjEQRYEhUxd6YYew7xAggRAgCQmB7Ov8//eM3Zg2nXkJvUjz4POAVEbyQXaVy0gOMaKRMAVAOBINcY5+UWD8OmKCIOaXhlDoNwVKNBShQImEwhQo4RAFjBIogRIogRIogRIoQWCCYXqaHJVaWrtl1IfpYp3GiczFqLHQ5kY9m0l0qVM8Txrs+8ZomkhSKpbOzlraolSP15o/EtxoU9gk2iZVujM7HnVe6eUhKaL4aYrWXWMXfd7+dIlScWxpbsjibQiLPm255sH5jYjKOoCEecge5LcTxqokuItZv5F2DID0iR21ALwctslfunNCurKEBRJkgBTZdIDOoVl0CU7FjgsZHpsi+gNoJGlisDlUkC+C8SQHejzOiqCLgXRTNYazw+vg8tsaHZ+DMd7ZlyR5Qix/uOAEgGOhlzy+EPLMMUmyOHVTyQ0wDBlXB2Dw1FzreCZJGfhyIyiDs/qWSEkiarNPxxaX3J1FWcCRLJXidtFW7MO5lmV3AhMMPS8HHsH4oBJmtEcHF+ROUEgD2E/AiVXO98AtSaoJmC4F1AUjXZAD97Bo0R491ApuBRNdVq/FGhz9hPaI48p9w1mI6rVpi1qQ9FmRuRe8iTPaJgfOi6NaTr20zDoYJUfOM2aOHM15EYwBOKbQwHm14wcY5FYgTzi5CHewMPZytO9aIHuj3MY53sF5s3M0S94EFV5bdiLeshQdgdGwc9T0IJC1VROHs4EHSgHY1XKflaFXQQ6y2MpIVIiSYDStgRLOvN/sDDCSImmv7cxaWVuu5z0LxJKU+Y1M9LE4GHOrsWnkXUDx3a5mRR8zRXFsisj5IeiBc0cmPkRxZMBY0BIGeRLIYmJ8smnLDmVuiL5ngWxksUd5JhVqYEzxTv4I1tiSc9Y38OSTgOZwnki0GYhe55Pg1VqjCUnORLf2SWAVb5fIeYPRJ/4JnoFa1THSATTyT3BcQ++f+8DKRwGN299Hltr/+zdWCZRACZRACZSAlEAJDifwRwPBP3uIUqBEg356EvzjmcCf//wFVbAkwfl+5CMAAAAASUVORK5CYII=</Image>
+<Url type="application/x-suggestions+json" method="GET" template="https://oc.wikipedia.org/w/api.php">
+ <Param name="action" value="opensearch"/>
+ <Param name="search" value="{searchTerms}"/>
+</Url>
+<Url type="text/html" method="GET" template="https://oc.wikipedia.org/wiki/Especial:Recèrca">
+ <Param name="search" value="{searchTerms}"/>
+ <Param name="sourceid" value="Mozilla-search"/>
+</Url>
+<SearchForm>https://oc.wikipedia.org/wiki/Especial:Recèrca</SearchForm>
+</SearchPlugin>
diff --git a/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-or.xml b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-or.xml
new file mode 100644
index 0000000000..109e9e0fb6
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-or.xml
@@ -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/. -->
+
+<SearchPlugin xmlns="http://www.mozilla.org/2006/browser/search/">
+<ShortName>ଉଇକିପିଡ଼ିଆ (or)</ShortName>
+<InputEncoding>UTF-8</InputEncoding>
+<Image width="16" height="16">data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGAAAABgCAMAAADVRocKAAAA51BMVEUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD////7+/vl5eWxsbH9/f3Ly8tzc3P39/fe3t5cXFzz8/Pt7e3i4uI3NzcaGhoHBwcFBQX5+fnIyMhTU1MXFxcMDAzx8fHX19fFxcXCwsK7u7u1tbWenp6WlpZ8fHxXV1ctLS319fXn5+fV1dWsrKySkpJnZ2cgICDv7+/p6eng4ODQ0NC9vb24uLikpKSPj4+JiYmCgoJiYmJCQkI7OzsyMjIpKSkQEBCoqKigoKCdnZ14eHhubm5PT09LS0tERETk5OTb29unp6c0NDQkJCQOGD7BAAAAB3RSTlMA8si8ZBhlc+JuAAAAAw1JREFUaN7tmtluIjEQRYEhUxd6YYew7xAggRAgCQmB7Ov8//eM3Zg2nXkJvUjz4POAVEbyQXaVy0gOMaKRMAVAOBINcY5+UWD8OmKCIOaXhlDoNwVKNBShQImEwhQo4RAFjBIogRIogRIogRIoQWCCYXqaHJVaWrtl1IfpYp3GiczFqLHQ5kY9m0l0qVM8Txrs+8ZomkhSKpbOzlraolSP15o/EtxoU9gk2iZVujM7HnVe6eUhKaL4aYrWXWMXfd7+dIlScWxpbsjibQiLPm255sH5jYjKOoCEecge5LcTxqokuItZv5F2DID0iR21ALwctslfunNCurKEBRJkgBTZdIDOoVl0CU7FjgsZHpsi+gNoJGlisDlUkC+C8SQHejzOiqCLgXRTNYazw+vg8tsaHZ+DMd7ZlyR5Qix/uOAEgGOhlzy+EPLMMUmyOHVTyQ0wDBlXB2Dw1FzreCZJGfhyIyiDs/qWSEkiarNPxxaX3J1FWcCRLJXidtFW7MO5lmV3AhMMPS8HHsH4oBJmtEcHF+ROUEgD2E/AiVXO98AtSaoJmC4F1AUjXZAD97Bo0R491ApuBRNdVq/FGhz9hPaI48p9w1mI6rVpi1qQ9FmRuRe8iTPaJgfOi6NaTr20zDoYJUfOM2aOHM15EYwBOKbQwHm14wcY5FYgTzi5CHewMPZytO9aIHuj3MY53sF5s3M0S94EFV5bdiLeshQdgdGwc9T0IJC1VROHs4EHSgHY1XKflaFXQQ6y2MpIVIiSYDStgRLOvN/sDDCSImmv7cxaWVuu5z0LxJKU+Y1M9LE4GHOrsWnkXUDx3a5mRR8zRXFsisj5IeiBc0cmPkRxZMBY0BIGeRLIYmJ8smnLDmVuiL5ngWxksUd5JhVqYEzxTv4I1tiSc9Y38OSTgOZwnki0GYhe55Pg1VqjCUnORLf2SWAVb5fIeYPRJ/4JnoFa1THSATTyT3BcQ++f+8DKRwGN299Hltr/+zdWCZRACZRACZSAlEAJDifwRwPBP3uIUqBEg356EvzjmcCf//wFVbAkwfl+5CMAAAAASUVORK5CYII=</Image>
+<Url type="application/x-suggestions+json" method="GET" template="https://or.wikipedia.org/w/api.php">
+ <Param name="action" value="opensearch"/>
+ <Param name="search" value="{searchTerms}"/>
+</Url>
+<Url type="text/html" method="GET" template="https://or.wikipedia.org/wiki/ବିଶେଷ:ଖୋଜନ୍ତୁ">
+ <Param name="search" value="{searchTerms}"/>
+ <Param name="sourceid" value="Mozilla-search"/>
+</Url>
+<SearchForm>https://or.wikipedia.org/wiki/ବିଶେଷ:ଖୋଜନ୍ତୁ</SearchForm>
+</SearchPlugin>
diff --git a/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-pa.xml b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-pa.xml
new file mode 100644
index 0000000000..b423d887da
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-pa.xml
@@ -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/. -->
+
+<SearchPlugin xmlns="http://www.mozilla.org/2006/browser/search/">
+<ShortName>Wikipedia (pa)</ShortName>
+<InputEncoding>UTF-8</InputEncoding>
+<Image width="16" height="16">data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGAAAABgCAMAAADVRocKAAAA51BMVEUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD////7+/vl5eWxsbH9/f3Ly8tzc3P39/fe3t5cXFzz8/Pt7e3i4uI3NzcaGhoHBwcFBQX5+fnIyMhTU1MXFxcMDAzx8fHX19fFxcXCwsK7u7u1tbWenp6WlpZ8fHxXV1ctLS319fXn5+fV1dWsrKySkpJnZ2cgICDv7+/p6eng4ODQ0NC9vb24uLikpKSPj4+JiYmCgoJiYmJCQkI7OzsyMjIpKSkQEBCoqKigoKCdnZ14eHhubm5PT09LS0tERETk5OTb29unp6c0NDQkJCQOGD7BAAAAB3RSTlMA8si8ZBhlc+JuAAAAAw1JREFUaN7tmtluIjEQRYEhUxd6YYew7xAggRAgCQmB7Ov8//eM3Zg2nXkJvUjz4POAVEbyQXaVy0gOMaKRMAVAOBINcY5+UWD8OmKCIOaXhlDoNwVKNBShQImEwhQo4RAFjBIogRIogRIogRIoQWCCYXqaHJVaWrtl1IfpYp3GiczFqLHQ5kY9m0l0qVM8Txrs+8ZomkhSKpbOzlraolSP15o/EtxoU9gk2iZVujM7HnVe6eUhKaL4aYrWXWMXfd7+dIlScWxpbsjibQiLPm255sH5jYjKOoCEecge5LcTxqokuItZv5F2DID0iR21ALwctslfunNCurKEBRJkgBTZdIDOoVl0CU7FjgsZHpsi+gNoJGlisDlUkC+C8SQHejzOiqCLgXRTNYazw+vg8tsaHZ+DMd7ZlyR5Qix/uOAEgGOhlzy+EPLMMUmyOHVTyQ0wDBlXB2Dw1FzreCZJGfhyIyiDs/qWSEkiarNPxxaX3J1FWcCRLJXidtFW7MO5lmV3AhMMPS8HHsH4oBJmtEcHF+ROUEgD2E/AiVXO98AtSaoJmC4F1AUjXZAD97Bo0R491ApuBRNdVq/FGhz9hPaI48p9w1mI6rVpi1qQ9FmRuRe8iTPaJgfOi6NaTr20zDoYJUfOM2aOHM15EYwBOKbQwHm14wcY5FYgTzi5CHewMPZytO9aIHuj3MY53sF5s3M0S94EFV5bdiLeshQdgdGwc9T0IJC1VROHs4EHSgHY1XKflaFXQQ6y2MpIVIiSYDStgRLOvN/sDDCSImmv7cxaWVuu5z0LxJKU+Y1M9LE4GHOrsWnkXUDx3a5mRR8zRXFsisj5IeiBc0cmPkRxZMBY0BIGeRLIYmJ8smnLDmVuiL5ngWxksUd5JhVqYEzxTv4I1tiSc9Y38OSTgOZwnki0GYhe55Pg1VqjCUnORLf2SWAVb5fIeYPRJ/4JnoFa1THSATTyT3BcQ++f+8DKRwGN299Hltr/+zdWCZRACZRACZSAlEAJDifwRwPBP3uIUqBEg356EvzjmcCf//wFVbAkwfl+5CMAAAAASUVORK5CYII=</Image>
+<Url type="application/x-suggestions+json" method="GET" template="https://pa.wikipedia.org/w/api.php">
+ <Param name="action" value="opensearch"/>
+ <Param name="search" value="{searchTerms}"/>
+</Url>
+<Url type="text/html" method="GET" template="https://pa.wikipedia.org/wiki/ਖ਼ਾਸ:ਖੋਜੋ">
+ <Param name="search" value="{searchTerms}"/>
+ <Param name="sourceid" value="Mozilla-search"/>
+</Url>
+<SearchForm>https://pa.wikipedia.org/wiki/ਖ਼ਾਸ:ਖੋਜੋ</SearchForm>
+</SearchPlugin>
diff --git a/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-pl.xml b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-pl.xml
new file mode 100644
index 0000000000..e8fb1aafb3
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-pl.xml
@@ -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/. -->
+
+<SearchPlugin xmlns="http://www.mozilla.org/2006/browser/search/">
+<ShortName>Wikipedia (pl)</ShortName>
+<InputEncoding>UTF-8</InputEncoding>
+<Image width="16" height="16">data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGAAAABgCAMAAADVRocKAAAA51BMVEUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD////7+/vl5eWxsbH9/f3Ly8tzc3P39/fe3t5cXFzz8/Pt7e3i4uI3NzcaGhoHBwcFBQX5+fnIyMhTU1MXFxcMDAzx8fHX19fFxcXCwsK7u7u1tbWenp6WlpZ8fHxXV1ctLS319fXn5+fV1dWsrKySkpJnZ2cgICDv7+/p6eng4ODQ0NC9vb24uLikpKSPj4+JiYmCgoJiYmJCQkI7OzsyMjIpKSkQEBCoqKigoKCdnZ14eHhubm5PT09LS0tERETk5OTb29unp6c0NDQkJCQOGD7BAAAAB3RSTlMA8si8ZBhlc+JuAAAAAw1JREFUaN7tmtluIjEQRYEhUxd6YYew7xAggRAgCQmB7Ov8//eM3Zg2nXkJvUjz4POAVEbyQXaVy0gOMaKRMAVAOBINcY5+UWD8OmKCIOaXhlDoNwVKNBShQImEwhQo4RAFjBIogRIogRIogRIoQWCCYXqaHJVaWrtl1IfpYp3GiczFqLHQ5kY9m0l0qVM8Txrs+8ZomkhSKpbOzlraolSP15o/EtxoU9gk2iZVujM7HnVe6eUhKaL4aYrWXWMXfd7+dIlScWxpbsjibQiLPm255sH5jYjKOoCEecge5LcTxqokuItZv5F2DID0iR21ALwctslfunNCurKEBRJkgBTZdIDOoVl0CU7FjgsZHpsi+gNoJGlisDlUkC+C8SQHejzOiqCLgXRTNYazw+vg8tsaHZ+DMd7ZlyR5Qix/uOAEgGOhlzy+EPLMMUmyOHVTyQ0wDBlXB2Dw1FzreCZJGfhyIyiDs/qWSEkiarNPxxaX3J1FWcCRLJXidtFW7MO5lmV3AhMMPS8HHsH4oBJmtEcHF+ROUEgD2E/AiVXO98AtSaoJmC4F1AUjXZAD97Bo0R491ApuBRNdVq/FGhz9hPaI48p9w1mI6rVpi1qQ9FmRuRe8iTPaJgfOi6NaTr20zDoYJUfOM2aOHM15EYwBOKbQwHm14wcY5FYgTzi5CHewMPZytO9aIHuj3MY53sF5s3M0S94EFV5bdiLeshQdgdGwc9T0IJC1VROHs4EHSgHY1XKflaFXQQ6y2MpIVIiSYDStgRLOvN/sDDCSImmv7cxaWVuu5z0LxJKU+Y1M9LE4GHOrsWnkXUDx3a5mRR8zRXFsisj5IeiBc0cmPkRxZMBY0BIGeRLIYmJ8smnLDmVuiL5ngWxksUd5JhVqYEzxTv4I1tiSc9Y38OSTgOZwnki0GYhe55Pg1VqjCUnORLf2SWAVb5fIeYPRJ/4JnoFa1THSATTyT3BcQ++f+8DKRwGN299Hltr/+zdWCZRACZRACZSAlEAJDifwRwPBP3uIUqBEg356EvzjmcCf//wFVbAkwfl+5CMAAAAASUVORK5CYII=</Image>
+<Url type="application/x-suggestions+json" method="GET" template="https://pl.wikipedia.org/w/api.php">
+ <Param name="action" value="opensearch"/>
+ <Param name="search" value="{searchTerms}"/>
+</Url>
+<Url type="text/html" method="GET" template="https://pl.wikipedia.org/wiki/Specjalna:Szukaj">
+ <Param name="search" value="{searchTerms}"/>
+ <Param name="sourceid" value="Mozilla-search"/>
+</Url>
+<SearchForm>https://pl.wikipedia.org/wiki/Specjalna:Szukaj</SearchForm>
+</SearchPlugin>
diff --git a/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-pt.xml b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-pt.xml
new file mode 100644
index 0000000000..1595395e25
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-pt.xml
@@ -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/. -->
+
+<SearchPlugin xmlns="http://www.mozilla.org/2006/browser/search/">
+<ShortName>Wikipedia (pt)</ShortName>
+<InputEncoding>UTF-8</InputEncoding>
+<Image width="16" height="16">data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGAAAABgCAMAAADVRocKAAAA51BMVEUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD////7+/vl5eWxsbH9/f3Ly8tzc3P39/fe3t5cXFzz8/Pt7e3i4uI3NzcaGhoHBwcFBQX5+fnIyMhTU1MXFxcMDAzx8fHX19fFxcXCwsK7u7u1tbWenp6WlpZ8fHxXV1ctLS319fXn5+fV1dWsrKySkpJnZ2cgICDv7+/p6eng4ODQ0NC9vb24uLikpKSPj4+JiYmCgoJiYmJCQkI7OzsyMjIpKSkQEBCoqKigoKCdnZ14eHhubm5PT09LS0tERETk5OTb29unp6c0NDQkJCQOGD7BAAAAB3RSTlMA8si8ZBhlc+JuAAAAAw1JREFUaN7tmtluIjEQRYEhUxd6YYew7xAggRAgCQmB7Ov8//eM3Zg2nXkJvUjz4POAVEbyQXaVy0gOMaKRMAVAOBINcY5+UWD8OmKCIOaXhlDoNwVKNBShQImEwhQo4RAFjBIogRIogRIogRIoQWCCYXqaHJVaWrtl1IfpYp3GiczFqLHQ5kY9m0l0qVM8Txrs+8ZomkhSKpbOzlraolSP15o/EtxoU9gk2iZVujM7HnVe6eUhKaL4aYrWXWMXfd7+dIlScWxpbsjibQiLPm255sH5jYjKOoCEecge5LcTxqokuItZv5F2DID0iR21ALwctslfunNCurKEBRJkgBTZdIDOoVl0CU7FjgsZHpsi+gNoJGlisDlUkC+C8SQHejzOiqCLgXRTNYazw+vg8tsaHZ+DMd7ZlyR5Qix/uOAEgGOhlzy+EPLMMUmyOHVTyQ0wDBlXB2Dw1FzreCZJGfhyIyiDs/qWSEkiarNPxxaX3J1FWcCRLJXidtFW7MO5lmV3AhMMPS8HHsH4oBJmtEcHF+ROUEgD2E/AiVXO98AtSaoJmC4F1AUjXZAD97Bo0R491ApuBRNdVq/FGhz9hPaI48p9w1mI6rVpi1qQ9FmRuRe8iTPaJgfOi6NaTr20zDoYJUfOM2aOHM15EYwBOKbQwHm14wcY5FYgTzi5CHewMPZytO9aIHuj3MY53sF5s3M0S94EFV5bdiLeshQdgdGwc9T0IJC1VROHs4EHSgHY1XKflaFXQQ6y2MpIVIiSYDStgRLOvN/sDDCSImmv7cxaWVuu5z0LxJKU+Y1M9LE4GHOrsWnkXUDx3a5mRR8zRXFsisj5IeiBc0cmPkRxZMBY0BIGeRLIYmJ8smnLDmVuiL5ngWxksUd5JhVqYEzxTv4I1tiSc9Y38OSTgOZwnki0GYhe55Pg1VqjCUnORLf2SWAVb5fIeYPRJ/4JnoFa1THSATTyT3BcQ++f+8DKRwGN299Hltr/+zdWCZRACZRACZSAlEAJDifwRwPBP3uIUqBEg356EvzjmcCf//wFVbAkwfl+5CMAAAAASUVORK5CYII=</Image>
+<Url type="application/x-suggestions+json" method="GET" template="https://pt.wikipedia.org/w/api.php">
+ <Param name="action" value="opensearch"/>
+ <Param name="search" value="{searchTerms}"/>
+</Url>
+<Url type="text/html" method="GET" template="https://pt.wikipedia.org/wiki/Especial:Pesquisar">
+ <Param name="search" value="{searchTerms}"/>
+ <Param name="sourceid" value="Mozilla-search"/>
+</Url>
+<SearchForm>https://pt.wikipedia.org/wiki/Especial:Pesquisar</SearchForm>
+</SearchPlugin>
diff --git a/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-rm.xml b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-rm.xml
new file mode 100644
index 0000000000..aca3ffdfb6
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-rm.xml
@@ -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/. -->
+
+<SearchPlugin xmlns="http://www.mozilla.org/2006/browser/search/">
+<ShortName>Wikipedia (rm)</ShortName>
+<InputEncoding>UTF-8</InputEncoding>
+<Image width="16" height="16">data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGAAAABgCAMAAADVRocKAAAA51BMVEUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD////7+/vl5eWxsbH9/f3Ly8tzc3P39/fe3t5cXFzz8/Pt7e3i4uI3NzcaGhoHBwcFBQX5+fnIyMhTU1MXFxcMDAzx8fHX19fFxcXCwsK7u7u1tbWenp6WlpZ8fHxXV1ctLS319fXn5+fV1dWsrKySkpJnZ2cgICDv7+/p6eng4ODQ0NC9vb24uLikpKSPj4+JiYmCgoJiYmJCQkI7OzsyMjIpKSkQEBCoqKigoKCdnZ14eHhubm5PT09LS0tERETk5OTb29unp6c0NDQkJCQOGD7BAAAAB3RSTlMA8si8ZBhlc+JuAAAAAw1JREFUaN7tmtluIjEQRYEhUxd6YYew7xAggRAgCQmB7Ov8//eM3Zg2nXkJvUjz4POAVEbyQXaVy0gOMaKRMAVAOBINcY5+UWD8OmKCIOaXhlDoNwVKNBShQImEwhQo4RAFjBIogRIogRIogRIoQWCCYXqaHJVaWrtl1IfpYp3GiczFqLHQ5kY9m0l0qVM8Txrs+8ZomkhSKpbOzlraolSP15o/EtxoU9gk2iZVujM7HnVe6eUhKaL4aYrWXWMXfd7+dIlScWxpbsjibQiLPm255sH5jYjKOoCEecge5LcTxqokuItZv5F2DID0iR21ALwctslfunNCurKEBRJkgBTZdIDOoVl0CU7FjgsZHpsi+gNoJGlisDlUkC+C8SQHejzOiqCLgXRTNYazw+vg8tsaHZ+DMd7ZlyR5Qix/uOAEgGOhlzy+EPLMMUmyOHVTyQ0wDBlXB2Dw1FzreCZJGfhyIyiDs/qWSEkiarNPxxaX3J1FWcCRLJXidtFW7MO5lmV3AhMMPS8HHsH4oBJmtEcHF+ROUEgD2E/AiVXO98AtSaoJmC4F1AUjXZAD97Bo0R491ApuBRNdVq/FGhz9hPaI48p9w1mI6rVpi1qQ9FmRuRe8iTPaJgfOi6NaTr20zDoYJUfOM2aOHM15EYwBOKbQwHm14wcY5FYgTzi5CHewMPZytO9aIHuj3MY53sF5s3M0S94EFV5bdiLeshQdgdGwc9T0IJC1VROHs4EHSgHY1XKflaFXQQ6y2MpIVIiSYDStgRLOvN/sDDCSImmv7cxaWVuu5z0LxJKU+Y1M9LE4GHOrsWnkXUDx3a5mRR8zRXFsisj5IeiBc0cmPkRxZMBY0BIGeRLIYmJ8smnLDmVuiL5ngWxksUd5JhVqYEzxTv4I1tiSc9Y38OSTgOZwnki0GYhe55Pg1VqjCUnORLf2SWAVb5fIeYPRJ/4JnoFa1THSATTyT3BcQ++f+8DKRwGN299Hltr/+zdWCZRACZRACZSAlEAJDifwRwPBP3uIUqBEg356EvzjmcCf//wFVbAkwfl+5CMAAAAASUVORK5CYII=</Image>
+<Url type="application/x-suggestions+json" method="GET" template="https://rm.wikipedia.org/w/api.php">
+ <Param name="action" value="opensearch"/>
+ <Param name="search" value="{searchTerms}"/>
+</Url>
+<Url type="text/html" method="GET" template="https://rm.wikipedia.org/wiki/Spezial:Search">
+ <Param name="search" value="{searchTerms}"/>
+ <Param name="sourceid" value="Mozilla-search"/>
+</Url>
+<SearchForm>https://rm.wikipedia.org/wiki/Spezial:Search</SearchForm>
+</SearchPlugin>
diff --git a/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-ro.xml b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-ro.xml
new file mode 100644
index 0000000000..f91f665dc1
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-ro.xml
@@ -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/. -->
+
+<SearchPlugin xmlns="http://www.mozilla.org/2006/browser/search/">
+<ShortName>Wikipedia (ro)</ShortName>
+<InputEncoding>UTF-8</InputEncoding>
+<Image width="16" height="16">data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGAAAABgCAMAAADVRocKAAAA51BMVEUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD////7+/vl5eWxsbH9/f3Ly8tzc3P39/fe3t5cXFzz8/Pt7e3i4uI3NzcaGhoHBwcFBQX5+fnIyMhTU1MXFxcMDAzx8fHX19fFxcXCwsK7u7u1tbWenp6WlpZ8fHxXV1ctLS319fXn5+fV1dWsrKySkpJnZ2cgICDv7+/p6eng4ODQ0NC9vb24uLikpKSPj4+JiYmCgoJiYmJCQkI7OzsyMjIpKSkQEBCoqKigoKCdnZ14eHhubm5PT09LS0tERETk5OTb29unp6c0NDQkJCQOGD7BAAAAB3RSTlMA8si8ZBhlc+JuAAAAAw1JREFUaN7tmtluIjEQRYEhUxd6YYew7xAggRAgCQmB7Ov8//eM3Zg2nXkJvUjz4POAVEbyQXaVy0gOMaKRMAVAOBINcY5+UWD8OmKCIOaXhlDoNwVKNBShQImEwhQo4RAFjBIogRIogRIogRIoQWCCYXqaHJVaWrtl1IfpYp3GiczFqLHQ5kY9m0l0qVM8Txrs+8ZomkhSKpbOzlraolSP15o/EtxoU9gk2iZVujM7HnVe6eUhKaL4aYrWXWMXfd7+dIlScWxpbsjibQiLPm255sH5jYjKOoCEecge5LcTxqokuItZv5F2DID0iR21ALwctslfunNCurKEBRJkgBTZdIDOoVl0CU7FjgsZHpsi+gNoJGlisDlUkC+C8SQHejzOiqCLgXRTNYazw+vg8tsaHZ+DMd7ZlyR5Qix/uOAEgGOhlzy+EPLMMUmyOHVTyQ0wDBlXB2Dw1FzreCZJGfhyIyiDs/qWSEkiarNPxxaX3J1FWcCRLJXidtFW7MO5lmV3AhMMPS8HHsH4oBJmtEcHF+ROUEgD2E/AiVXO98AtSaoJmC4F1AUjXZAD97Bo0R491ApuBRNdVq/FGhz9hPaI48p9w1mI6rVpi1qQ9FmRuRe8iTPaJgfOi6NaTr20zDoYJUfOM2aOHM15EYwBOKbQwHm14wcY5FYgTzi5CHewMPZytO9aIHuj3MY53sF5s3M0S94EFV5bdiLeshQdgdGwc9T0IJC1VROHs4EHSgHY1XKflaFXQQ6y2MpIVIiSYDStgRLOvN/sDDCSImmv7cxaWVuu5z0LxJKU+Y1M9LE4GHOrsWnkXUDx3a5mRR8zRXFsisj5IeiBc0cmPkRxZMBY0BIGeRLIYmJ8smnLDmVuiL5ngWxksUd5JhVqYEzxTv4I1tiSc9Y38OSTgOZwnki0GYhe55Pg1VqjCUnORLf2SWAVb5fIeYPRJ/4JnoFa1THSATTyT3BcQ++f+8DKRwGN299Hltr/+zdWCZRACZRACZSAlEAJDifwRwPBP3uIUqBEg356EvzjmcCf//wFVbAkwfl+5CMAAAAASUVORK5CYII=</Image>
+<Url type="application/x-suggestions+json" method="GET" template="https://ro.wikipedia.org/w/api.php">
+ <Param name="action" value="opensearch"/>
+ <Param name="search" value="{searchTerms}"/>
+</Url>
+<Url type="text/html" method="GET" template="https://ro.wikipedia.org/wiki/Special:Căutare">
+ <Param name="search" value="{searchTerms}"/>
+ <Param name="sourceid" value="Mozilla-search"/>
+</Url>
+<SearchForm>https://ro.wikipedia.org/wiki/Special:Căutare</SearchForm>
+</SearchPlugin>
diff --git a/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-ru.xml b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-ru.xml
new file mode 100644
index 0000000000..33a9a541bd
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-ru.xml
@@ -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/. -->
+
+<SearchPlugin xmlns="http://www.mozilla.org/2006/browser/search/">
+<ShortName>Википедия (ru)</ShortName>
+<InputEncoding>UTF-8</InputEncoding>
+<Image width="16" height="16">data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGAAAABgCAMAAADVRocKAAAA51BMVEUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD////7+/vl5eWxsbH9/f3Ly8tzc3P39/fe3t5cXFzz8/Pt7e3i4uI3NzcaGhoHBwcFBQX5+fnIyMhTU1MXFxcMDAzx8fHX19fFxcXCwsK7u7u1tbWenp6WlpZ8fHxXV1ctLS319fXn5+fV1dWsrKySkpJnZ2cgICDv7+/p6eng4ODQ0NC9vb24uLikpKSPj4+JiYmCgoJiYmJCQkI7OzsyMjIpKSkQEBCoqKigoKCdnZ14eHhubm5PT09LS0tERETk5OTb29unp6c0NDQkJCQOGD7BAAAAB3RSTlMA8si8ZBhlc+JuAAAAAw1JREFUaN7tmtluIjEQRYEhUxd6YYew7xAggRAgCQmB7Ov8//eM3Zg2nXkJvUjz4POAVEbyQXaVy0gOMaKRMAVAOBINcY5+UWD8OmKCIOaXhlDoNwVKNBShQImEwhQo4RAFjBIogRIogRIogRIoQWCCYXqaHJVaWrtl1IfpYp3GiczFqLHQ5kY9m0l0qVM8Txrs+8ZomkhSKpbOzlraolSP15o/EtxoU9gk2iZVujM7HnVe6eUhKaL4aYrWXWMXfd7+dIlScWxpbsjibQiLPm255sH5jYjKOoCEecge5LcTxqokuItZv5F2DID0iR21ALwctslfunNCurKEBRJkgBTZdIDOoVl0CU7FjgsZHpsi+gNoJGlisDlUkC+C8SQHejzOiqCLgXRTNYazw+vg8tsaHZ+DMd7ZlyR5Qix/uOAEgGOhlzy+EPLMMUmyOHVTyQ0wDBlXB2Dw1FzreCZJGfhyIyiDs/qWSEkiarNPxxaX3J1FWcCRLJXidtFW7MO5lmV3AhMMPS8HHsH4oBJmtEcHF+ROUEgD2E/AiVXO98AtSaoJmC4F1AUjXZAD97Bo0R491ApuBRNdVq/FGhz9hPaI48p9w1mI6rVpi1qQ9FmRuRe8iTPaJgfOi6NaTr20zDoYJUfOM2aOHM15EYwBOKbQwHm14wcY5FYgTzi5CHewMPZytO9aIHuj3MY53sF5s3M0S94EFV5bdiLeshQdgdGwc9T0IJC1VROHs4EHSgHY1XKflaFXQQ6y2MpIVIiSYDStgRLOvN/sDDCSImmv7cxaWVuu5z0LxJKU+Y1M9LE4GHOrsWnkXUDx3a5mRR8zRXFsisj5IeiBc0cmPkRxZMBY0BIGeRLIYmJ8smnLDmVuiL5ngWxksUd5JhVqYEzxTv4I1tiSc9Y38OSTgOZwnki0GYhe55Pg1VqjCUnORLf2SWAVb5fIeYPRJ/4JnoFa1THSATTyT3BcQ++f+8DKRwGN299Hltr/+zdWCZRACZRACZSAlEAJDifwRwPBP3uIUqBEg356EvzjmcCf//wFVbAkwfl+5CMAAAAASUVORK5CYII=</Image>
+<Url type="application/x-suggestions+json" method="GET" template="https://ru.wikipedia.org/w/api.php">
+ <Param name="action" value="opensearch"/>
+ <Param name="search" value="{searchTerms}"/>
+</Url>
+<Url type="text/html" method="GET" template="https://ru.wikipedia.org/wiki/Служебная:Поиск">
+ <Param name="search" value="{searchTerms}"/>
+ <Param name="sourceid" value="Mozilla-search"/>
+</Url>
+<SearchForm>https://ru.wikipedia.org/wiki/Служебная:Поиск</SearchForm>
+</SearchPlugin>
diff --git a/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-sk.xml b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-sk.xml
new file mode 100644
index 0000000000..44c3f0326a
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-sk.xml
@@ -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/. -->
+
+<SearchPlugin xmlns="http://www.mozilla.org/2006/browser/search/">
+<ShortName>Wikipédia (sk)</ShortName>
+<InputEncoding>UTF-8</InputEncoding>
+<Image width="16" height="16">data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGAAAABgCAMAAADVRocKAAAA51BMVEUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD////7+/vl5eWxsbH9/f3Ly8tzc3P39/fe3t5cXFzz8/Pt7e3i4uI3NzcaGhoHBwcFBQX5+fnIyMhTU1MXFxcMDAzx8fHX19fFxcXCwsK7u7u1tbWenp6WlpZ8fHxXV1ctLS319fXn5+fV1dWsrKySkpJnZ2cgICDv7+/p6eng4ODQ0NC9vb24uLikpKSPj4+JiYmCgoJiYmJCQkI7OzsyMjIpKSkQEBCoqKigoKCdnZ14eHhubm5PT09LS0tERETk5OTb29unp6c0NDQkJCQOGD7BAAAAB3RSTlMA8si8ZBhlc+JuAAAAAw1JREFUaN7tmtluIjEQRYEhUxd6YYew7xAggRAgCQmB7Ov8//eM3Zg2nXkJvUjz4POAVEbyQXaVy0gOMaKRMAVAOBINcY5+UWD8OmKCIOaXhlDoNwVKNBShQImEwhQo4RAFjBIogRIogRIogRIoQWCCYXqaHJVaWrtl1IfpYp3GiczFqLHQ5kY9m0l0qVM8Txrs+8ZomkhSKpbOzlraolSP15o/EtxoU9gk2iZVujM7HnVe6eUhKaL4aYrWXWMXfd7+dIlScWxpbsjibQiLPm255sH5jYjKOoCEecge5LcTxqokuItZv5F2DID0iR21ALwctslfunNCurKEBRJkgBTZdIDOoVl0CU7FjgsZHpsi+gNoJGlisDlUkC+C8SQHejzOiqCLgXRTNYazw+vg8tsaHZ+DMd7ZlyR5Qix/uOAEgGOhlzy+EPLMMUmyOHVTyQ0wDBlXB2Dw1FzreCZJGfhyIyiDs/qWSEkiarNPxxaX3J1FWcCRLJXidtFW7MO5lmV3AhMMPS8HHsH4oBJmtEcHF+ROUEgD2E/AiVXO98AtSaoJmC4F1AUjXZAD97Bo0R491ApuBRNdVq/FGhz9hPaI48p9w1mI6rVpi1qQ9FmRuRe8iTPaJgfOi6NaTr20zDoYJUfOM2aOHM15EYwBOKbQwHm14wcY5FYgTzi5CHewMPZytO9aIHuj3MY53sF5s3M0S94EFV5bdiLeshQdgdGwc9T0IJC1VROHs4EHSgHY1XKflaFXQQ6y2MpIVIiSYDStgRLOvN/sDDCSImmv7cxaWVuu5z0LxJKU+Y1M9LE4GHOrsWnkXUDx3a5mRR8zRXFsisj5IeiBc0cmPkRxZMBY0BIGeRLIYmJ8smnLDmVuiL5ngWxksUd5JhVqYEzxTv4I1tiSc9Y38OSTgOZwnki0GYhe55Pg1VqjCUnORLf2SWAVb5fIeYPRJ/4JnoFa1THSATTyT3BcQ++f+8DKRwGN299Hltr/+zdWCZRACZRACZSAlEAJDifwRwPBP3uIUqBEg356EvzjmcCf//wFVbAkwfl+5CMAAAAASUVORK5CYII=</Image>
+<Url type="application/x-suggestions+json" method="GET" template="https://sk.wikipedia.org/w/api.php">
+ <Param name="action" value="opensearch"/>
+ <Param name="search" value="{searchTerms}"/>
+</Url>
+<Url type="text/html" method="GET" template="https://sk.wikipedia.org/wiki/Špeciálne:Hľadanie">
+ <Param name="search" value="{searchTerms}"/>
+ <Param name="sourceid" value="Mozilla-search"/>
+</Url>
+<SearchForm>https://sk.wikipedia.org/wiki/Špeciálne:Hľadanie</SearchForm>
+</SearchPlugin>
diff --git a/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-sl.xml b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-sl.xml
new file mode 100644
index 0000000000..7ff7347b0a
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-sl.xml
@@ -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/. -->
+
+<SearchPlugin xmlns="http://www.mozilla.org/2006/browser/search/">
+<ShortName>Wikipedija (sl)</ShortName>
+<InputEncoding>UTF-8</InputEncoding>
+<Image width="16" height="16">data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGAAAABgCAMAAADVRocKAAAA51BMVEUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD////7+/vl5eWxsbH9/f3Ly8tzc3P39/fe3t5cXFzz8/Pt7e3i4uI3NzcaGhoHBwcFBQX5+fnIyMhTU1MXFxcMDAzx8fHX19fFxcXCwsK7u7u1tbWenp6WlpZ8fHxXV1ctLS319fXn5+fV1dWsrKySkpJnZ2cgICDv7+/p6eng4ODQ0NC9vb24uLikpKSPj4+JiYmCgoJiYmJCQkI7OzsyMjIpKSkQEBCoqKigoKCdnZ14eHhubm5PT09LS0tERETk5OTb29unp6c0NDQkJCQOGD7BAAAAB3RSTlMA8si8ZBhlc+JuAAAAAw1JREFUaN7tmtluIjEQRYEhUxd6YYew7xAggRAgCQmB7Ov8//eM3Zg2nXkJvUjz4POAVEbyQXaVy0gOMaKRMAVAOBINcY5+UWD8OmKCIOaXhlDoNwVKNBShQImEwhQo4RAFjBIogRIogRIogRIoQWCCYXqaHJVaWrtl1IfpYp3GiczFqLHQ5kY9m0l0qVM8Txrs+8ZomkhSKpbOzlraolSP15o/EtxoU9gk2iZVujM7HnVe6eUhKaL4aYrWXWMXfd7+dIlScWxpbsjibQiLPm255sH5jYjKOoCEecge5LcTxqokuItZv5F2DID0iR21ALwctslfunNCurKEBRJkgBTZdIDOoVl0CU7FjgsZHpsi+gNoJGlisDlUkC+C8SQHejzOiqCLgXRTNYazw+vg8tsaHZ+DMd7ZlyR5Qix/uOAEgGOhlzy+EPLMMUmyOHVTyQ0wDBlXB2Dw1FzreCZJGfhyIyiDs/qWSEkiarNPxxaX3J1FWcCRLJXidtFW7MO5lmV3AhMMPS8HHsH4oBJmtEcHF+ROUEgD2E/AiVXO98AtSaoJmC4F1AUjXZAD97Bo0R491ApuBRNdVq/FGhz9hPaI48p9w1mI6rVpi1qQ9FmRuRe8iTPaJgfOi6NaTr20zDoYJUfOM2aOHM15EYwBOKbQwHm14wcY5FYgTzi5CHewMPZytO9aIHuj3MY53sF5s3M0S94EFV5bdiLeshQdgdGwc9T0IJC1VROHs4EHSgHY1XKflaFXQQ6y2MpIVIiSYDStgRLOvN/sDDCSImmv7cxaWVuu5z0LxJKU+Y1M9LE4GHOrsWnkXUDx3a5mRR8zRXFsisj5IeiBc0cmPkRxZMBY0BIGeRLIYmJ8smnLDmVuiL5ngWxksUd5JhVqYEzxTv4I1tiSc9Y38OSTgOZwnki0GYhe55Pg1VqjCUnORLf2SWAVb5fIeYPRJ/4JnoFa1THSATTyT3BcQ++f+8DKRwGN299Hltr/+zdWCZRACZRACZSAlEAJDifwRwPBP3uIUqBEg356EvzjmcCf//wFVbAkwfl+5CMAAAAASUVORK5CYII=</Image>
+<Url type="application/x-suggestions+json" method="GET" template="https://sl.wikipedia.org/w/api.php">
+ <Param name="action" value="opensearch"/>
+ <Param name="search" value="{searchTerms}"/>
+</Url>
+<Url type="text/html" method="GET" template="https://sl.wikipedia.org/wiki/Posebno:Iskanje">
+ <Param name="search" value="{searchTerms}"/>
+ <Param name="sourceid" value="Mozilla-search"/>
+</Url>
+<SearchForm>https://sl.wikipedia.org/wiki/Posebno:Iskanje</SearchForm>
+</SearchPlugin>
diff --git a/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-sq.xml b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-sq.xml
new file mode 100644
index 0000000000..c100012f37
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-sq.xml
@@ -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/. -->
+
+<SearchPlugin xmlns="http://www.mozilla.org/2006/browser/search/">
+<ShortName>Wikipedia (sq)</ShortName>
+<InputEncoding>UTF-8</InputEncoding>
+<Image width="16" height="16">data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGAAAABgCAMAAADVRocKAAAA51BMVEUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD////7+/vl5eWxsbH9/f3Ly8tzc3P39/fe3t5cXFzz8/Pt7e3i4uI3NzcaGhoHBwcFBQX5+fnIyMhTU1MXFxcMDAzx8fHX19fFxcXCwsK7u7u1tbWenp6WlpZ8fHxXV1ctLS319fXn5+fV1dWsrKySkpJnZ2cgICDv7+/p6eng4ODQ0NC9vb24uLikpKSPj4+JiYmCgoJiYmJCQkI7OzsyMjIpKSkQEBCoqKigoKCdnZ14eHhubm5PT09LS0tERETk5OTb29unp6c0NDQkJCQOGD7BAAAAB3RSTlMA8si8ZBhlc+JuAAAAAw1JREFUaN7tmtluIjEQRYEhUxd6YYew7xAggRAgCQmB7Ov8//eM3Zg2nXkJvUjz4POAVEbyQXaVy0gOMaKRMAVAOBINcY5+UWD8OmKCIOaXhlDoNwVKNBShQImEwhQo4RAFjBIogRIogRIogRIoQWCCYXqaHJVaWrtl1IfpYp3GiczFqLHQ5kY9m0l0qVM8Txrs+8ZomkhSKpbOzlraolSP15o/EtxoU9gk2iZVujM7HnVe6eUhKaL4aYrWXWMXfd7+dIlScWxpbsjibQiLPm255sH5jYjKOoCEecge5LcTxqokuItZv5F2DID0iR21ALwctslfunNCurKEBRJkgBTZdIDOoVl0CU7FjgsZHpsi+gNoJGlisDlUkC+C8SQHejzOiqCLgXRTNYazw+vg8tsaHZ+DMd7ZlyR5Qix/uOAEgGOhlzy+EPLMMUmyOHVTyQ0wDBlXB2Dw1FzreCZJGfhyIyiDs/qWSEkiarNPxxaX3J1FWcCRLJXidtFW7MO5lmV3AhMMPS8HHsH4oBJmtEcHF+ROUEgD2E/AiVXO98AtSaoJmC4F1AUjXZAD97Bo0R491ApuBRNdVq/FGhz9hPaI48p9w1mI6rVpi1qQ9FmRuRe8iTPaJgfOi6NaTr20zDoYJUfOM2aOHM15EYwBOKbQwHm14wcY5FYgTzi5CHewMPZytO9aIHuj3MY53sF5s3M0S94EFV5bdiLeshQdgdGwc9T0IJC1VROHs4EHSgHY1XKflaFXQQ6y2MpIVIiSYDStgRLOvN/sDDCSImmv7cxaWVuu5z0LxJKU+Y1M9LE4GHOrsWnkXUDx3a5mRR8zRXFsisj5IeiBc0cmPkRxZMBY0BIGeRLIYmJ8smnLDmVuiL5ngWxksUd5JhVqYEzxTv4I1tiSc9Y38OSTgOZwnki0GYhe55Pg1VqjCUnORLf2SWAVb5fIeYPRJ/4JnoFa1THSATTyT3BcQ++f+8DKRwGN299Hltr/+zdWCZRACZRACZSAlEAJDifwRwPBP3uIUqBEg356EvzjmcCf//wFVbAkwfl+5CMAAAAASUVORK5CYII=</Image>
+<Url type="application/x-suggestions+json" method="GET" template="https://sq.wikipedia.org/w/api.php">
+ <Param name="action" value="opensearch"/>
+ <Param name="search" value="{searchTerms}"/>
+</Url>
+<Url type="text/html" method="GET" template="https://sq.wikipedia.org/wiki/Speciale:Kërkim">
+ <Param name="search" value="{searchTerms}"/>
+ <Param name="sourceid" value="Mozilla-search"/>
+</Url>
+<SearchForm>https://sq.wikipedia.org/wiki/Speciale:Kërkim</SearchForm>
+</SearchPlugin>
diff --git a/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-sr.xml b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-sr.xml
new file mode 100644
index 0000000000..3368eea67e
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-sr.xml
@@ -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/. -->
+
+<SearchPlugin xmlns="http://www.mozilla.org/2006/browser/search/">
+<ShortName>Википедија (sr)</ShortName>
+<InputEncoding>UTF-8</InputEncoding>
+<Image width="16" height="16">data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGAAAABgCAMAAADVRocKAAAA51BMVEUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD////7+/vl5eWxsbH9/f3Ly8tzc3P39/fe3t5cXFzz8/Pt7e3i4uI3NzcaGhoHBwcFBQX5+fnIyMhTU1MXFxcMDAzx8fHX19fFxcXCwsK7u7u1tbWenp6WlpZ8fHxXV1ctLS319fXn5+fV1dWsrKySkpJnZ2cgICDv7+/p6eng4ODQ0NC9vb24uLikpKSPj4+JiYmCgoJiYmJCQkI7OzsyMjIpKSkQEBCoqKigoKCdnZ14eHhubm5PT09LS0tERETk5OTb29unp6c0NDQkJCQOGD7BAAAAB3RSTlMA8si8ZBhlc+JuAAAAAw1JREFUaN7tmtluIjEQRYEhUxd6YYew7xAggRAgCQmB7Ov8//eM3Zg2nXkJvUjz4POAVEbyQXaVy0gOMaKRMAVAOBINcY5+UWD8OmKCIOaXhlDoNwVKNBShQImEwhQo4RAFjBIogRIogRIogRIoQWCCYXqaHJVaWrtl1IfpYp3GiczFqLHQ5kY9m0l0qVM8Txrs+8ZomkhSKpbOzlraolSP15o/EtxoU9gk2iZVujM7HnVe6eUhKaL4aYrWXWMXfd7+dIlScWxpbsjibQiLPm255sH5jYjKOoCEecge5LcTxqokuItZv5F2DID0iR21ALwctslfunNCurKEBRJkgBTZdIDOoVl0CU7FjgsZHpsi+gNoJGlisDlUkC+C8SQHejzOiqCLgXRTNYazw+vg8tsaHZ+DMd7ZlyR5Qix/uOAEgGOhlzy+EPLMMUmyOHVTyQ0wDBlXB2Dw1FzreCZJGfhyIyiDs/qWSEkiarNPxxaX3J1FWcCRLJXidtFW7MO5lmV3AhMMPS8HHsH4oBJmtEcHF+ROUEgD2E/AiVXO98AtSaoJmC4F1AUjXZAD97Bo0R491ApuBRNdVq/FGhz9hPaI48p9w1mI6rVpi1qQ9FmRuRe8iTPaJgfOi6NaTr20zDoYJUfOM2aOHM15EYwBOKbQwHm14wcY5FYgTzi5CHewMPZytO9aIHuj3MY53sF5s3M0S94EFV5bdiLeshQdgdGwc9T0IJC1VROHs4EHSgHY1XKflaFXQQ6y2MpIVIiSYDStgRLOvN/sDDCSImmv7cxaWVuu5z0LxJKU+Y1M9LE4GHOrsWnkXUDx3a5mRR8zRXFsisj5IeiBc0cmPkRxZMBY0BIGeRLIYmJ8smnLDmVuiL5ngWxksUd5JhVqYEzxTv4I1tiSc9Y38OSTgOZwnki0GYhe55Pg1VqjCUnORLf2SWAVb5fIeYPRJ/4JnoFa1THSATTyT3BcQ++f+8DKRwGN299Hltr/+zdWCZRACZRACZSAlEAJDifwRwPBP3uIUqBEg356EvzjmcCf//wFVbAkwfl+5CMAAAAASUVORK5CYII=</Image>
+<Url type="application/x-suggestions+json" method="GET" template="https://sr.wikipedia.org/w/api.php">
+ <Param name="action" value="opensearch"/>
+ <Param name="search" value="{searchTerms}"/>
+</Url>
+<Url type="text/html" method="GET" template="https://sr.wikipedia.org/wiki/Посебно:Претражи">
+ <Param name="search" value="{searchTerms}"/>
+ <Param name="sourceid" value="Mozilla-search"/>
+</Url>
+<SearchForm>https://sr.wikipedia.org/wiki/Посебно:Претражи</SearchForm>
+</SearchPlugin>
diff --git a/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-sv-SE.xml b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-sv-SE.xml
new file mode 100644
index 0000000000..3595d01bab
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-sv-SE.xml
@@ -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/. -->
+
+<SearchPlugin xmlns="http://www.mozilla.org/2006/browser/search/">
+<ShortName>Wikipedia (sv)</ShortName>
+<InputEncoding>UTF-8</InputEncoding>
+<Image width="16" height="16">data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGAAAABgCAMAAADVRocKAAAA51BMVEUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD////7+/vl5eWxsbH9/f3Ly8tzc3P39/fe3t5cXFzz8/Pt7e3i4uI3NzcaGhoHBwcFBQX5+fnIyMhTU1MXFxcMDAzx8fHX19fFxcXCwsK7u7u1tbWenp6WlpZ8fHxXV1ctLS319fXn5+fV1dWsrKySkpJnZ2cgICDv7+/p6eng4ODQ0NC9vb24uLikpKSPj4+JiYmCgoJiYmJCQkI7OzsyMjIpKSkQEBCoqKigoKCdnZ14eHhubm5PT09LS0tERETk5OTb29unp6c0NDQkJCQOGD7BAAAAB3RSTlMA8si8ZBhlc+JuAAAAAw1JREFUaN7tmtluIjEQRYEhUxd6YYew7xAggRAgCQmB7Ov8//eM3Zg2nXkJvUjz4POAVEbyQXaVy0gOMaKRMAVAOBINcY5+UWD8OmKCIOaXhlDoNwVKNBShQImEwhQo4RAFjBIogRIogRIogRIoQWCCYXqaHJVaWrtl1IfpYp3GiczFqLHQ5kY9m0l0qVM8Txrs+8ZomkhSKpbOzlraolSP15o/EtxoU9gk2iZVujM7HnVe6eUhKaL4aYrWXWMXfd7+dIlScWxpbsjibQiLPm255sH5jYjKOoCEecge5LcTxqokuItZv5F2DID0iR21ALwctslfunNCurKEBRJkgBTZdIDOoVl0CU7FjgsZHpsi+gNoJGlisDlUkC+C8SQHejzOiqCLgXRTNYazw+vg8tsaHZ+DMd7ZlyR5Qix/uOAEgGOhlzy+EPLMMUmyOHVTyQ0wDBlXB2Dw1FzreCZJGfhyIyiDs/qWSEkiarNPxxaX3J1FWcCRLJXidtFW7MO5lmV3AhMMPS8HHsH4oBJmtEcHF+ROUEgD2E/AiVXO98AtSaoJmC4F1AUjXZAD97Bo0R491ApuBRNdVq/FGhz9hPaI48p9w1mI6rVpi1qQ9FmRuRe8iTPaJgfOi6NaTr20zDoYJUfOM2aOHM15EYwBOKbQwHm14wcY5FYgTzi5CHewMPZytO9aIHuj3MY53sF5s3M0S94EFV5bdiLeshQdgdGwc9T0IJC1VROHs4EHSgHY1XKflaFXQQ6y2MpIVIiSYDStgRLOvN/sDDCSImmv7cxaWVuu5z0LxJKU+Y1M9LE4GHOrsWnkXUDx3a5mRR8zRXFsisj5IeiBc0cmPkRxZMBY0BIGeRLIYmJ8smnLDmVuiL5ngWxksUd5JhVqYEzxTv4I1tiSc9Y38OSTgOZwnki0GYhe55Pg1VqjCUnORLf2SWAVb5fIeYPRJ/4JnoFa1THSATTyT3BcQ++f+8DKRwGN299Hltr/+zdWCZRACZRACZSAlEAJDifwRwPBP3uIUqBEg356EvzjmcCf//wFVbAkwfl+5CMAAAAASUVORK5CYII=</Image>
+<Url type="application/x-suggestions+json" method="GET" template="https://sv.wikipedia.org/w/api.php">
+ <Param name="action" value="opensearch"/>
+ <Param name="search" value="{searchTerms}"/>
+</Url>
+<Url type="text/html" method="GET" template="https://sv.wikipedia.org/wiki/Special:Sök">
+ <Param name="search" value="{searchTerms}"/>
+ <Param name="sourceid" value="Mozilla-search"/>
+</Url>
+<SearchForm>https://sv.wikipedia.org/wiki/Special:Sök</SearchForm>
+</SearchPlugin>
diff --git a/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-ta.xml b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-ta.xml
new file mode 100644
index 0000000000..778e39f733
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-ta.xml
@@ -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/. -->
+
+<SearchPlugin xmlns="http://www.mozilla.org/2006/browser/search/">
+<ShortName>விக்கிப்பீடியா (ta)</ShortName>
+<InputEncoding>UTF-8</InputEncoding>
+<Image width="16" height="16">data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGAAAABgCAMAAADVRocKAAAA51BMVEUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD////7+/vl5eWxsbH9/f3Ly8tzc3P39/fe3t5cXFzz8/Pt7e3i4uI3NzcaGhoHBwcFBQX5+fnIyMhTU1MXFxcMDAzx8fHX19fFxcXCwsK7u7u1tbWenp6WlpZ8fHxXV1ctLS319fXn5+fV1dWsrKySkpJnZ2cgICDv7+/p6eng4ODQ0NC9vb24uLikpKSPj4+JiYmCgoJiYmJCQkI7OzsyMjIpKSkQEBCoqKigoKCdnZ14eHhubm5PT09LS0tERETk5OTb29unp6c0NDQkJCQOGD7BAAAAB3RSTlMA8si8ZBhlc+JuAAAAAw1JREFUaN7tmtluIjEQRYEhUxd6YYew7xAggRAgCQmB7Ov8//eM3Zg2nXkJvUjz4POAVEbyQXaVy0gOMaKRMAVAOBINcY5+UWD8OmKCIOaXhlDoNwVKNBShQImEwhQo4RAFjBIogRIogRIogRIoQWCCYXqaHJVaWrtl1IfpYp3GiczFqLHQ5kY9m0l0qVM8Txrs+8ZomkhSKpbOzlraolSP15o/EtxoU9gk2iZVujM7HnVe6eUhKaL4aYrWXWMXfd7+dIlScWxpbsjibQiLPm255sH5jYjKOoCEecge5LcTxqokuItZv5F2DID0iR21ALwctslfunNCurKEBRJkgBTZdIDOoVl0CU7FjgsZHpsi+gNoJGlisDlUkC+C8SQHejzOiqCLgXRTNYazw+vg8tsaHZ+DMd7ZlyR5Qix/uOAEgGOhlzy+EPLMMUmyOHVTyQ0wDBlXB2Dw1FzreCZJGfhyIyiDs/qWSEkiarNPxxaX3J1FWcCRLJXidtFW7MO5lmV3AhMMPS8HHsH4oBJmtEcHF+ROUEgD2E/AiVXO98AtSaoJmC4F1AUjXZAD97Bo0R491ApuBRNdVq/FGhz9hPaI48p9w1mI6rVpi1qQ9FmRuRe8iTPaJgfOi6NaTr20zDoYJUfOM2aOHM15EYwBOKbQwHm14wcY5FYgTzi5CHewMPZytO9aIHuj3MY53sF5s3M0S94EFV5bdiLeshQdgdGwc9T0IJC1VROHs4EHSgHY1XKflaFXQQ6y2MpIVIiSYDStgRLOvN/sDDCSImmv7cxaWVuu5z0LxJKU+Y1M9LE4GHOrsWnkXUDx3a5mRR8zRXFsisj5IeiBc0cmPkRxZMBY0BIGeRLIYmJ8smnLDmVuiL5ngWxksUd5JhVqYEzxTv4I1tiSc9Y38OSTgOZwnki0GYhe55Pg1VqjCUnORLf2SWAVb5fIeYPRJ/4JnoFa1THSATTyT3BcQ++f+8DKRwGN299Hltr/+zdWCZRACZRACZSAlEAJDifwRwPBP3uIUqBEg356EvzjmcCf//wFVbAkwfl+5CMAAAAASUVORK5CYII=</Image>
+<Url type="application/x-suggestions+json" method="GET" template="https://ta.wikipedia.org/w/api.php">
+ <Param name="action" value="opensearch"/>
+ <Param name="search" value="{searchTerms}"/>
+</Url>
+<Url type="text/html" method="GET" template="https://ta.wikipedia.org/wiki/சிறப்பு:Search">
+ <Param name="search" value="{searchTerms}"/>
+ <Param name="sourceid" value="Mozilla-search"/>
+</Url>
+<SearchForm>https://ta.wikipedia.org/wiki/சிறப்பு:Search</SearchForm>
+</SearchPlugin>
diff --git a/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-te.xml b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-te.xml
new file mode 100644
index 0000000000..79c2b04e8c
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-te.xml
@@ -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/. -->
+
+<SearchPlugin xmlns="http://www.mozilla.org/2006/browser/search/">
+<ShortName>వికీపీడియా (te)</ShortName>
+<InputEncoding>UTF-8</InputEncoding>
+<Image width="16" height="16">data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGAAAABgCAMAAADVRocKAAAA51BMVEUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD////7+/vl5eWxsbH9/f3Ly8tzc3P39/fe3t5cXFzz8/Pt7e3i4uI3NzcaGhoHBwcFBQX5+fnIyMhTU1MXFxcMDAzx8fHX19fFxcXCwsK7u7u1tbWenp6WlpZ8fHxXV1ctLS319fXn5+fV1dWsrKySkpJnZ2cgICDv7+/p6eng4ODQ0NC9vb24uLikpKSPj4+JiYmCgoJiYmJCQkI7OzsyMjIpKSkQEBCoqKigoKCdnZ14eHhubm5PT09LS0tERETk5OTb29unp6c0NDQkJCQOGD7BAAAAB3RSTlMA8si8ZBhlc+JuAAAAAw1JREFUaN7tmtluIjEQRYEhUxd6YYew7xAggRAgCQmB7Ov8//eM3Zg2nXkJvUjz4POAVEbyQXaVy0gOMaKRMAVAOBINcY5+UWD8OmKCIOaXhlDoNwVKNBShQImEwhQo4RAFjBIogRIogRIogRIoQWCCYXqaHJVaWrtl1IfpYp3GiczFqLHQ5kY9m0l0qVM8Txrs+8ZomkhSKpbOzlraolSP15o/EtxoU9gk2iZVujM7HnVe6eUhKaL4aYrWXWMXfd7+dIlScWxpbsjibQiLPm255sH5jYjKOoCEecge5LcTxqokuItZv5F2DID0iR21ALwctslfunNCurKEBRJkgBTZdIDOoVl0CU7FjgsZHpsi+gNoJGlisDlUkC+C8SQHejzOiqCLgXRTNYazw+vg8tsaHZ+DMd7ZlyR5Qix/uOAEgGOhlzy+EPLMMUmyOHVTyQ0wDBlXB2Dw1FzreCZJGfhyIyiDs/qWSEkiarNPxxaX3J1FWcCRLJXidtFW7MO5lmV3AhMMPS8HHsH4oBJmtEcHF+ROUEgD2E/AiVXO98AtSaoJmC4F1AUjXZAD97Bo0R491ApuBRNdVq/FGhz9hPaI48p9w1mI6rVpi1qQ9FmRuRe8iTPaJgfOi6NaTr20zDoYJUfOM2aOHM15EYwBOKbQwHm14wcY5FYgTzi5CHewMPZytO9aIHuj3MY53sF5s3M0S94EFV5bdiLeshQdgdGwc9T0IJC1VROHs4EHSgHY1XKflaFXQQ6y2MpIVIiSYDStgRLOvN/sDDCSImmv7cxaWVuu5z0LxJKU+Y1M9LE4GHOrsWnkXUDx3a5mRR8zRXFsisj5IeiBc0cmPkRxZMBY0BIGeRLIYmJ8smnLDmVuiL5ngWxksUd5JhVqYEzxTv4I1tiSc9Y38OSTgOZwnki0GYhe55Pg1VqjCUnORLf2SWAVb5fIeYPRJ/4JnoFa1THSATTyT3BcQ++f+8DKRwGN299Hltr/+zdWCZRACZRACZSAlEAJDifwRwPBP3uIUqBEg356EvzjmcCf//wFVbAkwfl+5CMAAAAASUVORK5CYII=</Image>
+<Url type="application/x-suggestions+json" method="GET" template="https://te.wikipedia.org/w/api.php">
+ <Param name="action" value="opensearch"/>
+ <Param name="search" value="{searchTerms}"/>
+</Url>
+<Url type="text/html" method="GET" template="https://te.wikipedia.org/wiki/ప్రత్యేక:అన్వేషణ">
+ <Param name="search" value="{searchTerms}"/>
+ <Param name="sourceid" value="Mozilla-search"/>
+</Url>
+<SearchForm>https://te.wikipedia.org/wiki/ప్రత్యేక:అన్వేషణ</SearchForm>
+</SearchPlugin>
diff --git a/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-th.xml b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-th.xml
new file mode 100644
index 0000000000..cbcf5319c9
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-th.xml
@@ -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/. -->
+
+<SearchPlugin xmlns="http://www.mozilla.org/2006/browser/search/">
+<ShortName>วิกิพีเดีย</ShortName>
+<InputEncoding>UTF-8</InputEncoding>
+<Image width="16" height="16">data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGAAAABgCAMAAADVRocKAAAA51BMVEUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD////7+/vl5eWxsbH9/f3Ly8tzc3P39/fe3t5cXFzz8/Pt7e3i4uI3NzcaGhoHBwcFBQX5+fnIyMhTU1MXFxcMDAzx8fHX19fFxcXCwsK7u7u1tbWenp6WlpZ8fHxXV1ctLS319fXn5+fV1dWsrKySkpJnZ2cgICDv7+/p6eng4ODQ0NC9vb24uLikpKSPj4+JiYmCgoJiYmJCQkI7OzsyMjIpKSkQEBCoqKigoKCdnZ14eHhubm5PT09LS0tERETk5OTb29unp6c0NDQkJCQOGD7BAAAAB3RSTlMA8si8ZBhlc+JuAAAAAw1JREFUaN7tmtluIjEQRYEhUxd6YYew7xAggRAgCQmB7Ov8//eM3Zg2nXkJvUjz4POAVEbyQXaVy0gOMaKRMAVAOBINcY5+UWD8OmKCIOaXhlDoNwVKNBShQImEwhQo4RAFjBIogRIogRIogRIoQWCCYXqaHJVaWrtl1IfpYp3GiczFqLHQ5kY9m0l0qVM8Txrs+8ZomkhSKpbOzlraolSP15o/EtxoU9gk2iZVujM7HnVe6eUhKaL4aYrWXWMXfd7+dIlScWxpbsjibQiLPm255sH5jYjKOoCEecge5LcTxqokuItZv5F2DID0iR21ALwctslfunNCurKEBRJkgBTZdIDOoVl0CU7FjgsZHpsi+gNoJGlisDlUkC+C8SQHejzOiqCLgXRTNYazw+vg8tsaHZ+DMd7ZlyR5Qix/uOAEgGOhlzy+EPLMMUmyOHVTyQ0wDBlXB2Dw1FzreCZJGfhyIyiDs/qWSEkiarNPxxaX3J1FWcCRLJXidtFW7MO5lmV3AhMMPS8HHsH4oBJmtEcHF+ROUEgD2E/AiVXO98AtSaoJmC4F1AUjXZAD97Bo0R491ApuBRNdVq/FGhz9hPaI48p9w1mI6rVpi1qQ9FmRuRe8iTPaJgfOi6NaTr20zDoYJUfOM2aOHM15EYwBOKbQwHm14wcY5FYgTzi5CHewMPZytO9aIHuj3MY53sF5s3M0S94EFV5bdiLeshQdgdGwc9T0IJC1VROHs4EHSgHY1XKflaFXQQ6y2MpIVIiSYDStgRLOvN/sDDCSImmv7cxaWVuu5z0LxJKU+Y1M9LE4GHOrsWnkXUDx3a5mRR8zRXFsisj5IeiBc0cmPkRxZMBY0BIGeRLIYmJ8smnLDmVuiL5ngWxksUd5JhVqYEzxTv4I1tiSc9Y38OSTgOZwnki0GYhe55Pg1VqjCUnORLf2SWAVb5fIeYPRJ/4JnoFa1THSATTyT3BcQ++f+8DKRwGN299Hltr/+zdWCZRACZRACZSAlEAJDifwRwPBP3uIUqBEg356EvzjmcCf//wFVbAkwfl+5CMAAAAASUVORK5CYII=</Image>
+<Url type="application/x-suggestions+json" method="GET" template="https://th.wikipedia.org/w/api.php">
+ <Param name="action" value="opensearch"/>
+ <Param name="search" value="{searchTerms}"/>
+</Url>
+<Url type="text/html" method="GET" template="https://th.wikipedia.org/wiki/พิเศษ:ค้นหา">
+ <Param name="search" value="{searchTerms}"/>
+ <Param name="sourceid" value="Mozilla-search"/>
+</Url>
+<SearchForm>https://th.wikipedia.org/wiki/พิเศษ:ค้นหา</SearchForm>
+</SearchPlugin>
diff --git a/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-tr.xml b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-tr.xml
new file mode 100644
index 0000000000..4bc9e189d3
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-tr.xml
@@ -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/. -->
+
+<SearchPlugin xmlns="http://www.mozilla.org/2006/browser/search/">
+<ShortName>Wikipedia (tr)</ShortName>
+<InputEncoding>UTF-8</InputEncoding>
+<Image width="16" height="16">data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGAAAABgCAMAAADVRocKAAAA51BMVEUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD////7+/vl5eWxsbH9/f3Ly8tzc3P39/fe3t5cXFzz8/Pt7e3i4uI3NzcaGhoHBwcFBQX5+fnIyMhTU1MXFxcMDAzx8fHX19fFxcXCwsK7u7u1tbWenp6WlpZ8fHxXV1ctLS319fXn5+fV1dWsrKySkpJnZ2cgICDv7+/p6eng4ODQ0NC9vb24uLikpKSPj4+JiYmCgoJiYmJCQkI7OzsyMjIpKSkQEBCoqKigoKCdnZ14eHhubm5PT09LS0tERETk5OTb29unp6c0NDQkJCQOGD7BAAAAB3RSTlMA8si8ZBhlc+JuAAAAAw1JREFUaN7tmtluIjEQRYEhUxd6YYew7xAggRAgCQmB7Ov8//eM3Zg2nXkJvUjz4POAVEbyQXaVy0gOMaKRMAVAOBINcY5+UWD8OmKCIOaXhlDoNwVKNBShQImEwhQo4RAFjBIogRIogRIogRIoQWCCYXqaHJVaWrtl1IfpYp3GiczFqLHQ5kY9m0l0qVM8Txrs+8ZomkhSKpbOzlraolSP15o/EtxoU9gk2iZVujM7HnVe6eUhKaL4aYrWXWMXfd7+dIlScWxpbsjibQiLPm255sH5jYjKOoCEecge5LcTxqokuItZv5F2DID0iR21ALwctslfunNCurKEBRJkgBTZdIDOoVl0CU7FjgsZHpsi+gNoJGlisDlUkC+C8SQHejzOiqCLgXRTNYazw+vg8tsaHZ+DMd7ZlyR5Qix/uOAEgGOhlzy+EPLMMUmyOHVTyQ0wDBlXB2Dw1FzreCZJGfhyIyiDs/qWSEkiarNPxxaX3J1FWcCRLJXidtFW7MO5lmV3AhMMPS8HHsH4oBJmtEcHF+ROUEgD2E/AiVXO98AtSaoJmC4F1AUjXZAD97Bo0R491ApuBRNdVq/FGhz9hPaI48p9w1mI6rVpi1qQ9FmRuRe8iTPaJgfOi6NaTr20zDoYJUfOM2aOHM15EYwBOKbQwHm14wcY5FYgTzi5CHewMPZytO9aIHuj3MY53sF5s3M0S94EFV5bdiLeshQdgdGwc9T0IJC1VROHs4EHSgHY1XKflaFXQQ6y2MpIVIiSYDStgRLOvN/sDDCSImmv7cxaWVuu5z0LxJKU+Y1M9LE4GHOrsWnkXUDx3a5mRR8zRXFsisj5IeiBc0cmPkRxZMBY0BIGeRLIYmJ8smnLDmVuiL5ngWxksUd5JhVqYEzxTv4I1tiSc9Y38OSTgOZwnki0GYhe55Pg1VqjCUnORLf2SWAVb5fIeYPRJ/4JnoFa1THSATTyT3BcQ++f+8DKRwGN299Hltr/+zdWCZRACZRACZSAlEAJDifwRwPBP3uIUqBEg356EvzjmcCf//wFVbAkwfl+5CMAAAAASUVORK5CYII=</Image>
+<Url type="application/x-suggestions+json" method="GET" template="https://tr.wikipedia.org/w/api.php">
+ <Param name="action" value="opensearch"/>
+ <Param name="search" value="{searchTerms}"/>
+</Url>
+<Url type="text/html" method="GET" template="https://tr.wikipedia.org/wiki/Özel:Ara">
+ <Param name="search" value="{searchTerms}"/>
+ <Param name="sourceid" value="Mozilla-search"/>
+</Url>
+<SearchForm>https://tr.wikipedia.org/wiki/Özel:Ara</SearchForm>
+</SearchPlugin>
diff --git a/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-uk.xml b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-uk.xml
new file mode 100644
index 0000000000..bc2f4741a8
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-uk.xml
@@ -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/. -->
+
+<SearchPlugin xmlns="http://www.mozilla.org/2006/browser/search/">
+<ShortName>Вікіпедія</ShortName>
+<InputEncoding>UTF-8</InputEncoding>
+<Image width="16" height="16">data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGAAAABgCAMAAADVRocKAAAA51BMVEUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD////7+/vl5eWxsbH9/f3Ly8tzc3P39/fe3t5cXFzz8/Pt7e3i4uI3NzcaGhoHBwcFBQX5+fnIyMhTU1MXFxcMDAzx8fHX19fFxcXCwsK7u7u1tbWenp6WlpZ8fHxXV1ctLS319fXn5+fV1dWsrKySkpJnZ2cgICDv7+/p6eng4ODQ0NC9vb24uLikpKSPj4+JiYmCgoJiYmJCQkI7OzsyMjIpKSkQEBCoqKigoKCdnZ14eHhubm5PT09LS0tERETk5OTb29unp6c0NDQkJCQOGD7BAAAAB3RSTlMA8si8ZBhlc+JuAAAAAw1JREFUaN7tmtluIjEQRYEhUxd6YYew7xAggRAgCQmB7Ov8//eM3Zg2nXkJvUjz4POAVEbyQXaVy0gOMaKRMAVAOBINcY5+UWD8OmKCIOaXhlDoNwVKNBShQImEwhQo4RAFjBIogRIogRIogRIoQWCCYXqaHJVaWrtl1IfpYp3GiczFqLHQ5kY9m0l0qVM8Txrs+8ZomkhSKpbOzlraolSP15o/EtxoU9gk2iZVujM7HnVe6eUhKaL4aYrWXWMXfd7+dIlScWxpbsjibQiLPm255sH5jYjKOoCEecge5LcTxqokuItZv5F2DID0iR21ALwctslfunNCurKEBRJkgBTZdIDOoVl0CU7FjgsZHpsi+gNoJGlisDlUkC+C8SQHejzOiqCLgXRTNYazw+vg8tsaHZ+DMd7ZlyR5Qix/uOAEgGOhlzy+EPLMMUmyOHVTyQ0wDBlXB2Dw1FzreCZJGfhyIyiDs/qWSEkiarNPxxaX3J1FWcCRLJXidtFW7MO5lmV3AhMMPS8HHsH4oBJmtEcHF+ROUEgD2E/AiVXO98AtSaoJmC4F1AUjXZAD97Bo0R491ApuBRNdVq/FGhz9hPaI48p9w1mI6rVpi1qQ9FmRuRe8iTPaJgfOi6NaTr20zDoYJUfOM2aOHM15EYwBOKbQwHm14wcY5FYgTzi5CHewMPZytO9aIHuj3MY53sF5s3M0S94EFV5bdiLeshQdgdGwc9T0IJC1VROHs4EHSgHY1XKflaFXQQ6y2MpIVIiSYDStgRLOvN/sDDCSImmv7cxaWVuu5z0LxJKU+Y1M9LE4GHOrsWnkXUDx3a5mRR8zRXFsisj5IeiBc0cmPkRxZMBY0BIGeRLIYmJ8smnLDmVuiL5ngWxksUd5JhVqYEzxTv4I1tiSc9Y38OSTgOZwnki0GYhe55Pg1VqjCUnORLf2SWAVb5fIeYPRJ/4JnoFa1THSATTyT3BcQ++f+8DKRwGN299Hltr/+zdWCZRACZRACZSAlEAJDifwRwPBP3uIUqBEg356EvzjmcCf//wFVbAkwfl+5CMAAAAASUVORK5CYII=</Image>
+<Url type="application/x-suggestions+json" method="GET" template="https://uk.wikipedia.org/w/api.php">
+ <Param name="action" value="opensearch"/>
+ <Param name="search" value="{searchTerms}"/>
+</Url>
+<Url type="text/html" method="GET" template="https://uk.wikipedia.org/wiki/Спеціальна:Пошук">
+ <Param name="search" value="{searchTerms}"/>
+ <Param name="sourceid" value="Mozilla-search"/>
+</Url>
+<SearchForm>https://uk.wikipedia.org/wiki/Спеціальна:Пошук</SearchForm>
+</SearchPlugin>
diff --git a/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-ur.xml b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-ur.xml
new file mode 100644
index 0000000000..e4b0c8a616
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-ur.xml
@@ -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/. -->
+
+<SearchPlugin xmlns="http://www.mozilla.org/2006/browser/search/">
+<ShortName>ویکیپیڈیا (ur)</ShortName>
+<InputEncoding>UTF-8</InputEncoding>
+<Image width="16" height="16">data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGAAAABgCAMAAADVRocKAAAA51BMVEUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD////7+/vl5eWxsbH9/f3Ly8tzc3P39/fe3t5cXFzz8/Pt7e3i4uI3NzcaGhoHBwcFBQX5+fnIyMhTU1MXFxcMDAzx8fHX19fFxcXCwsK7u7u1tbWenp6WlpZ8fHxXV1ctLS319fXn5+fV1dWsrKySkpJnZ2cgICDv7+/p6eng4ODQ0NC9vb24uLikpKSPj4+JiYmCgoJiYmJCQkI7OzsyMjIpKSkQEBCoqKigoKCdnZ14eHhubm5PT09LS0tERETk5OTb29unp6c0NDQkJCQOGD7BAAAAB3RSTlMA8si8ZBhlc+JuAAAAAw1JREFUaN7tmtluIjEQRYEhUxd6YYew7xAggRAgCQmB7Ov8//eM3Zg2nXkJvUjz4POAVEbyQXaVy0gOMaKRMAVAOBINcY5+UWD8OmKCIOaXhlDoNwVKNBShQImEwhQo4RAFjBIogRIogRIogRIoQWCCYXqaHJVaWrtl1IfpYp3GiczFqLHQ5kY9m0l0qVM8Txrs+8ZomkhSKpbOzlraolSP15o/EtxoU9gk2iZVujM7HnVe6eUhKaL4aYrWXWMXfd7+dIlScWxpbsjibQiLPm255sH5jYjKOoCEecge5LcTxqokuItZv5F2DID0iR21ALwctslfunNCurKEBRJkgBTZdIDOoVl0CU7FjgsZHpsi+gNoJGlisDlUkC+C8SQHejzOiqCLgXRTNYazw+vg8tsaHZ+DMd7ZlyR5Qix/uOAEgGOhlzy+EPLMMUmyOHVTyQ0wDBlXB2Dw1FzreCZJGfhyIyiDs/qWSEkiarNPxxaX3J1FWcCRLJXidtFW7MO5lmV3AhMMPS8HHsH4oBJmtEcHF+ROUEgD2E/AiVXO98AtSaoJmC4F1AUjXZAD97Bo0R491ApuBRNdVq/FGhz9hPaI48p9w1mI6rVpi1qQ9FmRuRe8iTPaJgfOi6NaTr20zDoYJUfOM2aOHM15EYwBOKbQwHm14wcY5FYgTzi5CHewMPZytO9aIHuj3MY53sF5s3M0S94EFV5bdiLeshQdgdGwc9T0IJC1VROHs4EHSgHY1XKflaFXQQ6y2MpIVIiSYDStgRLOvN/sDDCSImmv7cxaWVuu5z0LxJKU+Y1M9LE4GHOrsWnkXUDx3a5mRR8zRXFsisj5IeiBc0cmPkRxZMBY0BIGeRLIYmJ8smnLDmVuiL5ngWxksUd5JhVqYEzxTv4I1tiSc9Y38OSTgOZwnki0GYhe55Pg1VqjCUnORLf2SWAVb5fIeYPRJ/4JnoFa1THSATTyT3BcQ++f+8DKRwGN299Hltr/+zdWCZRACZRACZSAlEAJDifwRwPBP3uIUqBEg356EvzjmcCf//wFVbAkwfl+5CMAAAAASUVORK5CYII=</Image>
+<Url type="application/x-suggestions+json" method="GET" template="https://ur.wikipedia.org/w/api.php">
+ <Param name="action" value="opensearch"/>
+ <Param name="search" value="{searchTerms}"/>
+</Url>
+<Url type="text/html" method="GET" template="https://ur.wikipedia.org/wiki/خاص:تلاش">
+ <Param name="search" value="{searchTerms}"/>
+ <Param name="sourceid" value="Mozilla-search"/>
+</Url>
+<SearchForm>https://ur.wikipedia.org/wiki/خاص:تلاش</SearchForm>
+</SearchPlugin>
diff --git a/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-uz.xml b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-uz.xml
new file mode 100644
index 0000000000..a33e6a4d82
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-uz.xml
@@ -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/. -->
+
+<SearchPlugin xmlns="http://www.mozilla.org/2006/browser/search/">
+<ShortName>Vikipediya (uz)</ShortName>
+<InputEncoding>UTF-8</InputEncoding>
+<Image width="16" height="16">data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGAAAABgCAMAAADVRocKAAAA51BMVEUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD////7+/vl5eWxsbH9/f3Ly8tzc3P39/fe3t5cXFzz8/Pt7e3i4uI3NzcaGhoHBwcFBQX5+fnIyMhTU1MXFxcMDAzx8fHX19fFxcXCwsK7u7u1tbWenp6WlpZ8fHxXV1ctLS319fXn5+fV1dWsrKySkpJnZ2cgICDv7+/p6eng4ODQ0NC9vb24uLikpKSPj4+JiYmCgoJiYmJCQkI7OzsyMjIpKSkQEBCoqKigoKCdnZ14eHhubm5PT09LS0tERETk5OTb29unp6c0NDQkJCQOGD7BAAAAB3RSTlMA8si8ZBhlc+JuAAAAAw1JREFUaN7tmtluIjEQRYEhUxd6YYew7xAggRAgCQmB7Ov8//eM3Zg2nXkJvUjz4POAVEbyQXaVy0gOMaKRMAVAOBINcY5+UWD8OmKCIOaXhlDoNwVKNBShQImEwhQo4RAFjBIogRIogRIogRIoQWCCYXqaHJVaWrtl1IfpYp3GiczFqLHQ5kY9m0l0qVM8Txrs+8ZomkhSKpbOzlraolSP15o/EtxoU9gk2iZVujM7HnVe6eUhKaL4aYrWXWMXfd7+dIlScWxpbsjibQiLPm255sH5jYjKOoCEecge5LcTxqokuItZv5F2DID0iR21ALwctslfunNCurKEBRJkgBTZdIDOoVl0CU7FjgsZHpsi+gNoJGlisDlUkC+C8SQHejzOiqCLgXRTNYazw+vg8tsaHZ+DMd7ZlyR5Qix/uOAEgGOhlzy+EPLMMUmyOHVTyQ0wDBlXB2Dw1FzreCZJGfhyIyiDs/qWSEkiarNPxxaX3J1FWcCRLJXidtFW7MO5lmV3AhMMPS8HHsH4oBJmtEcHF+ROUEgD2E/AiVXO98AtSaoJmC4F1AUjXZAD97Bo0R491ApuBRNdVq/FGhz9hPaI48p9w1mI6rVpi1qQ9FmRuRe8iTPaJgfOi6NaTr20zDoYJUfOM2aOHM15EYwBOKbQwHm14wcY5FYgTzi5CHewMPZytO9aIHuj3MY53sF5s3M0S94EFV5bdiLeshQdgdGwc9T0IJC1VROHs4EHSgHY1XKflaFXQQ6y2MpIVIiSYDStgRLOvN/sDDCSImmv7cxaWVuu5z0LxJKU+Y1M9LE4GHOrsWnkXUDx3a5mRR8zRXFsisj5IeiBc0cmPkRxZMBY0BIGeRLIYmJ8smnLDmVuiL5ngWxksUd5JhVqYEzxTv4I1tiSc9Y38OSTgOZwnki0GYhe55Pg1VqjCUnORLf2SWAVb5fIeYPRJ/4JnoFa1THSATTyT3BcQ++f+8DKRwGN299Hltr/+zdWCZRACZRACZSAlEAJDifwRwPBP3uIUqBEg356EvzjmcCf//wFVbAkwfl+5CMAAAAASUVORK5CYII=</Image>
+<Url type="application/x-suggestions+json" method="GET" template="https://uz.wikipedia.org/w/api.php">
+ <Param name="action" value="opensearch"/>
+ <Param name="search" value="{searchTerms}"/>
+</Url>
+<Url type="text/html" method="GET" template="https://uz.wikipedia.org/wiki/Maxsus:Search">
+ <Param name="search" value="{searchTerms}"/>
+ <Param name="sourceid" value="Mozilla-search"/>
+</Url>
+<SearchForm>https://uz.wikipedia.org/wiki/Maxsus:Search</SearchForm>
+</SearchPlugin>
diff --git a/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-vi.xml b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-vi.xml
new file mode 100644
index 0000000000..e3ac224fd9
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-vi.xml
@@ -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/. -->
+
+<SearchPlugin xmlns="http://www.mozilla.org/2006/browser/search/">
+<ShortName>Wikipedia (vi)</ShortName>
+<InputEncoding>UTF-8</InputEncoding>
+<Image width="16" height="16">data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGAAAABgCAMAAADVRocKAAAA51BMVEUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD////7+/vl5eWxsbH9/f3Ly8tzc3P39/fe3t5cXFzz8/Pt7e3i4uI3NzcaGhoHBwcFBQX5+fnIyMhTU1MXFxcMDAzx8fHX19fFxcXCwsK7u7u1tbWenp6WlpZ8fHxXV1ctLS319fXn5+fV1dWsrKySkpJnZ2cgICDv7+/p6eng4ODQ0NC9vb24uLikpKSPj4+JiYmCgoJiYmJCQkI7OzsyMjIpKSkQEBCoqKigoKCdnZ14eHhubm5PT09LS0tERETk5OTb29unp6c0NDQkJCQOGD7BAAAAB3RSTlMA8si8ZBhlc+JuAAAAAw1JREFUaN7tmtluIjEQRYEhUxd6YYew7xAggRAgCQmB7Ov8//eM3Zg2nXkJvUjz4POAVEbyQXaVy0gOMaKRMAVAOBINcY5+UWD8OmKCIOaXhlDoNwVKNBShQImEwhQo4RAFjBIogRIogRIogRIoQWCCYXqaHJVaWrtl1IfpYp3GiczFqLHQ5kY9m0l0qVM8Txrs+8ZomkhSKpbOzlraolSP15o/EtxoU9gk2iZVujM7HnVe6eUhKaL4aYrWXWMXfd7+dIlScWxpbsjibQiLPm255sH5jYjKOoCEecge5LcTxqokuItZv5F2DID0iR21ALwctslfunNCurKEBRJkgBTZdIDOoVl0CU7FjgsZHpsi+gNoJGlisDlUkC+C8SQHejzOiqCLgXRTNYazw+vg8tsaHZ+DMd7ZlyR5Qix/uOAEgGOhlzy+EPLMMUmyOHVTyQ0wDBlXB2Dw1FzreCZJGfhyIyiDs/qWSEkiarNPxxaX3J1FWcCRLJXidtFW7MO5lmV3AhMMPS8HHsH4oBJmtEcHF+ROUEgD2E/AiVXO98AtSaoJmC4F1AUjXZAD97Bo0R491ApuBRNdVq/FGhz9hPaI48p9w1mI6rVpi1qQ9FmRuRe8iTPaJgfOi6NaTr20zDoYJUfOM2aOHM15EYwBOKbQwHm14wcY5FYgTzi5CHewMPZytO9aIHuj3MY53sF5s3M0S94EFV5bdiLeshQdgdGwc9T0IJC1VROHs4EHSgHY1XKflaFXQQ6y2MpIVIiSYDStgRLOvN/sDDCSImmv7cxaWVuu5z0LxJKU+Y1M9LE4GHOrsWnkXUDx3a5mRR8zRXFsisj5IeiBc0cmPkRxZMBY0BIGeRLIYmJ8smnLDmVuiL5ngWxksUd5JhVqYEzxTv4I1tiSc9Y38OSTgOZwnki0GYhe55Pg1VqjCUnORLf2SWAVb5fIeYPRJ/4JnoFa1THSATTyT3BcQ++f+8DKRwGN299Hltr/+zdWCZRACZRACZSAlEAJDifwRwPBP3uIUqBEg356EvzjmcCf//wFVbAkwfl+5CMAAAAASUVORK5CYII=</Image>
+<Url type="application/x-suggestions+json" method="get" template="https://vi.wikipedia.org/w/api.php">
+ <Param name="action" value="opensearch"/>
+ <Param name="search" value="{searchTerms}"/>
+</Url>
+<Url type="text/html" method="get" template="https://vi.wikipedia.org/wiki/Đặc_biệt:Tìm_kiếm">
+ <Param name="search" value="{searchTerms}"/>
+ <Param name="sourceid" value="Mozilla-search"/>
+</Url>
+<SearchForm>https://vi.wikipedia.org/wiki/Đặc_biệt:Tìm_kiếm</SearchForm>
+</SearchPlugin>
diff --git a/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-wo.xml b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-wo.xml
new file mode 100644
index 0000000000..39caa9839b
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-wo.xml
@@ -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/. -->
+
+<SearchPlugin xmlns="http://www.mozilla.org/2006/browser/search/">
+<ShortName>Wikipedia (wo)</ShortName>
+<InputEncoding>UTF-8</InputEncoding>
+<Image width="16" height="16">data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGAAAABgCAMAAADVRocKAAAA51BMVEUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD////7+/vl5eWxsbH9/f3Ly8tzc3P39/fe3t5cXFzz8/Pt7e3i4uI3NzcaGhoHBwcFBQX5+fnIyMhTU1MXFxcMDAzx8fHX19fFxcXCwsK7u7u1tbWenp6WlpZ8fHxXV1ctLS319fXn5+fV1dWsrKySkpJnZ2cgICDv7+/p6eng4ODQ0NC9vb24uLikpKSPj4+JiYmCgoJiYmJCQkI7OzsyMjIpKSkQEBCoqKigoKCdnZ14eHhubm5PT09LS0tERETk5OTb29unp6c0NDQkJCQOGD7BAAAAB3RSTlMA8si8ZBhlc+JuAAAAAw1JREFUaN7tmtluIjEQRYEhUxd6YYew7xAggRAgCQmB7Ov8//eM3Zg2nXkJvUjz4POAVEbyQXaVy0gOMaKRMAVAOBINcY5+UWD8OmKCIOaXhlDoNwVKNBShQImEwhQo4RAFjBIogRIogRIogRIoQWCCYXqaHJVaWrtl1IfpYp3GiczFqLHQ5kY9m0l0qVM8Txrs+8ZomkhSKpbOzlraolSP15o/EtxoU9gk2iZVujM7HnVe6eUhKaL4aYrWXWMXfd7+dIlScWxpbsjibQiLPm255sH5jYjKOoCEecge5LcTxqokuItZv5F2DID0iR21ALwctslfunNCurKEBRJkgBTZdIDOoVl0CU7FjgsZHpsi+gNoJGlisDlUkC+C8SQHejzOiqCLgXRTNYazw+vg8tsaHZ+DMd7ZlyR5Qix/uOAEgGOhlzy+EPLMMUmyOHVTyQ0wDBlXB2Dw1FzreCZJGfhyIyiDs/qWSEkiarNPxxaX3J1FWcCRLJXidtFW7MO5lmV3AhMMPS8HHsH4oBJmtEcHF+ROUEgD2E/AiVXO98AtSaoJmC4F1AUjXZAD97Bo0R491ApuBRNdVq/FGhz9hPaI48p9w1mI6rVpi1qQ9FmRuRe8iTPaJgfOi6NaTr20zDoYJUfOM2aOHM15EYwBOKbQwHm14wcY5FYgTzi5CHewMPZytO9aIHuj3MY53sF5s3M0S94EFV5bdiLeshQdgdGwc9T0IJC1VROHs4EHSgHY1XKflaFXQQ6y2MpIVIiSYDStgRLOvN/sDDCSImmv7cxaWVuu5z0LxJKU+Y1M9LE4GHOrsWnkXUDx3a5mRR8zRXFsisj5IeiBc0cmPkRxZMBY0BIGeRLIYmJ8smnLDmVuiL5ngWxksUd5JhVqYEzxTv4I1tiSc9Y38OSTgOZwnki0GYhe55Pg1VqjCUnORLf2SWAVb5fIeYPRJ/4JnoFa1THSATTyT3BcQ++f+8DKRwGN299Hltr/+zdWCZRACZRACZSAlEAJDifwRwPBP3uIUqBEg356EvzjmcCf//wFVbAkwfl+5CMAAAAASUVORK5CYII=</Image>
+<Url type="application/x-suggestions+json" method="GET" template="https://wo.wikipedia.org/w/api.php">
+ <Param name="action" value="opensearch"/>
+ <Param name="search" value="{searchTerms}"/>
+</Url>
+<Url type="text/html" method="GET" template="https://wo.wikipedia.org/wiki/Jagleel:Ceet">
+ <Param name="search" value="{searchTerms}"/>
+ <Param name="sourceid" value="Mozilla-search"/>
+</Url>
+<SearchForm>https://wo.wikipedia.org/wiki/Jagleel:Ceet</SearchForm>
+</SearchPlugin>
diff --git a/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-zh-CN.xml b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-zh-CN.xml
new file mode 100644
index 0000000000..a168d71dea
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-zh-CN.xml
@@ -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/. -->
+
+<SearchPlugin xmlns="http://www.mozilla.org/2006/browser/search/">
+<ShortName>维基百科</ShortName>
+<InputEncoding>UTF-8</InputEncoding>
+<Image width="16" height="16">data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGAAAABgCAMAAADVRocKAAAA51BMVEUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD////7+/vl5eWxsbH9/f3Ly8tzc3P39/fe3t5cXFzz8/Pt7e3i4uI3NzcaGhoHBwcFBQX5+fnIyMhTU1MXFxcMDAzx8fHX19fFxcXCwsK7u7u1tbWenp6WlpZ8fHxXV1ctLS319fXn5+fV1dWsrKySkpJnZ2cgICDv7+/p6eng4ODQ0NC9vb24uLikpKSPj4+JiYmCgoJiYmJCQkI7OzsyMjIpKSkQEBCoqKigoKCdnZ14eHhubm5PT09LS0tERETk5OTb29unp6c0NDQkJCQOGD7BAAAAB3RSTlMA8si8ZBhlc+JuAAAAAw1JREFUaN7tmtluIjEQRYEhUxd6YYew7xAggRAgCQmB7Ov8//eM3Zg2nXkJvUjz4POAVEbyQXaVy0gOMaKRMAVAOBINcY5+UWD8OmKCIOaXhlDoNwVKNBShQImEwhQo4RAFjBIogRIogRIogRIoQWCCYXqaHJVaWrtl1IfpYp3GiczFqLHQ5kY9m0l0qVM8Txrs+8ZomkhSKpbOzlraolSP15o/EtxoU9gk2iZVujM7HnVe6eUhKaL4aYrWXWMXfd7+dIlScWxpbsjibQiLPm255sH5jYjKOoCEecge5LcTxqokuItZv5F2DID0iR21ALwctslfunNCurKEBRJkgBTZdIDOoVl0CU7FjgsZHpsi+gNoJGlisDlUkC+C8SQHejzOiqCLgXRTNYazw+vg8tsaHZ+DMd7ZlyR5Qix/uOAEgGOhlzy+EPLMMUmyOHVTyQ0wDBlXB2Dw1FzreCZJGfhyIyiDs/qWSEkiarNPxxaX3J1FWcCRLJXidtFW7MO5lmV3AhMMPS8HHsH4oBJmtEcHF+ROUEgD2E/AiVXO98AtSaoJmC4F1AUjXZAD97Bo0R491ApuBRNdVq/FGhz9hPaI48p9w1mI6rVpi1qQ9FmRuRe8iTPaJgfOi6NaTr20zDoYJUfOM2aOHM15EYwBOKbQwHm14wcY5FYgTzi5CHewMPZytO9aIHuj3MY53sF5s3M0S94EFV5bdiLeshQdgdGwc9T0IJC1VROHs4EHSgHY1XKflaFXQQ6y2MpIVIiSYDStgRLOvN/sDDCSImmv7cxaWVuu5z0LxJKU+Y1M9LE4GHOrsWnkXUDx3a5mRR8zRXFsisj5IeiBc0cmPkRxZMBY0BIGeRLIYmJ8smnLDmVuiL5ngWxksUd5JhVqYEzxTv4I1tiSc9Y38OSTgOZwnki0GYhe55Pg1VqjCUnORLf2SWAVb5fIeYPRJ/4JnoFa1THSATTyT3BcQ++f+8DKRwGN299Hltr/+zdWCZRACZRACZSAlEAJDifwRwPBP3uIUqBEg356EvzjmcCf//wFVbAkwfl+5CMAAAAASUVORK5CYII=</Image>
+<Url type="application/x-suggestions+json" method="GET" template="https://zh.wikipedia.org/w/api.php">
+ <Param name="action" value="opensearch"/>
+ <Param name="search" value="{searchTerms}"/>
+</Url>
+<Url type="text/html" method="GET" template="https://zh.wikipedia.org/wiki/Special:搜索">
+ <Param name="search" value="{searchTerms}"/>
+ <Param name="sourceid" value="Mozilla-search"/>
+</Url>
+<SearchForm>https://zh.wikipedia.org/wiki/Special:搜索</SearchForm>
+</SearchPlugin>
diff --git a/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-zh-TW.xml b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-zh-TW.xml
new file mode 100644
index 0000000000..aeaabe6811
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia-zh-TW.xml
@@ -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/. -->
+
+<SearchPlugin xmlns="http://www.mozilla.org/2006/browser/search/">
+<ShortName>Wikipedia (zh)</ShortName>
+<InputEncoding>UTF-8</InputEncoding>
+<Image width="16" height="16">data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGAAAABgCAMAAADVRocKAAAA51BMVEUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD////7+/vl5eWxsbH9/f3Ly8tzc3P39/fe3t5cXFzz8/Pt7e3i4uI3NzcaGhoHBwcFBQX5+fnIyMhTU1MXFxcMDAzx8fHX19fFxcXCwsK7u7u1tbWenp6WlpZ8fHxXV1ctLS319fXn5+fV1dWsrKySkpJnZ2cgICDv7+/p6eng4ODQ0NC9vb24uLikpKSPj4+JiYmCgoJiYmJCQkI7OzsyMjIpKSkQEBCoqKigoKCdnZ14eHhubm5PT09LS0tERETk5OTb29unp6c0NDQkJCQOGD7BAAAAB3RSTlMA8si8ZBhlc+JuAAAAAw1JREFUaN7tmtluIjEQRYEhUxd6YYew7xAggRAgCQmB7Ov8//eM3Zg2nXkJvUjz4POAVEbyQXaVy0gOMaKRMAVAOBINcY5+UWD8OmKCIOaXhlDoNwVKNBShQImEwhQo4RAFjBIogRIogRIogRIoQWCCYXqaHJVaWrtl1IfpYp3GiczFqLHQ5kY9m0l0qVM8Txrs+8ZomkhSKpbOzlraolSP15o/EtxoU9gk2iZVujM7HnVe6eUhKaL4aYrWXWMXfd7+dIlScWxpbsjibQiLPm255sH5jYjKOoCEecge5LcTxqokuItZv5F2DID0iR21ALwctslfunNCurKEBRJkgBTZdIDOoVl0CU7FjgsZHpsi+gNoJGlisDlUkC+C8SQHejzOiqCLgXRTNYazw+vg8tsaHZ+DMd7ZlyR5Qix/uOAEgGOhlzy+EPLMMUmyOHVTyQ0wDBlXB2Dw1FzreCZJGfhyIyiDs/qWSEkiarNPxxaX3J1FWcCRLJXidtFW7MO5lmV3AhMMPS8HHsH4oBJmtEcHF+ROUEgD2E/AiVXO98AtSaoJmC4F1AUjXZAD97Bo0R491ApuBRNdVq/FGhz9hPaI48p9w1mI6rVpi1qQ9FmRuRe8iTPaJgfOi6NaTr20zDoYJUfOM2aOHM15EYwBOKbQwHm14wcY5FYgTzi5CHewMPZytO9aIHuj3MY53sF5s3M0S94EFV5bdiLeshQdgdGwc9T0IJC1VROHs4EHSgHY1XKflaFXQQ6y2MpIVIiSYDStgRLOvN/sDDCSImmv7cxaWVuu5z0LxJKU+Y1M9LE4GHOrsWnkXUDx3a5mRR8zRXFsisj5IeiBc0cmPkRxZMBY0BIGeRLIYmJ8smnLDmVuiL5ngWxksUd5JhVqYEzxTv4I1tiSc9Y38OSTgOZwnki0GYhe55Pg1VqjCUnORLf2SWAVb5fIeYPRJ/4JnoFa1THSATTyT3BcQ++f+8DKRwGN299Hltr/+zdWCZRACZRACZSAlEAJDifwRwPBP3uIUqBEg356EvzjmcCf//wFVbAkwfl+5CMAAAAASUVORK5CYII=</Image>
+<Url type="application/x-suggestions+json" method="GET" template="https://zh.wikipedia.org/w/api.php">
+ <Param name="action" value="opensearch"/>
+ <Param name="search" value="{searchTerms}"/>
+</Url>
+<Url type="text/html" method="GET" template="https://zh.wikipedia.org/wiki/Special:搜索">
+ <Param name="search" value="{searchTerms}"/>
+ <Param name="sourceid" value="Mozilla-search"/>
+ <Param name="variant" value="zh-tw"/>
+</Url>
+<SearchForm>https://zh.wikipedia.org/wiki/Special:搜索</SearchForm>
+</SearchPlugin>
diff --git a/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia.xml b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia.xml
new file mode 100644
index 0000000000..ab1d0521e3
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wikipedia.xml
@@ -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/. -->
+
+<SearchPlugin xmlns="http://www.mozilla.org/2006/browser/search/">
+<ShortName>Wikipedia</ShortName>
+<InputEncoding>UTF-8</InputEncoding>
+<Image width="32" height="32">data:image/png;base64,AAABAAIAICAQAAEABADuAQAAJgAAABAQEAABAAQAYAEAABQCAACJUE5HDQoaCgAAAA1JSERSAAAAIAAAACAIBgAAAHN6evQAAAG1SURBVFiF7ZfNccQgDIVJJi2oBlXgGqjBBdADJdACTbgS36mBJqQcMnLEj9jsXpzD7gwnGenj8SR7P5iZ3Y2/zzuLvwH+BcDXzR68X4HbARwR8bZt7Jwb1r7vTERMRIyITQwAOOfMRMQpJQaAJi6xnPOwV+d2UqDW2iSptV7FZYUQrvh5nk2slMLOOUZELqUMe/d9vwrr3E4/lFK6ChzHMSSptV7xEEITO47D3CcAADAczPUFRIVt26aJYoxTlRCRvffTPQKeUhpiblXAUkEgY4zN6ftr0Tlnp58CaJmtE/UqIGJj2H4BwHBlJoA2jHNuaiitgjw7e06rY8WnAOLovhUtFazTEf20uKWkCUBE7L1ftuSqI2Sd57nsjCWASKfNNrtbGUrW3LC66SGAyGcV0ICzFhOFZCK+BKCL9AUQkUMIlwkBoInLeF7lfwjQyzxztjashgSA6eB5GiDnPLxg5PS9YQVSAGe+eBpA9zwiTvu6vyrv/bI1nwIganvemg39K90aPC8B6J63kmsVVoPnJQCi32+B1cyXD4/V4HkZoNbKMcalsUopf3K+Xh/vv2ZvgLsBvgEmf6Ud8idB7wAAAABJRU5ErkJggolQTkcNChoKAAAADUlIRFIAAAAQAAAAEAgGAAAAH/P/YQAAASdJREFUOI3FkzGKwzAQRX9M7iDnBGqDywhBSCeUi/gQKdL4BiGtK5Fe1zDug3vjMieYv5WEtWG3ycIKBvQ16I/mDdqQJD5Y1SeX/8Rg+2EHqMZxhLUWVVXhfr8DALz3WS/LAmstrLVYlgWPxwO73Q7ee0zTBIgI53kmAMYYmbTWmrfbjSJC5xzneaaIUERojMl7pI1zrkiEEKiUYoyRXdcV58m4MBiGgQA4DENOaq2ptc46FVrrPIWmaeCcw+VyyYBOpxNer1fW4zhiv9+XFNduMUYC4PP5zNWUUgwhUETYtm3BQkS4XZt576G1Rt/3OBwOOJ/PsNbier3ieDwCAOq6/vkFCRKA3GuakDGm4PMGcR1KqYJ027Zv8H41SAzW8b33FJt//41fMtqn5156WuIAAAAASUVORK5CYII=</Image>
+<Url type="application/x-suggestions+json" method="GET" template="https://en.wikipedia.org/w/api.php">
+ <Param name="action" value="opensearch"/>
+ <Param name="search" value="{searchTerms}"/>
+</Url>
+<Url type="text/html" method="GET" template="https://en.wikipedia.org/wiki/Special:Search">
+ <Param name="search" value="{searchTerms}"/>
+ <Param name="sourceid" value="Mozilla-search"/>
+</Url>
+<SearchForm>https://en.wikipedia.org/wiki/Special:Search</SearchForm>
+</SearchPlugin>
diff --git a/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wiktionary-kn.xml b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wiktionary-kn.xml
new file mode 100644
index 0000000000..7e39c48ee2
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wiktionary-kn.xml
@@ -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/. -->
+
+<SearchPlugin xmlns="http://www.mozilla.org/2006/browser/search/">
+<ShortName>ವಿಕ್ಷನರಿ (kn)</ShortName>
+<Image width="16" height="16">data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGAAAABgCAMAAADVRocKAAAA21BMVEUAAAAAAAAAAAAAAAAAAAAAAAAAAAD////Z2dnm5uYSEhJCQkJjY2PJycn6+vq4uLhOTk79/f0GBgbg4OBra2tbW1sEBAQeHh729va/v7/u7u4pKSkPDw/d3d2BgYFQUFAjIyMYGBjq6uq0tLSrq6umpqadnZ2Xl5eSkpKNjY1wcHBWVlZGRkY7Ozs1NTUwMDAKCgrDw8OxsbGIiIh6enpoaGhLS0tAQEA3NzcsLCwrKysICAjw8PDW1tbS0tJ0dHTo6Ojj4+PPz898fHxiYmLx8fG6urqhoaFlZWXTVXa3AAAABnRSTlMA8si8ZBgxEvPEAAACy0lEQVRo3u2aa1fiMBCGAXUiiLW2tFguAsr9orBcFBDwsrf//4t2kqbN0d2DS5Pshz15P0BmQvtMMsmclpMU6jiTBg1KZ45TVCdHoE1HJwjQeH8k4PyAVh2nMqBVmVQatCqdAs0yAAMwAAMwAAP414B8pCIzh/m8DYfpMc81+COARKoxc0LI9kBAh3Bl9wPCwC8IOT8Q0CNcp5+MICmg+ymg5Nm2XWskBaxqtr142wfIOsJMAAgzvReQkwecGYAB/AYoLsurOgitV6vyMgdCjSXaEoCpZVmlovDPLVQbhAK0hwkAASGvrKoSlCf8t9SurmO7buF1lQSAB89jceVusENEnCtRwOW9GBGaPxLk4H3Ip05k2YSp8K57IAXoi4hFzW/GKX7CGpmTAtxfYk+fG85pCHDH3OGh8QUkAPyet9y4Q1pQwiHdcUcLO7/KAaCNPc+8Z4btxTl+7EK7kiXkqigJGBDUMF68WacjpmWBzQAkAcUr7JrGzSYS46VPWX1ZAExIVJc8NuN1ShyxulElxCpLA65JNNEtbGBhokmYUXvE0NKAh6haVF4ImfDnkwtWqLBxLQMQS4W0OemNp/YGf+tv6YKVB0CTV4spv1+DFqSzcA9ufAWAeVgt/NeoKgV0asJd0QMFgLJFVyP76sRpD8LldaYC4G/Z1irgpx2nvVShu8IdqwBAl3aOm2FqUZVnuhM8lnslgBpbqK4onLc0CS06IlmAqPpkgymYc8cObfeGjkgNAALCdFUXZZupCYoAM0IlysLYDR2eKsBjGLEoCy1mf2soAYiIR7HjJ7MvQAVAROyuxd5jgII6wMCtVl96wva/o2NTVwcAx/edDw7HB0mA+qfrDyEpfwl82hVQRUioUR+v7v7ViziX6hdxLjspoKcZIEbg/qd/SDEZgAEYAIABGIABaJD2QwPajz1oP7ih++iJ/sMz2o///ALGfwB3vnCGuQAAAABJRU5ErkJggg==</Image>
+<Url type="text/html" method="get" template="https://kn.wiktionary.org/wiki/ವಿಶೇಷ:Search">
+ <Param name="search" value="{searchTerms}"/>
+</Url>
+<Url type="application/x-suggestions+json" method="GET" template="https://kn.wiktionary.org/w/api.php">
+ <Param name="action" value="opensearch"/>
+ <Param name="format" value="xml"/>
+ <Param name="search" value="{searchTerms}"/>
+ <Param name="namespace" value="0"/>
+</Url>
+<SearchForm>https://kn.wiktionary.org/wiki/ವಿಶೇಷ:Search</SearchForm>
+</SearchPlugin>
diff --git a/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wiktionary-oc.xml b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wiktionary-oc.xml
new file mode 100644
index 0000000000..82bd9724c1
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wiktionary-oc.xml
@@ -0,0 +1,17 @@
+<!-- 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/. -->
+
+<SearchPlugin xmlns="http://www.mozilla.org/2006/browser/search/">
+<ShortName>Wikiccionari (oc)</ShortName>
+<Image width="16" height="16">data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGAAAABgCAMAAADVRocKAAAA21BMVEUAAAAAAAAAAAAAAAAAAAAAAAAAAAD////Z2dnm5uYSEhJCQkJjY2PJycn6+vq4uLhOTk79/f0GBgbg4OBra2tbW1sEBAQeHh729va/v7/u7u4pKSkPDw/d3d2BgYFQUFAjIyMYGBjq6uq0tLSrq6umpqadnZ2Xl5eSkpKNjY1wcHBWVlZGRkY7Ozs1NTUwMDAKCgrDw8OxsbGIiIh6enpoaGhLS0tAQEA3NzcsLCwrKysICAjw8PDW1tbS0tJ0dHTo6Ojj4+PPz898fHxiYmLx8fG6urqhoaFlZWXTVXa3AAAABnRSTlMA8si8ZBgxEvPEAAACy0lEQVRo3u2aa1fiMBCGAXUiiLW2tFguAsr9orBcFBDwsrf//4t2kqbN0d2DS5Pshz15P0BmQvtMMsmclpMU6jiTBg1KZ45TVCdHoE1HJwjQeH8k4PyAVh2nMqBVmVQatCqdAs0yAAMwAAMwAAP414B8pCIzh/m8DYfpMc81+COARKoxc0LI9kBAh3Bl9wPCwC8IOT8Q0CNcp5+MICmg+ymg5Nm2XWskBaxqtr142wfIOsJMAAgzvReQkwecGYAB/AYoLsurOgitV6vyMgdCjSXaEoCpZVmlovDPLVQbhAK0hwkAASGvrKoSlCf8t9SurmO7buF1lQSAB89jceVusENEnCtRwOW9GBGaPxLk4H3Ip05k2YSp8K57IAXoi4hFzW/GKX7CGpmTAtxfYk+fG85pCHDH3OGh8QUkAPyet9y4Q1pQwiHdcUcLO7/KAaCNPc+8Z4btxTl+7EK7kiXkqigJGBDUMF68WacjpmWBzQAkAcUr7JrGzSYS46VPWX1ZAExIVJc8NuN1ShyxulElxCpLA65JNNEtbGBhokmYUXvE0NKAh6haVF4ImfDnkwtWqLBxLQMQS4W0OemNp/YGf+tv6YKVB0CTV4spv1+DFqSzcA9ufAWAeVgt/NeoKgV0asJd0QMFgLJFVyP76sRpD8LldaYC4G/Z1irgpx2nvVShu8IdqwBAl3aOm2FqUZVnuhM8lnslgBpbqK4onLc0CS06IlmAqPpkgymYc8cObfeGjkgNAALCdFUXZZupCYoAM0IlysLYDR2eKsBjGLEoCy1mf2soAYiIR7HjJ7MvQAVAROyuxd5jgII6wMCtVl96wva/o2NTVwcAx/edDw7HB0mA+qfrDyEpfwl82hVQRUioUR+v7v7ViziX6hdxLjspoKcZIEbg/qd/SDEZgAEYAIABGIABaJD2QwPajz1oP7ih++iJ/sMz2o///ALGfwB3vnCGuQAAAABJRU5ErkJggg==</Image>
+<Url type="application/x-suggestions+json" method="GET" template="https://oc.wiktionary.org/w/api.php">
+ <Param name="action" value="opensearch"/>
+ <Param name="search" value="{searchTerms}"/>
+ <Param name="namespace" value="0"/>
+</Url>
+<Url type="text/html" method="get" template="https://oc.wiktionary.org/wiki/Especial:Recèrca">
+ <Param name="search" value="{searchTerms}"/>
+</Url>
+<SearchForm>https://oc.wiktionary.org/wiki/Especial:Recèrca</SearchForm>
+</SearchPlugin>
diff --git a/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wiktionary-or.xml b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wiktionary-or.xml
new file mode 100644
index 0000000000..bb475cafb5
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wiktionary-or.xml
@@ -0,0 +1,17 @@
+<!-- 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/. -->
+
+<SearchPlugin xmlns="http://www.mozilla.org/2006/browser/search/">
+<ShortName>Wiktionary (or)</ShortName>
+<Image width="16" height="16">data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGAAAABgCAMAAADVRocKAAAA21BMVEUAAAAAAAAAAAAAAAAAAAAAAAAAAAD////Z2dnm5uYSEhJCQkJjY2PJycn6+vq4uLhOTk79/f0GBgbg4OBra2tbW1sEBAQeHh729va/v7/u7u4pKSkPDw/d3d2BgYFQUFAjIyMYGBjq6uq0tLSrq6umpqadnZ2Xl5eSkpKNjY1wcHBWVlZGRkY7Ozs1NTUwMDAKCgrDw8OxsbGIiIh6enpoaGhLS0tAQEA3NzcsLCwrKysICAjw8PDW1tbS0tJ0dHTo6Ojj4+PPz898fHxiYmLx8fG6urqhoaFlZWXTVXa3AAAABnRSTlMA8si8ZBgxEvPEAAACy0lEQVRo3u2aa1fiMBCGAXUiiLW2tFguAsr9orBcFBDwsrf//4t2kqbN0d2DS5Pshz15P0BmQvtMMsmclpMU6jiTBg1KZ45TVCdHoE1HJwjQeH8k4PyAVh2nMqBVmVQatCqdAs0yAAMwAAMwAAP414B8pCIzh/m8DYfpMc81+COARKoxc0LI9kBAh3Bl9wPCwC8IOT8Q0CNcp5+MICmg+ymg5Nm2XWskBaxqtr142wfIOsJMAAgzvReQkwecGYAB/AYoLsurOgitV6vyMgdCjSXaEoCpZVmlovDPLVQbhAK0hwkAASGvrKoSlCf8t9SurmO7buF1lQSAB89jceVusENEnCtRwOW9GBGaPxLk4H3Ip05k2YSp8K57IAXoi4hFzW/GKX7CGpmTAtxfYk+fG85pCHDH3OGh8QUkAPyet9y4Q1pQwiHdcUcLO7/KAaCNPc+8Z4btxTl+7EK7kiXkqigJGBDUMF68WacjpmWBzQAkAcUr7JrGzSYS46VPWX1ZAExIVJc8NuN1ShyxulElxCpLA65JNNEtbGBhokmYUXvE0NKAh6haVF4ImfDnkwtWqLBxLQMQS4W0OemNp/YGf+tv6YKVB0CTV4spv1+DFqSzcA9ufAWAeVgt/NeoKgV0asJd0QMFgLJFVyP76sRpD8LldaYC4G/Z1irgpx2nvVShu8IdqwBAl3aOm2FqUZVnuhM8lnslgBpbqK4onLc0CS06IlmAqPpkgymYc8cObfeGjkgNAALCdFUXZZupCYoAM0IlysLYDR2eKsBjGLEoCy1mf2soAYiIR7HjJ7MvQAVAROyuxd5jgII6wMCtVl96wva/o2NTVwcAx/edDw7HB0mA+qfrDyEpfwl82hVQRUioUR+v7v7ViziX6hdxLjspoKcZIEbg/qd/SDEZgAEYAIABGIABaJD2QwPajz1oP7ih++iJ/sMz2o///ALGfwB3vnCGuQAAAABJRU5ErkJggg==</Image>
+<Url type="application/x-suggestions+json" method="GET" template="https://or.wiktionary.org/w/api.php">
+ <Param name="action" value="opensearch"/>
+ <Param name="search" value="{searchTerms}"/>
+ <Param name="namespace" value="0"/>
+</Url>
+<Url type="text/html" method="get" template="https://or.wiktionary.org/wiki/ବିଶେଷ:ଖୋଜନ୍ତୁ">
+ <Param name="search" value="{searchTerms}"/>
+</Url>
+<SearchForm>https://or.wiktionary.org/wiki/ବିଶେଷ:ଖୋଜନ୍ତୁ</SearchForm>
+</SearchPlugin>
diff --git a/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wiktionary-ta.xml b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wiktionary-ta.xml
new file mode 100644
index 0000000000..5b4662a29e
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wiktionary-ta.xml
@@ -0,0 +1,17 @@
+<!-- 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/. -->
+
+<SearchPlugin xmlns="http://www.mozilla.org/2006/browser/search/">
+<ShortName>விக்சனரி (ta)</ShortName>
+<Image width="16" height="16">data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGAAAABgCAMAAADVRocKAAAA21BMVEUAAAAAAAAAAAAAAAAAAAAAAAAAAAD////Z2dnm5uYSEhJCQkJjY2PJycn6+vq4uLhOTk79/f0GBgbg4OBra2tbW1sEBAQeHh729va/v7/u7u4pKSkPDw/d3d2BgYFQUFAjIyMYGBjq6uq0tLSrq6umpqadnZ2Xl5eSkpKNjY1wcHBWVlZGRkY7Ozs1NTUwMDAKCgrDw8OxsbGIiIh6enpoaGhLS0tAQEA3NzcsLCwrKysICAjw8PDW1tbS0tJ0dHTo6Ojj4+PPz898fHxiYmLx8fG6urqhoaFlZWXTVXa3AAAABnRSTlMA8si8ZBgxEvPEAAACy0lEQVRo3u2aa1fiMBCGAXUiiLW2tFguAsr9orBcFBDwsrf//4t2kqbN0d2DS5Pshz15P0BmQvtMMsmclpMU6jiTBg1KZ45TVCdHoE1HJwjQeH8k4PyAVh2nMqBVmVQatCqdAs0yAAMwAAMwAAP414B8pCIzh/m8DYfpMc81+COARKoxc0LI9kBAh3Bl9wPCwC8IOT8Q0CNcp5+MICmg+ymg5Nm2XWskBaxqtr142wfIOsJMAAgzvReQkwecGYAB/AYoLsurOgitV6vyMgdCjSXaEoCpZVmlovDPLVQbhAK0hwkAASGvrKoSlCf8t9SurmO7buF1lQSAB89jceVusENEnCtRwOW9GBGaPxLk4H3Ip05k2YSp8K57IAXoi4hFzW/GKX7CGpmTAtxfYk+fG85pCHDH3OGh8QUkAPyet9y4Q1pQwiHdcUcLO7/KAaCNPc+8Z4btxTl+7EK7kiXkqigJGBDUMF68WacjpmWBzQAkAcUr7JrGzSYS46VPWX1ZAExIVJc8NuN1ShyxulElxCpLA65JNNEtbGBhokmYUXvE0NKAh6haVF4ImfDnkwtWqLBxLQMQS4W0OemNp/YGf+tv6YKVB0CTV4spv1+DFqSzcA9ufAWAeVgt/NeoKgV0asJd0QMFgLJFVyP76sRpD8LldaYC4G/Z1irgpx2nvVShu8IdqwBAl3aOm2FqUZVnuhM8lnslgBpbqK4onLc0CS06IlmAqPpkgymYc8cObfeGjkgNAALCdFUXZZupCYoAM0IlysLYDR2eKsBjGLEoCy1mf2soAYiIR7HjJ7MvQAVAROyuxd5jgII6wMCtVl96wva/o2NTVwcAx/edDw7HB0mA+qfrDyEpfwl82hVQRUioUR+v7v7ViziX6hdxLjspoKcZIEbg/qd/SDEZgAEYAIABGIABaJD2QwPajz1oP7ih++iJ/sMz2o///ALGfwB3vnCGuQAAAABJRU5ErkJggg==</Image>
+<Url type="application/x-suggestions+json" method="GET" template="https://ta.wiktionary.org/w/api.php">
+ <Param name="action" value="opensearch"/>
+ <Param name="search" value="{searchTerms}"/>
+ <Param name="namespace" value="0"/>
+</Url>
+<Url type="text/html" method="get" template="https://ta.wiktionary.org/wiki/சிறப்பு:Search">
+ <Param name="search" value="{searchTerms}"/>
+</Url>
+<SearchForm>https://ta.wiktionary.org/wiki/சிறப்பு:Search</SearchForm>
+</SearchPlugin>
diff --git a/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wiktionary-te.xml b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wiktionary-te.xml
new file mode 100644
index 0000000000..1dd499dc37
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/wiktionary-te.xml
@@ -0,0 +1,17 @@
+<!-- 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/. -->
+
+<SearchPlugin xmlns="http://www.mozilla.org/2006/browser/search/">
+<ShortName>విక్షనరీ (te)</ShortName>
+<Image width="16" height="16">data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGAAAABgCAMAAADVRocKAAAA21BMVEUAAAAAAAAAAAAAAAAAAAAAAAAAAAD////Z2dnm5uYSEhJCQkJjY2PJycn6+vq4uLhOTk79/f0GBgbg4OBra2tbW1sEBAQeHh729va/v7/u7u4pKSkPDw/d3d2BgYFQUFAjIyMYGBjq6uq0tLSrq6umpqadnZ2Xl5eSkpKNjY1wcHBWVlZGRkY7Ozs1NTUwMDAKCgrDw8OxsbGIiIh6enpoaGhLS0tAQEA3NzcsLCwrKysICAjw8PDW1tbS0tJ0dHTo6Ojj4+PPz898fHxiYmLx8fG6urqhoaFlZWXTVXa3AAAABnRSTlMA8si8ZBgxEvPEAAACy0lEQVRo3u2aa1fiMBCGAXUiiLW2tFguAsr9orBcFBDwsrf//4t2kqbN0d2DS5Pshz15P0BmQvtMMsmclpMU6jiTBg1KZ45TVCdHoE1HJwjQeH8k4PyAVh2nMqBVmVQatCqdAs0yAAMwAAMwAAP414B8pCIzh/m8DYfpMc81+COARKoxc0LI9kBAh3Bl9wPCwC8IOT8Q0CNcp5+MICmg+ymg5Nm2XWskBaxqtr142wfIOsJMAAgzvReQkwecGYAB/AYoLsurOgitV6vyMgdCjSXaEoCpZVmlovDPLVQbhAK0hwkAASGvrKoSlCf8t9SurmO7buF1lQSAB89jceVusENEnCtRwOW9GBGaPxLk4H3Ip05k2YSp8K57IAXoi4hFzW/GKX7CGpmTAtxfYk+fG85pCHDH3OGh8QUkAPyet9y4Q1pQwiHdcUcLO7/KAaCNPc+8Z4btxTl+7EK7kiXkqigJGBDUMF68WacjpmWBzQAkAcUr7JrGzSYS46VPWX1ZAExIVJc8NuN1ShyxulElxCpLA65JNNEtbGBhokmYUXvE0NKAh6haVF4ImfDnkwtWqLBxLQMQS4W0OemNp/YGf+tv6YKVB0CTV4spv1+DFqSzcA9ufAWAeVgt/NeoKgV0asJd0QMFgLJFVyP76sRpD8LldaYC4G/Z1irgpx2nvVShu8IdqwBAl3aOm2FqUZVnuhM8lnslgBpbqK4onLc0CS06IlmAqPpkgymYc8cObfeGjkgNAALCdFUXZZupCYoAM0IlysLYDR2eKsBjGLEoCy1mf2soAYiIR7HjJ7MvQAVAROyuxd5jgII6wMCtVl96wva/o2NTVwcAx/edDw7HB0mA+qfrDyEpfwl82hVQRUioUR+v7v7ViziX6hdxLjspoKcZIEbg/qd/SDEZgAEYAIABGIABaJD2QwPajz1oP7ih++iJ/sMz2o///ALGfwB3vnCGuQAAAABJRU5ErkJggg==</Image>
+<Url type="application/x-suggestions+json" method="GET" template="https://te.wiktionary.org/w/api.php">
+ <Param name="action" value="opensearch"/>
+ <Param name="search" value="{searchTerms}"/>
+ <Param name="namespace" value="0"/>
+</Url>
+<Url type="text/html" method="get" template="https://te.wiktionary.org/wiki/ప్రత్యేక:అన్వేషణ">
+ <Param name="search" value="{searchTerms}"/>
+</Url>
+<SearchForm>https://te.wiktionary.org/wiki/ప్రత్యేక:అన్వేషణ</SearchForm>
+</SearchPlugin>
diff --git a/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/yahoo-jp-auctions.xml b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/yahoo-jp-auctions.xml
new file mode 100644
index 0000000000..6a3666954d
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/yahoo-jp-auctions.xml
@@ -0,0 +1,16 @@
+<!-- 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/. -->
+
+<SearchPlugin xmlns="http://www.mozilla.org/2006/browser/search/">
+ <ShortName>Yahoo!オークション</ShortName>
+ <Description>ヤフオク! 検索</Description>
+ <InputEncoding>EUC-JP</InputEncoding>
+ <Image height="16" width="16">data:image/png;base64,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</Image>
+ <Url method="GET" template="https://auctions.yahoo.co.jp/search/search" type="text/html">
+ <Param name="p" value="{searchTerms}" />
+ <Param name="ei" value="EUC-JP" />
+ <Param name="fr" value="mozff" />
+ </Url>
+ <SearchForm>https://auctions.yahoo.co.jp/</SearchForm>
+</SearchPlugin>
diff --git a/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/yahoo-jp.xml b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/yahoo-jp.xml
new file mode 100644
index 0000000000..2196d37b61
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/yahoo-jp.xml
@@ -0,0 +1,16 @@
+<!-- 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/. -->
+
+<SearchPlugin xmlns="http://www.mozilla.org/2006/browser/search/">
+<ShortName>Yahoo! JAPAN</ShortName>
+<Description>検索エンジン - Yahoo!検索</Description>
+<InputEncoding>UTF-8</InputEncoding>
+<Image width="16" height="16">data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGAAAABgCAMAAADVRocKAAAAxlBMVEUAAAD/////////////////////////////////ADP/r7///f3/Bjj/Czz/JVH/Hkz/2uH/b4z/aYf/+/z/6+//ma7/9Pb/xtL/vcr/VHb/F0X/EkH/9vj/8vX/7/L/nrL/iqL/dZH/Xn7/PmX/K1b/Dz//1t//0dr/wc3/s8L/qLn/YoH/WXr/Sm7/RGr/lKr/kKb/e5b/T3L/OWH/Mlv/HEn/5uv/4ef/3uX/ytX/q7z/o7b/gJr/IU3/hp7/co7/ucf/ZINYCJxYAAAACHRSTlMA8Qz3rqoz9iHWq2MAAAKtSURBVGje7ZrZlqIwEEDRVrtiEB1RxH3flx4d7VZ7mZn//6nxCJ0SkEga8zB9ch9N5JJUpYrDQdO0ZDoBUkikk9qJzCNI4zFzuv8HkMhDUkuDVNJaAqSS0EAySqAESqAESqAESqAEdxb8Ijx68QU7rqATX1AnodSN1SG+AEqV9rq6zZFLPrKHQuu+QaaFHkG6IMRoxBGgokiQiW+wQMLoU4AeMboVeksA9GIN+ZZvLEeukyucBs9xrM2nDb4AzCVhLADhZfNPAJgw26Zd4gnAurhM2zf2XDl+9Dy58L7o2OfrdQmy5Qqg9I5rH8EV6OBzhdMS+9EgSIUvgNGQTR1YEKTjjBmVkASY36xFts4rE6/OyN+mV8qol24KoIzTy/6xtrN5M/DQJ4ynKNUUj4M+vrY/g4IvboQxoFEE5or9wWgGD+LCCm4bHs8oAmhhKlWB0VyyvPdSxdlRG86YZTtebz84B3ECfhpssv4SVQAzDIObj5P6ecv2EOAPm/sm0DJ/s3/tWufUOifvssXLiXxDQGBi6m0oUMdXpHCFPHGZCTX95xqGwaziDgQYs7INQgKwMQx9PHVB3ojLWFAAa+LhNWTa1h0vgqjA9HSAdthWYhESFUBBj9Cjy1iEhAUwx97QgBCWbhEyvyL4wQQ1CMFyV2lDPEEeQsiyIiRBgLuo72UJqHMc1yBLUHHKlSVN0CovdSxC9xQgzeOaShQgcc+BFMGCCYZXz8CsEU8w1bkCapDhfNr8oqAxLq/IBatqsdspH+2DhX63WbwIC9qGUSNh4EOXewMGFRZsCAdWNUdYpwUFZo6Es/M/TAwtYUEzy8HGdvS0GWInkvMqgdrF2meIv/XLEBclUAIlAFACJVACgP9QIP2zhxRIJSX/0xMtI9HwkNFOJFOyPv9Jne7/HyIEPtcrxWwlAAAAAElFTkSuQmCC</Image>
+<Url type="text/html" method="GET" template="https://search.yahoo.co.jp/search">
+ <Param name="p" value="{searchTerms}"/>
+ <Param name="ei" value="UTF-8"/>
+ <Param name="fr" value="mozff" />
+</Url>
+<SearchForm>https://search.yahoo.co.jp/</SearchForm>
+</SearchPlugin>
diff --git a/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/yandex-en.xml b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/yandex-en.xml
new file mode 100644
index 0000000000..75ba859ca3
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/yandex-en.xml
@@ -0,0 +1,22 @@
+<!-- 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/. -->
+
+<SearchPlugin xmlns="http://www.mozilla.org/2006/browser/search/">
+<ShortName>Yandex</ShortName>
+<Description>Use Yandex to search the Internet.</Description>
+<InputEncoding>UTF-8</InputEncoding>
+<Image width="16" height="16">data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGAAAABgCAMAAADVRocKAAAAqFBMVEUAAAD29PL29PL29PP29PLd3d3w8PD29fP/JQD7ion35uT28/H8bmz36+r6paT+Lh7+KRL+Jwz41tX4ysn4wcD7h4X8dHL+OTD27+333t37lZT7jYz8aWb9Qz3+JQH36Of34+H40tH5vLv5uLj5sbD5rKv8e3n9WVb9Uk/9TUn9SEP+Myf+Jgb32tr4xMP6nJv7mpn7goH8gH78X1z9Pzb+NSn+JQD8Yl99ghQbAAAAB3RSTlMA88/IbQYbgu4OFQAAAe5JREFUaN7t2slywjAMBmCzKjSsISxhXwtlXwp9/zcr+VsQKfQU6dCpdfLooG/isWVPxsaYTDqVIIVIpNIZc4lsktQimTUmo1YfQsakSTXSJkWqkTIJUo2EIeWwgAUsYAFVwK84lyhhrALUnTA+MNYA3BKACSEUAB/1y01CKAAHAHWMYwG1/CXqg4cZOgHw4wPvKNT+ma4ifXLjAy1U6j58GNI1ig8EPZQaPv2woQBAM5TKRZMef1dsYIpajWcT1xIBCmUUq0aSizDVC+ID3BP296kAqRnJABtUW7rEsUWqKAS4DZTbEMc8TFQKQgC1AbxyYoCl2yEpYA2gxHNURGIsAvCMOCO6xhFgUw4oAsjfFu6Kp0wGKFQivX8CryoIUD5yenV4a0sBvnO3bJplNCdRwF3eLfwxNE8O4PY/5daxIFnAA3Dk68RWGKC3sOqqfz0sewNpoHhrb21upJJAH1thfv2WqSjAi/8cfG3jckEeGH0fkmPuGnIAb4UuHdD3pAHeCsMuOrcG4AHIn9FIpQHeCtxI5QFsBW6k4gC2At+E5QGcCtxI5QGcCtxIxQG+IO0IoQDQHsAaYxUgB+AFYwtYwAJEFrCABYgs8DR2zi9X97/5c9wCFrDAfwK0Hw2oP3tQf7ih/vRE/fGM+vOfTzkzCrugwvNDAAAAAElFTkSuQmCC</Image>
+<Url type="application/x-suggestions+json" method="GET" template="http://suggest.yandex.com/suggest-ff.cgi">
+ <Param name="part" value="{searchTerms}"/>
+ <Param name="uil" value="tr"/>
+</Url>
+<Url type="text/html" method="GET" template="https://yandex.com/search">
+ <Param name="clid" value="2186727"/>
+ <Param name="text" value="{searchTerms}"/>
+</Url>
+<Url type="application/x-moz-tabletsearch" method="GET" template="https://yandex.com/search">
+ <Param name="clid" value="2186733"/>
+ <Param name="text" value="{searchTerms}"/>
+</Url>
+</SearchPlugin>
diff --git a/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/yandex-ru.xml b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/yandex-ru.xml
new file mode 100644
index 0000000000..68d5f6bbf8
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/yandex-ru.xml
@@ -0,0 +1,21 @@
+<!-- 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/. -->
+
+<SearchPlugin xmlns="http://www.mozilla.org/2006/browser/search/">
+<ShortName>Яндекс</ShortName>
+<InputEncoding>UTF-8</InputEncoding>
+<Image width="16" height="16">data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGAAAABgCAMAAADVRocKAAAAqFBMVEUAAAD29PL29PL29PP29PLd3d3w8PD29fP/Jg76oKL33t3+Jxj27+342dn+Lyv28/H28fD36+r35+f35eT34OD9U1X+LCX4wMH5qqz7kJL+PDz7l5r8Z2v9TE3+OTj+NDH4y8v5ubr5trf5sLH8eHz8dHf9XF/9Pj/37Ov41tb40dH4x8j5vb75s7T6pKb7i438foH8bXD8YWP9UVP9RUb+KR77h4v7g4aogTBNAAAAB3RSTlMA88/IbQYbgu4OFQAAAcpJREFUaN7t2lduwkAURmETINcEV4zpvaXRA8n+dxbkX8ji3echiu8CzucBjRmhcRynXqtWDJhKtVZ3bvP8ZNg8Pd+en+pLqDs1Q6fmVA2dqlMxdCqOwVMCJVACJVAwEC9X46Dp3mdQMPCyurqPUygQ9fXoFJCkalJA8uqigDdWsbneJqGZNYoG1gqOfbsNAHTV23jGAOEly73GBgEL5T6NAjZZ7WwU0FZtiwG9LNaJMOCUxUaGAdrEQwzwFJtjgK/YBwZ0FWtjwFyxFgYsFYsxYKdYQn8H7xgwU6yLAS3FGhhgkyx24oBRFgsi+G3qzjEg1okrxQBbKbfDgLaW0PEpwPrqTd4pIPxSsNOIGMDaA1cz/VnMfN/vFw1IQI/vrTMIaPYBDNjbkQTyl1IzTdMxAnyq+m1mLwigzXBNKGCh6MEgIBpoM7cooKFm3yAgDvIFIMDhvgACyH8SgpgC1ioODQI+FAzeKGCTLwABuupNPQgIL/npEQF6+QIQwJvmC0CAoWoTDwKSjmp7g4CjYpMIAvymYj2DgJFagxACZq5maRDQUyoNH49h2ecW2J/7c7wEsimBEviXAH1pAL/2gF/cwK+e4Jdn8Os/v3xBC8Xv9bfOAAAAAElFTkSuQmCC</Image>
+<Url type="application/x-suggestions+json" method="GET" template="https://suggest.yandex.net/suggest-ff.cgi">
+ <Param name="part" value="{searchTerms}"/>
+</Url>
+<Url type="text/html" method="GET" template="https://yandex.ru/search">
+ <Param name="clid" value="2186727"/>
+ <Param name="text" value="{searchTerms}"/>
+</Url>
+<Url type="application/x-moz-tabletsearch" method="GET" template="https://yandex.ru/search">
+ <Param name="clid" value="2186733"/>
+ <Param name="text" value="{searchTerms}"/>
+</Url>
+<SearchForm>https://www.yandex.ru/</SearchForm>
+</SearchPlugin>
diff --git a/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/yandex-tr.xml b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/yandex-tr.xml
new file mode 100644
index 0000000000..5d798c746c
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/yandex-tr.xml
@@ -0,0 +1,22 @@
+<!-- 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/. -->
+
+<SearchPlugin xmlns="http://www.mozilla.org/2006/browser/search/">
+<ShortName>Yandex</ShortName>
+<Description>Yandex Türkiye arama motoru</Description>
+<InputEncoding>UTF-8</InputEncoding>
+<Image width="16" height="16">data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGAAAABgCAMAAADVRocKAAAAqFBMVEUAAAD29PL29PL29PP29PLd3d3w8PD29fP/JQD7ion35uT28/H8bmz36+r6paT+Lh7+KRL+Jwz41tX4ysn4wcD7h4X8dHL+OTD27+333t37lZT7jYz8aWb9Qz3+JQH36Of34+H40tH5vLv5uLj5sbD5rKv8e3n9WVb9Uk/9TUn9SEP+Myf+Jgb32tr4xMP6nJv7mpn7goH8gH78X1z9Pzb+NSn+JQD8Yl99ghQbAAAAB3RSTlMA88/IbQYbgu4OFQAAAe5JREFUaN7t2slywjAMBmCzKjSsISxhXwtlXwp9/zcr+VsQKfQU6dCpdfLooG/isWVPxsaYTDqVIIVIpNIZc4lsktQimTUmo1YfQsakSTXSJkWqkTIJUo2EIeWwgAUsYAFVwK84lyhhrALUnTA+MNYA3BKACSEUAB/1y01CKAAHAHWMYwG1/CXqg4cZOgHw4wPvKNT+ma4ifXLjAy1U6j58GNI1ig8EPZQaPv2woQBAM5TKRZMef1dsYIpajWcT1xIBCmUUq0aSizDVC+ID3BP296kAqRnJABtUW7rEsUWqKAS4DZTbEMc8TFQKQgC1AbxyYoCl2yEpYA2gxHNURGIsAvCMOCO6xhFgUw4oAsjfFu6Kp0wGKFQivX8CryoIUD5yenV4a0sBvnO3bJplNCdRwF3eLfwxNE8O4PY/5daxIFnAA3Dk68RWGKC3sOqqfz0sewNpoHhrb21upJJAH1thfv2WqSjAi/8cfG3jckEeGH0fkmPuGnIAb4UuHdD3pAHeCsMuOrcG4AHIn9FIpQHeCtxI5QFsBW6k4gC2At+E5QGcCtxI5QGcCtxIxQG+IO0IoQDQHsAaYxUgB+AFYwtYwAJEFrCABYgs8DR2zi9X97/5c9wCFrDAfwK0Hw2oP3tQf7ih/vRE/fGM+vOfTzkzCrugwvNDAAAAAElFTkSuQmCC</Image>
+<Url type="application/x-suggestions+json" method="GET" template="http://suggest.yandex.com.tr/suggest-ff.cgi">
+ <Param name="part" value="{searchTerms}"/>
+ <Param name="uil" value="tr"/>
+</Url>
+<Url type="text/html" method="GET" template="https://yandex.com.tr/search">
+ <Param name="clid" value="2186727"/>
+ <Param name="text" value="{searchTerms}"/>
+</Url>
+<Url type="application/x-moz-tabletsearch" method="GET" template="https://yandex.com.tr/search">
+ <Param name="clid" value="2186733"/>
+ <Param name="text" value="{searchTerms}"/>
+</Url>
+</SearchPlugin>
diff --git a/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/yandex.by.xml b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/yandex.by.xml
new file mode 100644
index 0000000000..a4c6ea7a55
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/yandex.by.xml
@@ -0,0 +1,22 @@
+<!-- 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/. -->
+
+<SearchPlugin xmlns="http://www.mozilla.org/2006/browser/search/">
+<ShortName>Яндекс</ShortName>
+<Description>Пошук з дапамогаю Яндекс</Description>
+<InputEncoding>UTF-8</InputEncoding>
+<Image width="16" height="16">data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGAAAABgCAMAAADVRocKAAAAqFBMVEUAAAD29PL29PL29PP29PLd3d3w8PD29fP/Jg76oKL33t3+Jxj27+342dn+Lyv28/H28fD36+r35+f35eT34OD9U1X+LCX4wMH5qqz7kJL+PDz7l5r8Z2v9TE3+OTj+NDH4y8v5ubr5trf5sLH8eHz8dHf9XF/9Pj/37Ov41tb40dH4x8j5vb75s7T6pKb7i438foH8bXD8YWP9UVP9RUb+KR77h4v7g4aogTBNAAAAB3RSTlMA88/IbQYbgu4OFQAAAcpJREFUaN7t2lduwkAURmETINcEV4zpvaXRA8n+dxbkX8ji3echiu8CzucBjRmhcRynXqtWDJhKtVZ3bvP8ZNg8Pd+en+pLqDs1Q6fmVA2dqlMxdCqOwVMCJVACJVAwEC9X46Dp3mdQMPCyurqPUygQ9fXoFJCkalJA8uqigDdWsbneJqGZNYoG1gqOfbsNAHTV23jGAOEly73GBgEL5T6NAjZZ7WwU0FZtiwG9LNaJMOCUxUaGAdrEQwzwFJtjgK/YBwZ0FWtjwFyxFgYsFYsxYKdYQn8H7xgwU6yLAS3FGhhgkyx24oBRFgsi+G3qzjEg1okrxQBbKbfDgLaW0PEpwPrqTd4pIPxSsNOIGMDaA1cz/VnMfN/vFw1IQI/vrTMIaPYBDNjbkQTyl1IzTdMxAnyq+m1mLwigzXBNKGCh6MEgIBpoM7cooKFm3yAgDvIFIMDhvgACyH8SgpgC1ioODQI+FAzeKGCTLwABuupNPQgIL/npEQF6+QIQwJvmC0CAoWoTDwKSjmp7g4CjYpMIAvymYj2DgJFagxACZq5maRDQUyoNH49h2ecW2J/7c7wEsimBEviXAH1pAL/2gF/cwK+e4Jdn8Os/v3xBC8Xv9bfOAAAAAElFTkSuQmCC</Image>
+<Url type="application/x-suggestions+json" method="GET" template="https://suggest.yandex.by/suggest-ff.cgi">
+ <Param name="part" value="{searchTerms}"/>
+</Url>
+<Url type="text/html" method="GET" template="https://yandex.by/search">
+ <Param name="clid" value="2186727"/>
+ <Param name="text" value="{searchTerms}"/>
+</Url>
+<Url type="application/x-moz-tabletsearch" method="GET" template="https://yandex.by/search">
+ <Param name="clid" value="2186733"/>
+ <Param name="text" value="{searchTerms}"/>
+</Url>
+<SearchForm>https://www.yandex.by/</SearchForm>
+</SearchPlugin>
diff --git a/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/yandex.xml b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/yandex.xml
new file mode 100644
index 0000000000..801ff5cbef
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/yandex.xml
@@ -0,0 +1,21 @@
+<!-- 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/. -->
+
+<SearchPlugin xmlns="http://www.mozilla.org/2006/browser/search/">
+<ShortName>Яндекс</ShortName>
+<InputEncoding>UTF-8</InputEncoding>
+<Image width="16" height="16">data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGAAAABgCAMAAADVRocKAAAAqFBMVEUAAAD29PL29PL29PP29PLd3d3w8PD29fP/Jg76oKL33t3+Jxj27+342dn+Lyv28/H28fD36+r35+f35eT34OD9U1X+LCX4wMH5qqz7kJL+PDz7l5r8Z2v9TE3+OTj+NDH4y8v5ubr5trf5sLH8eHz8dHf9XF/9Pj/37Ov41tb40dH4x8j5vb75s7T6pKb7i438foH8bXD8YWP9UVP9RUb+KR77h4v7g4aogTBNAAAAB3RSTlMA88/IbQYbgu4OFQAAAcpJREFUaN7t2lduwkAURmETINcEV4zpvaXRA8n+dxbkX8ji3echiu8CzucBjRmhcRynXqtWDJhKtVZ3bvP8ZNg8Pd+en+pLqDs1Q6fmVA2dqlMxdCqOwVMCJVACJVAwEC9X46Dp3mdQMPCyurqPUygQ9fXoFJCkalJA8uqigDdWsbneJqGZNYoG1gqOfbsNAHTV23jGAOEly73GBgEL5T6NAjZZ7WwU0FZtiwG9LNaJMOCUxUaGAdrEQwzwFJtjgK/YBwZ0FWtjwFyxFgYsFYsxYKdYQn8H7xgwU6yLAS3FGhhgkyx24oBRFgsi+G3qzjEg1okrxQBbKbfDgLaW0PEpwPrqTd4pIPxSsNOIGMDaA1cz/VnMfN/vFw1IQI/vrTMIaPYBDNjbkQTyl1IzTdMxAnyq+m1mLwigzXBNKGCh6MEgIBpoM7cooKFm3yAgDvIFIMDhvgACyH8SgpgC1ioODQI+FAzeKGCTLwABuupNPQgIL/npEQF6+QIQwJvmC0CAoWoTDwKSjmp7g4CjYpMIAvymYj2DgJFagxACZq5maRDQUyoNH49h2ecW2J/7c7wEsimBEviXAH1pAL/2gF/cwK+e4Jdn8Os/v3xBC8Xv9bfOAAAAAElFTkSuQmCC</Image>
+<Url type="application/x-suggestions+json" method="GET" template="https://suggest.yandex.net/suggest-ff.cgi">
+ <Param name="part" value="{searchTerms}"/>
+</Url>
+<Url type="text/html" method="GET" template="https://yandex.kz/search">
+ <Param name="clid" value="2186727"/>
+ <Param name="text" value="{searchTerms}"/>
+</Url>
+<Url type="application/x-moz-tabletsearch" method="GET" template="https://yandex.kz/search">
+ <Param name="clid" value="2186733"/>
+ <Param name="text" value="{searchTerms}"/>
+</Url>
+<SearchForm>https://www.yandex.kz/</SearchForm>
+</SearchPlugin>
diff --git a/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/youtube.xml b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/youtube.xml
new file mode 100644
index 0000000000..60a7897ae4
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/youtube.xml
@@ -0,0 +1,12 @@
+<?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/. -->
+<SearchPlugin xmlns="http://www.mozilla.org/2006/browser/search/">
+ <ShortName>YouTube</ShortName>
+ <Description>Search for videos on YouTube</Description>
+ <Tags>youtube video</Tags>
+ <Image height="16" width="16">data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAABa0lEQVR42u2YoYoCURSGBzSLk62L0TJvsEywWAxabRaFlQ2GQdY38AF8Ci0Gsy9gECybRU0GkQn++4fLbjm7K8wdmQPng6+I3rkfqHPnBIZhGIbxCAiCkL7QiL7SFu3QHu3TIX2nY5rQCf1wTtxrY/eeoftMz63RcmtG7hqhj82+0RX9pDeKJ3tz1165vVQf3XxMTxQF80Tj/zbfoFeKgnqljb8C1hQFd/3b5mv0riDgTmtSQJtCiW0pIFEUkEgBc0UBcylgkXnhKAIqlWcELKSATeaFp1PgeAT6faBUyjNgIwXsfQR8s90CcZxXwF4KOHgM+GG5BOp13wEHKeDiP8CRpsBsBoShr4CLFJB6DJA5n4HBACiXswakUsA9hwCZ3Q5oNjPdjfUH6P8K6f8R6/8b1X8j03+U0H+Y03+c1v9Ao/+RUv9Dvf6xiv7Blv7RojzcHRVouDui1TzG610P4/WuOF43DMMwjAf4ArcA0xFiL427AAAAAElFTkSuQmCC</Image>
+ <Url type="text/html" template="https://www.youtube.com/results?search_query={searchTerms}&amp;page={startPage?}&amp;utm_source=opensearch" />
+ <Query role="example" searchTerms="cat" />
+</SearchPlugin>
diff --git a/mobile/android/android-components/components/feature/search/src/main/java/mozilla/components/feature/search/BrowserStoreSearchAdapter.kt b/mobile/android/android-components/components/feature/search/src/main/java/mozilla/components/feature/search/BrowserStoreSearchAdapter.kt
new file mode 100644
index 0000000000..ffc6179d84
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/java/mozilla/components/feature/search/BrowserStoreSearchAdapter.kt
@@ -0,0 +1,41 @@
+/* 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.feature.search
+
+import mozilla.components.browser.state.action.ContentAction
+import mozilla.components.browser.state.selector.findTabOrCustomTabOrSelectedTab
+import mozilla.components.browser.state.store.BrowserStore
+import mozilla.components.concept.engine.search.SearchRequest
+
+/**
+ * Adapter which wraps a [browserStore] in order to fulfill the [SearchAdapter] interface.
+ *
+ * This class uses the [browserStore] to determine when private mode is active, and updates the
+ * [browserStore] whenever a new search has been requested.
+ *
+ * NOTE: this will add [SearchRequest]s to [BrowserStore.state] when [sendSearch] is called. Client
+ * code is responsible for consuming these requests and displaying something to the user.
+ *
+ * NOTE: client code is responsible for sending [ContentAction.ConsumeSearchRequestAction]s
+ * after consuming events. See [SearchFeature] for a component that will handle this for you.
+ *
+ * @param browserStore The application's [BrowserStore].
+ * @param tabId ID of the tab that requests the search, or null to use the selected tab.
+ */
+class BrowserStoreSearchAdapter(
+ private val browserStore: BrowserStore,
+ private val tabId: String? = null,
+) : SearchAdapter {
+
+ override fun sendSearch(isPrivate: Boolean, text: String) {
+ val selectedTabId = tabId ?: browserStore.state.selectedTabId ?: return
+ browserStore.dispatch(
+ ContentAction.UpdateSearchRequestAction(selectedTabId, SearchRequest(isPrivate, text)),
+ )
+ }
+
+ override fun isPrivateSession(): Boolean =
+ browserStore.state.findTabOrCustomTabOrSelectedTab(tabId)?.content?.private ?: false
+}
diff --git a/mobile/android/android-components/components/feature/search/src/main/java/mozilla/components/feature/search/SearchAdapter.kt b/mobile/android/android-components/components/feature/search/src/main/java/mozilla/components/feature/search/SearchAdapter.kt
new file mode 100644
index 0000000000..0d06911936
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/java/mozilla/components/feature/search/SearchAdapter.kt
@@ -0,0 +1,21 @@
+/* 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.feature.search
+
+/**
+ * May be implemented by client code in order to allow a component to start searches.
+ */
+interface SearchAdapter {
+
+ /**
+ * Called by the component to indicate that the user should be shown a search.
+ */
+ fun sendSearch(isPrivate: Boolean, text: String)
+
+ /**
+ * Called by the component to check whether or not the currently selected session is private.
+ */
+ fun isPrivateSession(): Boolean
+}
diff --git a/mobile/android/android-components/components/feature/search/src/main/java/mozilla/components/feature/search/SearchFeature.kt b/mobile/android/android-components/components/feature/search/src/main/java/mozilla/components/feature/search/SearchFeature.kt
new file mode 100644
index 0000000000..61d89a2844
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/java/mozilla/components/feature/search/SearchFeature.kt
@@ -0,0 +1,52 @@
+/* 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.feature.search
+
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.cancel
+import kotlinx.coroutines.flow.distinctUntilChangedBy
+import kotlinx.coroutines.flow.map
+import kotlinx.coroutines.flow.mapNotNull
+import mozilla.components.browser.state.action.ContentAction
+import mozilla.components.browser.state.selector.findTabOrCustomTabOrSelectedTab
+import mozilla.components.browser.state.store.BrowserStore
+import mozilla.components.concept.engine.search.SearchRequest
+import mozilla.components.lib.state.ext.flowScoped
+import mozilla.components.support.base.feature.LifecycleAwareFeature
+import mozilla.components.support.utils.ext.toNullablePair
+
+/**
+ * Lifecycle aware feature that forwards [SearchRequest]s from the [store] to [performSearch], and
+ * then consumes them.
+ *
+ * NOTE: that this only consumes SearchRequests, and will not hook up the [store] to a source of
+ * SearchRequests. See [mozilla.components.concept.engine.selection.SelectionActionDelegate] for use
+ * in generating SearchRequests.
+ */
+class SearchFeature(
+ private val store: BrowserStore,
+ private val tabId: String? = null,
+ private val performSearch: (SearchRequest, tabId: String) -> Unit,
+) : LifecycleAwareFeature {
+
+ private var scope: CoroutineScope? = null
+
+ override fun start() {
+ scope = store.flowScoped { flow ->
+ flow.map { state -> state.findTabOrCustomTabOrSelectedTab(tabId) }
+ .distinctUntilChangedBy { it?.content?.searchRequest }
+ // Do nothing if searchRequest or sessionId is null
+ .mapNotNull { tab -> Pair(tab?.content?.searchRequest, tab?.id).toNullablePair() }
+ .collect { (searchRequest, sessionId) ->
+ performSearch(searchRequest, sessionId)
+ store.dispatch(ContentAction.ConsumeSearchRequestAction(sessionId))
+ }
+ }
+ }
+
+ override fun stop() {
+ scope?.cancel()
+ }
+}
diff --git a/mobile/android/android-components/components/feature/search/src/main/java/mozilla/components/feature/search/SearchUseCases.kt b/mobile/android/android-components/components/feature/search/src/main/java/mozilla/components/feature/search/SearchUseCases.kt
new file mode 100644
index 0000000000..b3e8a1763b
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/java/mozilla/components/feature/search/SearchUseCases.kt
@@ -0,0 +1,343 @@
+/* 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.feature.search
+
+import mozilla.components.browser.state.action.ContentAction
+import mozilla.components.browser.state.action.EngineAction
+import mozilla.components.browser.state.action.SearchAction
+import mozilla.components.browser.state.search.SearchEngine
+import mozilla.components.browser.state.selector.findTabOrCustomTab
+import mozilla.components.browser.state.state.SessionState
+import mozilla.components.browser.state.state.selectedOrDefaultSearchEngine
+import mozilla.components.browser.state.store.BrowserStore
+import mozilla.components.concept.engine.EngineSession
+import mozilla.components.feature.search.ext.buildSearchUrl
+import mozilla.components.feature.session.SessionUseCases
+import mozilla.components.feature.tabs.TabsUseCases
+import mozilla.components.support.base.log.logger.Logger
+
+/**
+ * Contains use cases related to the search feature.
+ */
+class SearchUseCases(
+ store: BrowserStore,
+ tabsUseCases: TabsUseCases,
+ sessionUseCases: SessionUseCases,
+) {
+ interface SearchUseCase {
+ /**
+ * Triggers a search.
+ */
+ fun invoke(
+ searchTerms: String,
+ searchEngine: SearchEngine? = null,
+ parentSessionId: String? = null,
+ )
+ }
+
+ class DefaultSearchUseCase(
+ private val store: BrowserStore,
+ private val tabsUseCases: TabsUseCases,
+ private val sessionUseCases: SessionUseCases,
+ ) : SearchUseCase {
+ private val logger = Logger("DefaultSearchUseCase")
+
+ /**
+ * Triggers a search in the currently selected session.
+ */
+ override fun invoke(
+ searchTerms: String,
+ searchEngine: SearchEngine?,
+ parentSessionId: String?,
+ ) {
+ invoke(searchTerms, store.state.selectedTabId, searchEngine)
+ }
+
+ /**
+ * Triggers a search using the default search engine for the provided search terms.
+ *
+ * @param searchTerms the search terms.
+ * @param sessionId the ID of the session/tab to use, or null if the currently selected tab
+ * should be used.
+ * @param searchEngine Search Engine to use, or the default search engine if none is provided
+ * @param flags Flags that will be used when loading the URL.
+ * @param additionalHeaders The extra headers to use when loading the URL.
+ */
+ operator fun invoke(
+ searchTerms: String,
+ sessionId: String? = store.state.selectedTabId,
+ searchEngine: SearchEngine? = null,
+ flags: EngineSession.LoadUrlFlags = EngineSession.LoadUrlFlags.none(),
+ additionalHeaders: Map<String, String>? = null,
+ ) {
+ val searchUrl = searchEngine?.let {
+ searchEngine.buildSearchUrl(searchTerms)
+ } ?: store.state.search.selectedOrDefaultSearchEngine?.buildSearchUrl(searchTerms)
+
+ if (searchUrl == null) {
+ logger.warn("No default search engine available to perform search")
+ return
+ }
+
+ val id = if (sessionId == null) {
+ // If no `sessionId` was passed in then create a new tab
+ tabsUseCases.addTab(
+ url = searchUrl,
+ flags = flags,
+ isSearch = true,
+ searchEngineName = searchEngine?.name,
+ additionalHeaders = additionalHeaders,
+ )
+ } else {
+ // If we got a `sessionId` then try to find the tab and load the search URL in it
+ val existingTab = store.state.findTabOrCustomTab(sessionId)
+ if (existingTab != null) {
+ store.dispatch(ContentAction.UpdateIsSearchAction(existingTab.id, true, searchEngine?.name))
+ store.dispatch(
+ EngineAction.LoadUrlAction(
+ tabId = existingTab.id,
+ url = searchUrl,
+ flags = flags,
+ additionalHeaders = additionalHeaders,
+ ),
+ )
+ existingTab.id
+ } else {
+ // If the tab with the provided id was not found then create a new tab
+ tabsUseCases.addTab(
+ url = searchUrl,
+ isSearch = true,
+ searchEngineName = searchEngine?.name,
+ flags = flags,
+ additionalHeaders = additionalHeaders,
+ )
+ }
+ }
+
+ store.dispatch(ContentAction.UpdateSearchTermsAction(id, searchTerms))
+ }
+ }
+
+ class NewTabSearchUseCase(
+ private val store: BrowserStore,
+ private val tabsUseCases: TabsUseCases,
+ private val isPrivate: Boolean,
+ ) : SearchUseCase {
+ private val logger = Logger("NewTabSearchUseCase")
+
+ override fun invoke(
+ searchTerms: String,
+ searchEngine: SearchEngine?,
+ parentSessionId: String?,
+ ) {
+ invoke(
+ searchTerms,
+ source = SessionState.Source.Internal.None,
+ selected = true,
+ searchEngine = searchEngine,
+ parentSessionId = parentSessionId,
+ )
+ }
+
+ /**
+ * Triggers a search on a new session, using the default search engine for the provided search terms.
+ *
+ * @param searchTerms the search terms.
+ * @param selected whether or not the new session should be selected, defaults to true.
+ * @param source the source of the new session.
+ * @param searchEngine Search Engine to use, or the default search engine if none is provided
+ * @param parentSessionId optional parent session to attach this new search session to
+ * @param flags Flags that will be used when loading the URL.
+ * @param additionalHeaders The extra headers to use when loading the URL.
+ */
+ operator fun invoke(
+ searchTerms: String,
+ source: SessionState.Source,
+ selected: Boolean = true,
+ searchEngine: SearchEngine? = null,
+ parentSessionId: String? = null,
+ flags: EngineSession.LoadUrlFlags = EngineSession.LoadUrlFlags.none(),
+ additionalHeaders: Map<String, String>? = null,
+ ) {
+ val searchUrl = searchEngine?.let {
+ searchEngine.buildSearchUrl(searchTerms)
+ } ?: store.state.search.selectedOrDefaultSearchEngine?.buildSearchUrl(searchTerms)
+
+ if (searchUrl == null) {
+ logger.warn("No default search engine available to perform search")
+ return
+ }
+
+ val id = tabsUseCases.addTab(
+ url = searchUrl,
+ parentId = parentSessionId,
+ flags = flags,
+ source = source,
+ selectTab = selected,
+ private = isPrivate,
+ isSearch = true,
+ additionalHeaders = additionalHeaders,
+ )
+
+ store.dispatch(ContentAction.UpdateSearchTermsAction(id, searchTerms))
+ }
+ }
+
+ /**
+ * Adds a new search engine to the list of search engines the user can use for searches.
+ */
+ class AddNewSearchEngineUseCase(
+ private val store: BrowserStore,
+ ) {
+ /**
+ * Adds the given [searchEngine] to the list of search engines the user can use for searches.
+ */
+ operator fun invoke(
+ searchEngine: SearchEngine,
+ ) {
+ when (searchEngine.type) {
+ SearchEngine.Type.BUNDLED -> store.dispatch(
+ SearchAction.ShowSearchEngineAction(searchEngine.id),
+ )
+
+ SearchEngine.Type.BUNDLED_ADDITIONAL -> store.dispatch(
+ SearchAction.AddAdditionalSearchEngineAction(searchEngine.id),
+ )
+
+ SearchEngine.Type.CUSTOM -> store.dispatch(
+ SearchAction.UpdateCustomSearchEngineAction(searchEngine),
+ )
+
+ SearchEngine.Type.APPLICATION -> { /* Do nothing */ }
+ }
+ }
+ }
+
+ /**
+ * Removes a search engine from the list of search engines the user can use for searches.
+ */
+ class RemoveExistingSearchEngineUseCase(
+ private val store: BrowserStore,
+ ) {
+ /**
+ * Removes the given [searchEngine] from the list of search engines the user can use for
+ * searches.
+ */
+ operator fun invoke(
+ searchEngine: SearchEngine,
+ ) {
+ when (searchEngine.type) {
+ SearchEngine.Type.BUNDLED -> store.dispatch(
+ SearchAction.HideSearchEngineAction(searchEngine.id),
+ )
+
+ SearchEngine.Type.BUNDLED_ADDITIONAL -> store.dispatch(
+ SearchAction.RemoveAdditionalSearchEngineAction(searchEngine.id),
+ )
+
+ SearchEngine.Type.CUSTOM -> store.dispatch(
+ SearchAction.RemoveCustomSearchEngineAction(searchEngine.id),
+ )
+
+ SearchEngine.Type.APPLICATION -> { /* Do nothing */ }
+ }
+ }
+ }
+
+ /**
+ * Marks a search engine as "selected" by the user to be the default search engine to perform
+ * searches with.
+ */
+ class SelectSearchEngineUseCase(
+ private val store: BrowserStore,
+ ) {
+ /**
+ * Marks the given [searchEngine] as "selected" by the user to be the default search engine
+ * to perform searches with.
+ */
+ operator fun invoke(
+ searchEngine: SearchEngine,
+ ) {
+ val name = if (searchEngine.type == SearchEngine.Type.BUNDLED) {
+ // For bundled search engines we additionally save the name of the search engine.
+ // We do this because with "home" region changes the previous search plugin/id
+ // may no longer be available, but there may be a clone of the search engine with
+ // a different plugin/id using the same name.
+ // This should be safe to do since Fenix as well as Fennec only kept the name of
+ // the default search engine.
+ // For all other cases (e.g. custom search engines) we only care about the ID and
+ // do not want to switch to a different search engine based on its name once it is
+ // gone.
+ searchEngine.name
+ } else {
+ null
+ }
+
+ store.dispatch(
+ SearchAction.SelectSearchEngineAction(searchEngine.id, name),
+ )
+ }
+ }
+
+ /**
+ * Updates the list of unselected shortcuts, to be hidden from the quick search menus.
+ */
+ class UpdateDisabledSearchEngineIdsUseCase(private val store: BrowserStore) {
+ /**
+ * Updates the list of unselected shortcuts with the given [searchEngineId], to be hidden from
+ * the quick search menus.
+ */
+ operator fun invoke(
+ searchEngineId: String,
+ isEnabled: Boolean,
+ ) {
+ store.dispatch(SearchAction.UpdateDisabledSearchEngineIdsAction(searchEngineId, isEnabled))
+ }
+ }
+
+ /**
+ * Restores bundled search engines that may have been removed.
+ */
+ class RestoreHiddenSearchEnginesUseCase(private val store: BrowserStore) {
+ /**
+ * Restores all hidden engines back to the bundled engine list.
+ */
+ operator fun invoke() {
+ store.dispatch(SearchAction.RestoreHiddenSearchEnginesAction)
+ }
+ }
+
+ val defaultSearch: DefaultSearchUseCase by lazy {
+ DefaultSearchUseCase(store, tabsUseCases, sessionUseCases)
+ }
+
+ val newTabSearch: NewTabSearchUseCase by lazy {
+ NewTabSearchUseCase(store, tabsUseCases, false)
+ }
+
+ val newPrivateTabSearch: NewTabSearchUseCase by lazy {
+ NewTabSearchUseCase(store, tabsUseCases, true)
+ }
+
+ val addSearchEngine: AddNewSearchEngineUseCase by lazy {
+ AddNewSearchEngineUseCase(store)
+ }
+
+ val removeSearchEngine: RemoveExistingSearchEngineUseCase by lazy {
+ RemoveExistingSearchEngineUseCase(store)
+ }
+
+ val selectSearchEngine: SelectSearchEngineUseCase by lazy {
+ SelectSearchEngineUseCase(store)
+ }
+
+ val updateDisabledSearchEngineIds: UpdateDisabledSearchEngineIdsUseCase by lazy {
+ UpdateDisabledSearchEngineIdsUseCase(store)
+ }
+
+ val restoreHiddenSearchEngines: RestoreHiddenSearchEnginesUseCase by lazy {
+ RestoreHiddenSearchEnginesUseCase(store)
+ }
+}
diff --git a/mobile/android/android-components/components/feature/search/src/main/java/mozilla/components/feature/search/ext/BrowserStore.kt b/mobile/android/android-components/components/feature/search/src/main/java/mozilla/components/feature/search/ext/BrowserStore.kt
new file mode 100644
index 0000000000..2fce10dfe8
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/java/mozilla/components/feature/search/ext/BrowserStore.kt
@@ -0,0 +1,36 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+package mozilla.components.feature.search.ext
+
+import mozilla.components.browser.state.action.BrowserAction
+import mozilla.components.browser.state.state.BrowserState
+import mozilla.components.browser.state.state.selectedOrDefaultSearchEngine
+import mozilla.components.browser.state.store.BrowserStore
+import mozilla.components.lib.state.Store
+
+/**
+ * Waits (asynchronously, non-blocking) for the search state to be loaded from disk (when using
+ * `RegionMiddleware` and `SearchMiddleware`) and invokes [block] with the default search engine
+ * (or `null` if no default could be loaded).
+ */
+fun BrowserStore.waitForSelectedOrDefaultSearchEngine(
+ block: (mozilla.components.browser.state.search.SearchEngine?) -> Unit,
+) {
+ // Did we already load the search state? In that case we can invoke `block` immediately.
+ if (state.search.complete) {
+ block(state.search.selectedOrDefaultSearchEngine)
+ return
+ }
+
+ // Otherwise: Wait for the search state to be loaded and then invoke `block`.
+ var subscription: Store.Subscription<BrowserState, BrowserAction>? = null
+ subscription = observeManually { state ->
+ if (state.search.complete) {
+ block(state.search.selectedOrDefaultSearchEngine)
+ subscription!!.unsubscribe()
+ }
+ }
+ subscription.resume()
+}
diff --git a/mobile/android/android-components/components/feature/search/src/main/java/mozilla/components/feature/search/ext/SearchEngine.kt b/mobile/android/android-components/components/feature/search/src/main/java/mozilla/components/feature/search/ext/SearchEngine.kt
new file mode 100644
index 0000000000..08615935f4
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/java/mozilla/components/feature/search/ext/SearchEngine.kt
@@ -0,0 +1,148 @@
+/* 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.feature.search.ext
+
+import android.graphics.Bitmap
+import android.net.Uri
+import androidx.annotation.VisibleForTesting
+import mozilla.components.browser.state.search.OS_SEARCH_ENGINE_TERMS_PARAM
+import mozilla.components.browser.state.search.SearchEngine
+import mozilla.components.browser.state.state.SearchState
+import mozilla.components.browser.state.state.searchEngines
+import mozilla.components.browser.state.state.selectedOrDefaultSearchEngine
+import mozilla.components.feature.search.internal.SearchUrlBuilder
+import mozilla.components.feature.search.storage.SearchEngineReader
+import java.io.InputStream
+import java.lang.IllegalArgumentException
+import java.util.UUID
+
+/**
+ * Creates a custom [SearchEngine].
+ */
+fun createSearchEngine(
+ name: String,
+ url: String,
+ icon: Bitmap,
+ inputEncoding: String? = null,
+ suggestUrl: String? = null,
+ isGeneral: Boolean = false,
+): SearchEngine {
+ if (!url.contains(OS_SEARCH_ENGINE_TERMS_PARAM)) {
+ throw IllegalArgumentException("URL does not contain search terms placeholder")
+ }
+
+ return SearchEngine(
+ id = UUID.randomUUID().toString(),
+ name = name,
+ icon = icon,
+ inputEncoding = inputEncoding,
+ type = SearchEngine.Type.CUSTOM,
+ resultUrls = listOf(url),
+ suggestUrl = suggestUrl,
+ isGeneral = isGeneral,
+ )
+}
+
+/**
+ * Creates an application [SearchEngine].
+ */
+fun createApplicationSearchEngine(
+ id: String? = null,
+ name: String,
+ url: String,
+ inputEncoding: String? = null,
+ icon: Bitmap,
+ suggestUrl: String? = null,
+): SearchEngine {
+ return SearchEngine(
+ id = id ?: UUID.randomUUID().toString(),
+ name = name,
+ icon = icon,
+ inputEncoding = inputEncoding,
+ type = SearchEngine.Type.APPLICATION,
+ resultUrls = listOf(url),
+ suggestUrl = suggestUrl,
+ )
+}
+
+/**
+ * Whether this [SearchEngine] has a [SearchEngine.suggestUrl] set and can provide search
+ * suggestions.
+ */
+val SearchEngine.canProvideSearchSuggestions: Boolean
+ get() = suggestUrl != null
+
+/**
+ * Creates an URL to retrieve search suggestions for the provided [query].
+ */
+fun SearchEngine.buildSuggestionsURL(query: String): String? {
+ val builder = SearchUrlBuilder(this)
+ return builder.buildSuggestionUrl(query)
+}
+
+/**
+ * Builds a URL to search for the given search terms with this search engine.
+ */
+fun SearchEngine.buildSearchUrl(searchTerm: String): String {
+ val builder = SearchUrlBuilder(this)
+ return builder.buildSearchUrl(searchTerm)
+}
+
+/**
+ * Parses a [SearchEngine] from the given [stream].
+ */
+@Deprecated("Only for migrating legacy search engines. Will eventually be removed.")
+fun parseLegacySearchEngine(id: String, stream: InputStream): SearchEngine {
+ val reader = SearchEngineReader(SearchEngine.Type.CUSTOM)
+ return reader.loadStream(id, stream)
+}
+
+/**
+ * Given a [SearchState], determine if the passed-in [url] is a known search results page url
+ * and what are the associated search terms.
+ * @return Search terms if [url] is a known search results page, `null` otherwise.
+ */
+fun SearchState.parseSearchTerms(url: String): String? {
+ val parsedUrl = Uri.parse(url)
+ // Default/selected engine is the most likely to match, check it first.
+ val currentEngine = this.selectedOrDefaultSearchEngine
+ // Or go through the rest of known engines.
+ val fallback: () -> String? = fallback@{
+ this.searchEngines.forEach { searchEngine ->
+ searchEngine.parseSearchTerms(parsedUrl)?.let { return@fallback it }
+ }
+ return@fallback null
+ }
+ return currentEngine?.parseSearchTerms(parsedUrl) ?: fallback()
+}
+
+/**
+ * Given a [SearchEngine], determine if the passed-in [url] matches its results template,
+ * and what are the associated search terms.
+ * @return Search terms if [url] matches the results page template, `null` otherwise.
+ */
+@VisibleForTesting
+fun SearchEngine.parseSearchTerms(url: Uri): String? {
+ // Basic approach:
+ // - look at the "base" of the template url; if there's a match, continue
+ // - see if the GET parameter for the search terms is present in the url
+ // - if that param present, its value is our answer if it's non-empty
+ val searchResultsRoot = this.resultsUrl.authority + this.resultsUrl.path
+ val urlRoot = url.authority + url.path
+
+ return if (searchResultsRoot == urlRoot) {
+ val searchTerms = try {
+ this.searchParameterName?.let {
+ url.getQueryParameter(it)
+ }
+ } catch (e: UnsupportedOperationException) {
+ // Non-hierarchical url.
+ null
+ }
+ searchTerms.takeUnless { it.isNullOrEmpty() }
+ } else {
+ null
+ }
+}
diff --git a/mobile/android/android-components/components/feature/search/src/main/java/mozilla/components/feature/search/internal/SearchUrlBuilder.kt b/mobile/android/android-components/components/feature/search/src/main/java/mozilla/components/feature/search/internal/SearchUrlBuilder.kt
new file mode 100644
index 0000000000..9fc9f61dd5
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/java/mozilla/components/feature/search/internal/SearchUrlBuilder.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.feature.search.internal
+
+import android.net.Uri
+import android.text.TextUtils
+import mozilla.components.browser.state.search.OS_SEARCH_ENGINE_TERMS_PARAM
+import mozilla.components.browser.state.search.SearchEngine
+import java.io.UnsupportedEncodingException
+import java.net.URLEncoder
+import java.util.Locale
+
+// We are using string concatenation here to avoid the Kotlin compiler interpreting this
+// as string templates. It is possible to escape the string accordingly. But this seems to
+// be inconsistent between Kotlin versions. So to be safe we avoid this completely by
+// constructing the strings manually.
+
+// Parameters copied from nsSearchService.js
+private const val MOZ_PARAM_LOCALE = "{" + "moz:locale" + "}"
+private const val MOZ_PARAM_DIST_ID = "{" + "moz:distributionID" + "}"
+private const val MOZ_PARAM_OFFICIAL = "{" + "moz:official" + "}"
+
+// Supported OpenSearch parameters
+// See http://opensearch.a9.com/spec/1.1/querysyntax/#core
+private const val OS_PARAM_USER_DEFINED = OS_SEARCH_ENGINE_TERMS_PARAM
+private const val OS_PARAM_INPUT_ENCODING = "{" + "inputEncoding" + "}"
+private const val OS_PARAM_LANGUAGE = "{" + "language" + "}"
+private const val OS_PARAM_OUTPUT_ENCODING = "{" + "outputEncoding" + "}"
+private const val OS_PARAM_OPTIONAL = "\\{" + "(?:\\w+:)?\\w+?" + "\\}"
+
+internal class SearchUrlBuilder(
+ private val searchEngine: SearchEngine,
+) {
+ fun buildSearchUrl(searchTerms: String): String {
+ // The parser should have put the best URL for this device at the beginning of the list.
+ val template = searchEngine.resultUrls[0]
+ return buildUrl(template, searchTerms)
+ }
+
+ fun buildSuggestionUrl(searchTerms: String): String? {
+ val template = searchEngine.suggestUrl ?: return null
+ return buildUrl(template, searchTerms)
+ }
+
+ private fun buildUrl(template: String, searchTerms: String): String {
+ val templateUri = Uri.decode(template)
+ val inputEncoding = searchEngine.inputEncoding ?: "UTF-8"
+ val query = try {
+ // Although android.net.Uri.encode convert space (U+0x20) to "%20", java.net.URLEncoder convert it to "+".
+ URLEncoder.encode(searchTerms, inputEncoding).replace("+", "%20")
+ } catch (e: UnsupportedEncodingException) {
+ Uri.encode(searchTerms)
+ }
+ val urlWithSubstitutions = paramSubstitution(templateUri, query, inputEncoding)
+ return normalize(urlWithSubstitutions) // User-entered search engines may need normalization.
+ }
+}
+
+/**
+ * Formats template string with proper parameters. Modeled after ParamSubstitution in nsSearchService.js
+ */
+private fun paramSubstitution(template: String, query: String, inputEncoding: String): String {
+ var result = template
+ val locale = Locale.getDefault().toString()
+
+ result = result.replace(MOZ_PARAM_LOCALE, locale)
+ result = result.replace(MOZ_PARAM_DIST_ID, "")
+ result = result.replace(MOZ_PARAM_OFFICIAL, "unofficial")
+
+ result = result.replace(OS_PARAM_USER_DEFINED, query)
+ result = result.replace(OS_PARAM_INPUT_ENCODING, inputEncoding)
+
+ result = result.replace(OS_PARAM_LANGUAGE, locale)
+ result = result.replace(OS_PARAM_OUTPUT_ENCODING, "UTF-8")
+
+ // Replace any optional parameters
+ result = result.replace(OS_PARAM_OPTIONAL.toRegex(), "")
+
+ return result
+}
+
+private fun normalize(input: String): String {
+ val trimmedInput = input.trim { it <= ' ' }
+ var uri = Uri.parse(trimmedInput)
+
+ if (TextUtils.isEmpty(uri.scheme)) {
+ uri = Uri.parse("http://$trimmedInput")
+ }
+
+ return uri.toString()
+}
diff --git a/mobile/android/android-components/components/feature/search/src/main/java/mozilla/components/feature/search/middleware/AdsTelemetryMiddleware.kt b/mobile/android/android-components/components/feature/search/src/main/java/mozilla/components/feature/search/middleware/AdsTelemetryMiddleware.kt
new file mode 100644
index 0000000000..5139af8740
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/java/mozilla/components/feature/search/middleware/AdsTelemetryMiddleware.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.feature.search.middleware
+
+import androidx.annotation.VisibleForTesting
+import mozilla.components.browser.state.action.BrowserAction
+import mozilla.components.browser.state.action.ContentAction
+import mozilla.components.browser.state.selector.findTab
+import mozilla.components.browser.state.state.BrowserState
+import mozilla.components.browser.state.store.BrowserStore
+import mozilla.components.feature.search.telemetry.ads.AdsTelemetry
+import mozilla.components.lib.state.Middleware
+import mozilla.components.lib.state.MiddlewareContext
+import mozilla.components.support.base.log.logger.Logger
+
+/**
+ * [BrowserStore] middleware to be used alongside with [AdsTelemetry] to check when an ad shown
+ * in search results is clicked.
+ */
+class AdsTelemetryMiddleware(
+ private val adsTelemetry: AdsTelemetry,
+) : Middleware<BrowserState, BrowserAction> {
+ @VisibleForTesting
+ internal val redirectChain = mutableMapOf<String, RedirectChain>()
+ private val logger = Logger("AdsTelemetryMiddleware")
+
+ @Suppress("TooGenericExceptionCaught")
+ override fun invoke(
+ context: MiddlewareContext<BrowserState, BrowserAction>,
+ next: (BrowserAction) -> Unit,
+ action: BrowserAction,
+ ) {
+ when (action) {
+ is ContentAction.UpdateLoadRequestAction -> {
+ context.state.findTab(action.sessionId)?.let { tab ->
+ // Collect all load requests in between location changes
+ if (!redirectChain.containsKey(action.sessionId) && action.loadRequest.url != tab.content.url) {
+ redirectChain[action.sessionId] = RedirectChain(tab.content.url)
+ }
+
+ redirectChain[action.sessionId]?.add(action.loadRequest.url)
+ }
+ }
+ is ContentAction.UpdateUrlAction -> {
+ redirectChain[action.sessionId]?.let {
+ // Record ads telemetry providing all redirects
+ try {
+ adsTelemetry.checkIfAddWasClicked(it.root, it.chain)
+ } catch (t: Throwable) {
+ logger.info("Failed to record search telemetry", t)
+ } finally {
+ redirectChain.remove(action.sessionId)
+ }
+ }
+ }
+ else -> {
+ // no-op
+ }
+ }
+
+ next(action)
+ }
+}
+
+/**
+ * Utility to collect URLs / load requests in between location changes.
+ */
+@VisibleForTesting
+internal class RedirectChain(val root: String) {
+ val chain = mutableListOf<String>()
+
+ fun add(url: String) {
+ chain.add(url)
+ }
+}
diff --git a/mobile/android/android-components/components/feature/search/src/main/java/mozilla/components/feature/search/middleware/SearchMiddleware.kt b/mobile/android/android-components/components/feature/search/src/main/java/mozilla/components/feature/search/middleware/SearchMiddleware.kt
new file mode 100644
index 0000000000..c748ce9c21
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/java/mozilla/components/feature/search/middleware/SearchMiddleware.kt
@@ -0,0 +1,397 @@
+/* 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.feature.search.middleware
+
+import android.content.Context
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.async
+import kotlinx.coroutines.launch
+import mozilla.components.browser.state.action.BrowserAction
+import mozilla.components.browser.state.action.SearchAction
+import mozilla.components.browser.state.search.RegionState
+import mozilla.components.browser.state.search.SearchEngine
+import mozilla.components.browser.state.state.BrowserState
+import mozilla.components.browser.state.state.SearchState
+import mozilla.components.feature.search.storage.BundledSearchEnginesStorage
+import mozilla.components.feature.search.storage.CustomSearchEngineStorage
+import mozilla.components.feature.search.storage.SearchMetadataStorage
+import mozilla.components.lib.state.Middleware
+import mozilla.components.lib.state.MiddlewareContext
+import mozilla.components.lib.state.Store
+import mozilla.components.support.base.log.logger.Logger
+import java.util.Locale
+import kotlin.coroutines.CoroutineContext
+
+/**
+ * Holds data for the search extra params.
+ */
+data class SearchExtraParams(
+ val searchEngineName: String,
+ val featureEnablerName: String?,
+ val featureEnablerParam: String?,
+ val channelIdName: String,
+ val channelIdParam: String,
+)
+
+/**
+ * [Middleware] implementation for loading and saving [SearchEngine]s whenever the state changes.
+ *
+ * @param additionalBundledSearchEngineIds List of (bundled) search engine IDs that will be loaded
+ * in addition to the search engines for the user's region and made available through
+ * [SearchState.additionalSearchEngines] and [SearchState.additionalSearchEngines].
+ * @param migration Interface for a class that can provide data from a legacy system to be imported into the
+ * storage used by the middleware.
+ * @param customStorage A storage for custom search engines of the user.
+ * @param bundleStorage A storage for loading bundled search engines.
+ * @param metadataStorage A storage for saving additional metadata related to search.
+ * @param searchExtraParams Optional search extra params.
+ * @param ioDispatcher The coroutine dispatcher to be used when loading.
+ */
+class SearchMiddleware(
+ context: Context,
+ private val additionalBundledSearchEngineIds: List<String> = emptyList(),
+ private val migration: Migration? = null,
+ private val customStorage: CustomStorage = CustomSearchEngineStorage(context),
+ private val bundleStorage: BundleStorage = BundledSearchEnginesStorage(context),
+ private val metadataStorage: MetadataStorage = SearchMetadataStorage(
+ context,
+ additionalBundledSearchEngineIds.toSet(),
+ ),
+ private val searchExtraParams: SearchExtraParams? = null,
+ private val ioDispatcher: CoroutineContext = Dispatchers.IO,
+) : Middleware<BrowserState, BrowserAction> {
+ private val logger = Logger("SearchMiddleware")
+ private val scope = CoroutineScope(ioDispatcher)
+
+ override fun invoke(
+ context: MiddlewareContext<BrowserState, BrowserAction>,
+ next: (BrowserAction) -> Unit,
+ action: BrowserAction,
+ ) {
+ when (action) {
+ is SearchAction.SetRegionAction -> loadSearchEngines(context.store, action.regionState, action.distribution)
+ is SearchAction.UpdateCustomSearchEngineAction -> saveCustomSearchEngine(action)
+ is SearchAction.RemoveCustomSearchEngineAction -> removeCustomSearchEngine(action)
+ is SearchAction.SelectSearchEngineAction -> updateSearchEngineSelection(action)
+ else -> {
+ // no-op
+ }
+ }
+
+ next(action)
+
+ when (action) {
+ is SearchAction.ShowSearchEngineAction, is SearchAction.HideSearchEngineAction,
+ is SearchAction.RestoreHiddenSearchEnginesAction,
+ -> updateHiddenSearchEngines(context.state.search.hiddenSearchEngines)
+ is SearchAction.AddAdditionalSearchEngineAction, is SearchAction.RemoveAdditionalSearchEngineAction ->
+ updateAdditionalSearchEngines(context.state.search.additionalSearchEngines)
+ is SearchAction.UpdateDisabledSearchEngineIdsAction -> updateDisabledSearchEngineIds(
+ context.store,
+ action,
+ )
+ else -> {
+ // no-op
+ }
+ }
+ }
+
+ private fun loadSearchEngines(
+ store: Store<BrowserState, BrowserAction>,
+ region: RegionState,
+ distribution: String? = null,
+ ) = scope.launch {
+ val migrationValues = migration?.getValuesToMigrate()
+ performCustomSearchEnginesMigration(migrationValues)
+
+ val regionBundle = async(ioDispatcher) {
+ bundleStorage.load(
+ region = region,
+ distribution = distribution,
+ searchExtraParams = searchExtraParams,
+ coroutineContext = ioDispatcher,
+ )
+ }
+ val customSearchEngines = async(ioDispatcher) { customStorage.loadSearchEngineList() }
+ val hiddenSearchEngineIds = async(ioDispatcher) { metadataStorage.getHiddenSearchEngines() }
+ val disabledSearchEngineIds = async(ioDispatcher) { metadataStorage.getDisabledSearchEngineIds() }
+ val additionalSearchEngineIds = async(ioDispatcher) { metadataStorage.getAdditionalSearchEngines() }
+ val allAdditionalSearchEngines = async(ioDispatcher) {
+ bundleStorage.load(
+ ids = additionalBundledSearchEngineIds,
+ searchExtraParams = searchExtraParams,
+ coroutineContext = ioDispatcher,
+ )
+ }
+
+ val hiddenSearchEngines = mutableListOf<SearchEngine>()
+ val filteredRegionSearchEngines = regionBundle.await().list.filter { searchEngine ->
+ if (hiddenSearchEngineIds.await().contains(searchEngine.id)) {
+ hiddenSearchEngines.add(searchEngine)
+ false
+ } else {
+ true
+ }
+ }
+
+ val regionSearchEngineIds = regionBundle.await().list.map { searchEngine -> searchEngine.id }
+
+ val additionalSearchEngines = allAdditionalSearchEngines.await().filter { searchEngine ->
+ searchEngine.id in additionalSearchEngineIds.await() &&
+ searchEngine.id !in regionSearchEngineIds
+ }
+
+ val additionalAvailableSearchEngines = allAdditionalSearchEngines.await().filter { searchEngine ->
+ searchEngine.id !in additionalSearchEngineIds.await() &&
+ searchEngine.id !in regionSearchEngineIds
+ }
+
+ performDefaultSearchEngineMigration(
+ migrationValues,
+ filteredRegionSearchEngines + customSearchEngines.await() + additionalSearchEngines,
+ )
+ val userChoice = async(ioDispatcher) { metadataStorage.getUserSelectedSearchEngine() }
+
+ val action = SearchAction.SetSearchEnginesAction(
+ regionSearchEngines = filteredRegionSearchEngines,
+ regionDefaultSearchEngineId = regionBundle.await().defaultSearchEngineId,
+ userSelectedSearchEngineId = userChoice.await()?.searchEngineId,
+ userSelectedSearchEngineName = userChoice.await()?.searchEngineName,
+ customSearchEngines = customSearchEngines.await(),
+ hiddenSearchEngines = hiddenSearchEngines,
+ disabledSearchEngineIds = disabledSearchEngineIds.await(),
+ additionalSearchEngines = additionalSearchEngines,
+ additionalAvailableSearchEngines = additionalAvailableSearchEngines,
+ regionSearchEnginesOrder = regionSearchEngineIds,
+ )
+ store.dispatch(action)
+ }
+
+ private fun updateSearchEngineSelection(
+ action: SearchAction.SelectSearchEngineAction,
+ ) = scope.launch {
+ metadataStorage.setUserSelectedSearchEngine(
+ action.searchEngineId,
+ action.searchEngineName,
+ )
+ }
+
+ private fun removeCustomSearchEngine(
+ action: SearchAction.RemoveCustomSearchEngineAction,
+ ) = scope.launch {
+ customStorage.removeSearchEngine(action.searchEngineId)
+ }
+
+ private fun saveCustomSearchEngine(
+ action: SearchAction.UpdateCustomSearchEngineAction,
+ ) = scope.launch {
+ customStorage.saveSearchEngine(action.searchEngine)
+ }
+
+ private fun updateHiddenSearchEngines(
+ hiddenSearchEngines: List<SearchEngine>,
+ ) = scope.launch {
+ metadataStorage.setHiddenSearchEngines(
+ hiddenSearchEngines.map { searchEngine -> searchEngine.id },
+ )
+ }
+
+ private fun updateAdditionalSearchEngines(
+ additionalSearchEngines: List<SearchEngine>,
+ ) = scope.launch {
+ metadataStorage.setAdditionalSearchEngines(
+ additionalSearchEngines.map { searchEngine -> searchEngine.id },
+ )
+ }
+
+ private fun updateDisabledSearchEngineIds(
+ store: Store<BrowserState, BrowserAction>,
+ action: SearchAction.UpdateDisabledSearchEngineIdsAction,
+ ) = scope.launch {
+ val disabledIds = store.state.search.disabledSearchEngineIds
+ val updatedList = if (action.isEnabled) {
+ disabledIds - action.searchEngineId
+ } else {
+ disabledIds + action.searchEngineId
+ }
+ metadataStorage.setDisabledSearchEngineIds(updatedList)
+ }
+
+ private suspend fun performCustomSearchEnginesMigration(values: Migration.MigrationValues?) {
+ if (values == null) {
+ return
+ }
+
+ values.customSearchEngines.forEach { searchEngine ->
+ customStorage.saveSearchEngine(searchEngine)
+ }
+ }
+
+ private suspend fun performDefaultSearchEngineMigration(
+ values: Migration.MigrationValues?,
+ engines: List<SearchEngine>,
+ ) {
+ if (values == null) {
+ return
+ }
+
+ val name = values.defaultSearchEngineName ?: return
+
+ val default = engines.find { searchEngine ->
+ searchEngine.name == name
+ }
+
+ if (default == null) {
+ logger.error("Could not find migrated default search engine ($name)")
+ return
+ }
+
+ metadataStorage.setUserSelectedSearchEngine(
+ id = default.id,
+ name = if (default.type == SearchEngine.Type.BUNDLED) {
+ default.name
+ } else {
+ null
+ },
+ )
+ }
+
+ /**
+ * A storage for custom search engines of the user.
+ */
+ interface CustomStorage {
+ /**
+ * Loads the list of search engines from the storage.
+ */
+ suspend fun loadSearchEngineList(): List<SearchEngine>
+
+ /**
+ * Removes the search engine with the specified [identifier] from the storage.
+ */
+ suspend fun removeSearchEngine(identifier: String)
+
+ /**
+ * Saves the given [searchEngine] to the storage. May replace an already existing search
+ * engine with the same ID.
+ */
+ suspend fun saveSearchEngine(searchEngine: SearchEngine): Boolean
+ }
+
+ /**
+ * A storage for loading bundled search engines.
+ */
+ interface BundleStorage {
+ /**
+ * Loads the bundled search engines for the given [locale] and [region].
+ *
+ * If [distribution] is not null then attempt to load the bundled search engine for the
+ * [distribution] in the specified [locale] and [region] if available.
+ */
+ suspend fun load(
+ region: RegionState,
+ locale: Locale = Locale.getDefault(),
+ distribution: String? = null,
+ searchExtraParams: SearchExtraParams? = null,
+ coroutineContext: CoroutineContext = Dispatchers.IO,
+ ): Bundle
+
+ /**
+ * Loads the bundled search engines with the given [ids].
+ */
+ suspend fun load(
+ ids: List<String>,
+ searchExtraParams: SearchExtraParams? = null,
+ coroutineContext: CoroutineContext = Dispatchers.IO,
+ ): List<SearchEngine>
+
+ /**
+ * A loaded bundle containing the list of search engines and the ID of the default for
+ * the region.
+ */
+ data class Bundle(
+ val list: List<SearchEngine>,
+ val defaultSearchEngineId: String,
+ )
+ }
+
+ /**
+ * A storage for saving additional metadata related to search.
+ */
+ interface MetadataStorage {
+ /**
+ * Gets the ID (and optinally name) of the default search engine the user has picked. Returns
+ * `null` if the user has not made a choice.
+ */
+ suspend fun getUserSelectedSearchEngine(): UserChoice?
+
+ /**
+ * Sets the ID (and optionally name) of the default search engine the user has picked.
+ */
+ suspend fun setUserSelectedSearchEngine(id: String, name: String?)
+
+ /**
+ * Sets the list of IDs of hidden search engines.
+ */
+ suspend fun setHiddenSearchEngines(ids: List<String>)
+
+ /**
+ * Gets the list of IDs of hidden search engines.
+ */
+ suspend fun getHiddenSearchEngines(): List<String>
+
+ /**
+ * Gets the list of IDs of additional search engines that the user explicitly added.
+ */
+ suspend fun getAdditionalSearchEngines(): List<String>
+
+ /**
+ * Sets the list of IDs of additional search engines that the user explicitly added.
+ */
+ suspend fun setAdditionalSearchEngines(ids: List<String>)
+
+ /**
+ * Gets the list of IDs of disabled search engine shortcuts.
+ */
+ suspend fun getDisabledSearchEngineIds(): List<String>
+
+ /**
+ * Sets the list of IDs of disabled search engine shortcuts.
+ */
+ suspend fun setDisabledSearchEngineIds(ids: List<String>)
+
+ /**
+ * Data class holding the ID and name of the selected search engine of the user.
+ */
+ data class UserChoice(
+ val searchEngineId: String,
+ val searchEngineName: String?,
+ )
+ }
+
+ /**
+ * Interface for a class that can provide data from a legacy system to be imported into the
+ * storage used by the middleware.
+ */
+ interface Migration {
+ /**
+ * Returns the values to be migrated. It is expected that the application returns the values
+ * only once. Afterwards the data is assumed to be migrated and should not be provided again.
+ */
+ fun getValuesToMigrate(): MigrationValues?
+
+ /**
+ * Holder data class for values to be migrated.
+ *
+ * @param customSearchEngines List of custom search engines that should be imported.
+ * @param defaultSearchEngineName Name of the default search engine that the user had
+ * selected. Or `null` if the user has not made any choice.
+ */
+ data class MigrationValues(
+ val customSearchEngines: List<SearchEngine>,
+ val defaultSearchEngineName: String?,
+ )
+ }
+}
diff --git a/mobile/android/android-components/components/feature/search/src/main/java/mozilla/components/feature/search/region/RegionManager.kt b/mobile/android/android-components/components/feature/search/src/main/java/mozilla/components/feature/search/region/RegionManager.kt
new file mode 100644
index 0000000000..33f75a8a17
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/java/mozilla/components/feature/search/region/RegionManager.kt
@@ -0,0 +1,126 @@
+/* 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.feature.search.region
+
+import android.content.Context
+import android.content.SharedPreferences
+import kotlinx.coroutines.CoroutineDispatcher
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.delay
+import kotlinx.coroutines.withContext
+import mozilla.components.browser.state.search.RegionState
+import mozilla.components.service.location.LocationService
+
+// The amount of time (in seconds) we need to be in a new
+// location before we update the home region.
+// Currently set to 2 weeks.
+// https://searchfox.org/mozilla-central/rev/89d33e1c3b0a57a9377b4815c2f4b58d933b7c32/toolkit/modules/Region.jsm#82-85
+private const val UPDATE_INTERVAL_MS = 14 * 24 * 60 * 60 * 1000
+
+// The maximum number of times we retry fetching the region from
+// the location service until we give up. We will try again on
+// the next app start.
+private const val MAX_RETRIES = 3
+
+// Timeout until we try to fetch the region again after a failure.
+private const val RETRY_TIMEOUT_MS: Long = 10L * 60L * 1000L
+
+private const val PREFERENCE_FILE = "mozac_feature_search_region"
+private const val PREFERENCE_KEY_HOME_REGION = "region.home"
+private const val PREFERENCE_KEY_CURRENT_REGION = "region.current"
+private const val PREFERENCE_KEY_REGION_FIRST_SEEN = "region.first_seen"
+
+/**
+ * Internal RegionManager for keeping track of the "current" and "home" region of a user. Used by
+ * [RegionMiddleware].
+ */
+internal class RegionManager(
+ context: Context,
+ private val locationService: LocationService,
+ private val currentTime: () -> Long = { System.currentTimeMillis() },
+ private val preferences: Lazy<SharedPreferences> = lazy {
+ context.getSharedPreferences(
+ PREFERENCE_FILE,
+ Context.MODE_PRIVATE,
+ )
+ },
+ private val dispatcher: CoroutineDispatcher = Dispatchers.IO,
+) {
+ private var homeRegion: String?
+ get() = preferences.value.getString(PREFERENCE_KEY_HOME_REGION, null)
+ set(value) = preferences.value.edit().putString(PREFERENCE_KEY_HOME_REGION, value).apply()
+
+ private var currentRegion: String?
+ get() = preferences.value.getString(PREFERENCE_KEY_CURRENT_REGION, null)
+ set(value) = preferences.value.edit().putString(PREFERENCE_KEY_CURRENT_REGION, value).apply()
+
+ private var firstSeen: Long?
+ get() = preferences.value.getLong(PREFERENCE_KEY_REGION_FIRST_SEEN, 0)
+ set(value) = if (value == null) {
+ preferences.value.edit().remove(PREFERENCE_KEY_REGION_FIRST_SEEN).apply()
+ } else {
+ preferences.value.edit().putLong(PREFERENCE_KEY_REGION_FIRST_SEEN, value).apply()
+ }
+
+ fun region(): RegionState? {
+ return homeRegion?.let { region ->
+ RegionState(
+ region,
+ currentRegion ?: region,
+ )
+ }
+ }
+
+ suspend fun update(): RegionState? {
+ val region = fetchRegionWithRetry()?.countryCode ?: return null
+
+ if (homeRegion == null) {
+ // If we do not have a value for the home region yet, then we can set it immediately.
+ homeRegion = region
+ return RegionState(home = region, current = region)
+ }
+
+ return when (region) {
+ homeRegion -> {
+ // If we are in the home region (again) then we can clear a previously seen different
+ // "current" region.
+ currentRegion = null
+ firstSeen = null
+ null
+ }
+
+ currentRegion -> {
+ val now = currentTime()
+ if (now > (firstSeen ?: 0) + UPDATE_INTERVAL_MS) {
+ // We have been in the "current" region longer than the specified "interval".
+ // So we will set the "current" region as our new home region.
+ homeRegion = region
+ RegionState(home = region, current = region)
+ } else {
+ null
+ }
+ }
+
+ else -> {
+ // This region is neither the home region nor the current region. We set it as the
+ // new "current" region and remember when we saw it the first time.
+ firstSeen = currentTime()
+ currentRegion = region
+ null
+ }
+ }
+ }
+
+ private suspend fun fetchRegionWithRetry(): LocationService.Region? = withContext(dispatcher) {
+ repeat(MAX_RETRIES) {
+ val region = locationService.fetchRegion(readFromCache = true)
+ if (region != null) {
+ return@withContext region
+ }
+ delay(RETRY_TIMEOUT_MS)
+ }
+ return@withContext null
+ }
+}
diff --git a/mobile/android/android-components/components/feature/search/src/main/java/mozilla/components/feature/search/region/RegionMiddleware.kt b/mobile/android/android-components/components/feature/search/src/main/java/mozilla/components/feature/search/region/RegionMiddleware.kt
new file mode 100644
index 0000000000..7bf4893c0b
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/java/mozilla/components/feature/search/region/RegionMiddleware.kt
@@ -0,0 +1,72 @@
+/* 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.feature.search.region
+
+import android.content.Context
+import androidx.annotation.VisibleForTesting
+import kotlinx.coroutines.CoroutineDispatcher
+import kotlinx.coroutines.DelicateCoroutinesApi
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.GlobalScope
+import kotlinx.coroutines.Job
+import kotlinx.coroutines.launch
+import mozilla.components.browser.state.action.BrowserAction
+import mozilla.components.browser.state.action.InitAction
+import mozilla.components.browser.state.action.SearchAction
+import mozilla.components.browser.state.search.RegionState
+import mozilla.components.browser.state.state.BrowserState
+import mozilla.components.lib.state.Middleware
+import mozilla.components.lib.state.MiddlewareContext
+import mozilla.components.lib.state.Store
+import mozilla.components.service.location.LocationService
+
+/**
+ * [Middleware] implementation for updating the [RegionState] using the provided [LocationService].
+ */
+class RegionMiddleware(
+ context: Context,
+ locationService: LocationService,
+ private val ioDispatcher: CoroutineDispatcher = Dispatchers.IO,
+) : Middleware<BrowserState, BrowserAction> {
+ @VisibleForTesting
+ internal var regionManager = RegionManager(context, locationService, dispatcher = ioDispatcher)
+
+ @VisibleForTesting
+ @Volatile
+ internal var updateJob: Job? = null
+
+ override fun invoke(
+ context: MiddlewareContext<BrowserState, BrowserAction>,
+ next: (BrowserAction) -> Unit,
+ action: BrowserAction,
+ ) {
+ if (action is InitAction || action is SearchAction.RefreshSearchEnginesAction) {
+ updateJob = determineRegion(context.store)
+ }
+
+ next(action)
+ }
+
+ @OptIn(DelicateCoroutinesApi::class)
+ private fun determineRegion(
+ store: Store<BrowserState, BrowserAction>,
+ ) = GlobalScope.launch(ioDispatcher) {
+ // Get the region state from the RegionManager. If there's none then dispatch the default
+ // region to be used.
+ val region = regionManager.region()
+ if (region != null) {
+ store.dispatch(SearchAction.SetRegionAction(region))
+ } else {
+ store.dispatch(SearchAction.SetRegionAction(RegionState.Default))
+ }
+
+ // Ask the RegionManager to perform an update. If the "home" region changed then it will
+ // return a new RegionState.
+ val update = regionManager.update()
+ if (update != null) {
+ store.dispatch(SearchAction.SetRegionAction(update))
+ }
+ }
+}
diff --git a/mobile/android/android-components/components/feature/search/src/main/java/mozilla/components/feature/search/storage/BundledSearchEnginesStorage.kt b/mobile/android/android-components/components/feature/search/src/main/java/mozilla/components/feature/search/storage/BundledSearchEnginesStorage.kt
new file mode 100644
index 0000000000..eaa196739d
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/java/mozilla/components/feature/search/storage/BundledSearchEnginesStorage.kt
@@ -0,0 +1,278 @@
+/* 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.feature.search.storage
+
+import android.content.Context
+import android.content.res.AssetManager
+import kotlinx.coroutines.Deferred
+import kotlinx.coroutines.DelicateCoroutinesApi
+import kotlinx.coroutines.GlobalScope
+import kotlinx.coroutines.async
+import kotlinx.coroutines.withContext
+import mozilla.components.browser.state.search.RegionState
+import mozilla.components.browser.state.search.SearchEngine
+import mozilla.components.feature.search.middleware.SearchExtraParams
+import mozilla.components.feature.search.middleware.SearchMiddleware
+import mozilla.components.support.base.log.logger.Logger
+import mozilla.components.support.ktx.android.content.res.readJSONObject
+import mozilla.components.support.ktx.android.org.json.toList
+import mozilla.components.support.ktx.android.org.json.tryGetString
+import org.json.JSONArray
+import org.json.JSONObject
+import java.util.Locale
+import kotlin.coroutines.CoroutineContext
+
+private val logger = Logger("BundledSearchEnginesStorage")
+
+/**
+ * A storage implementation for reading bundled [SearchEngine]s from the app's assets.
+ */
+internal class BundledSearchEnginesStorage(
+ private val context: Context,
+) : SearchMiddleware.BundleStorage {
+ /**
+ * Load the [SearchMiddleware.BundleStorage.Bundle] for the given [region] and [locale].
+ */
+ override suspend fun load(
+ region: RegionState,
+ locale: Locale,
+ distribution: String?,
+ searchExtraParams: SearchExtraParams?,
+ coroutineContext: CoroutineContext,
+ ): SearchMiddleware.BundleStorage.Bundle = withContext(coroutineContext) {
+ val localizedConfiguration = loadAndFilterConfiguration(context, region, locale, distribution)
+ val searchEngineIdentifiers = localizedConfiguration.visibleSearchEngines
+
+ val searchEngines = loadSearchEnginesFromList(
+ context = context,
+ searchEngineIdentifiers = searchEngineIdentifiers.distinct(),
+ type = SearchEngine.Type.BUNDLED,
+ searchExtraParams = searchExtraParams,
+ coroutineContext = coroutineContext,
+ )
+
+ // Reorder the list of search engines according to the configuration.
+ // Note: we're using the name of the search engine, not the id, so we can only do this
+ // after we've loaded the search engine from the XML
+ val searchOrder = localizedConfiguration.searchOrder
+ val orderedList = searchOrder
+ .map { name ->
+ searchEngines.filter { it.name == name }
+ }
+ .flatten()
+
+ val unorderedRest = searchEngines
+ .filter {
+ !searchOrder.contains(it.name)
+ }
+
+ val defaultEngine = localizedConfiguration.searchDefault?.let { name ->
+ searchEngines.find { it.name == name }
+ } ?: throw IllegalStateException("No default engine for configuration: locale=$locale, region=$region")
+
+ SearchMiddleware.BundleStorage.Bundle(
+ list = orderedList + unorderedRest,
+ defaultSearchEngineId = defaultEngine.id,
+ )
+ }
+
+ override suspend fun load(
+ ids: List<String>,
+ searchExtraParams: SearchExtraParams?,
+ coroutineContext: CoroutineContext,
+ ): List<SearchEngine> = withContext(coroutineContext) {
+ if (ids.isEmpty()) {
+ emptyList()
+ } else {
+ loadSearchEnginesFromList(
+ context = context,
+ searchEngineIdentifiers = ids.distinct(),
+ type = SearchEngine.Type.BUNDLED_ADDITIONAL,
+ searchExtraParams = searchExtraParams,
+ coroutineContext = coroutineContext,
+ )
+ }
+ }
+}
+
+private data class SearchEngineListConfiguration(
+ val visibleSearchEngines: List<String>,
+ val searchOrder: List<String>,
+ val searchDefault: String?,
+)
+
+private fun loadAndFilterConfiguration(
+ context: Context,
+ region: RegionState,
+ locale: Locale,
+ distribution: String?,
+): SearchEngineListConfiguration {
+ val config = context.assets.readJSONObject("search/list.json")
+
+ val configBlocks = pickConfigurationBlocks(locale, config)
+ val jsonSearchEngineIdentifiers =
+ getSearchEngineIdentifiersFromBlock(region, locale, distribution, configBlocks)
+
+ val searchOrder = getSearchOrderFromBlock(region, configBlocks)
+ val searchDefault = getSearchDefaultFromBlock(region, configBlocks)
+
+ return SearchEngineListConfiguration(
+ applyOverridesIfNeeded(region, config, jsonSearchEngineIdentifiers),
+ searchOrder.toList(),
+ searchDefault,
+ )
+}
+
+private fun pickConfigurationBlocks(
+ locale: Locale,
+ config: JSONObject,
+): Array<JSONObject> {
+ val localesConfig = config.getJSONObject("locales")
+
+ val localizedConfig = when {
+ // First try (Locale): locales/xx_XX/
+ localesConfig.has(locale.languageTag) ->
+ localesConfig.getJSONObject(locale.languageTag)
+
+ // Second try (Language): locales/xx/
+ localesConfig.has(locale.language) ->
+ localesConfig.getJSONObject(locale.language)
+
+ // Give up, and fallback to defaults
+ else -> null
+ }
+
+ return localizedConfig?.let {
+ arrayOf(it, config)
+ } ?: arrayOf(config)
+}
+
+private fun getSearchEngineIdentifiersFromBlock(
+ region: RegionState,
+ locale: Locale,
+ distribution: String?,
+ configBlocks: Array<JSONObject>,
+): JSONArray {
+ // Now test if there's an override for the distribution or region (if it's set)
+ return distribution?.let { getArrayFromBlock(region, distribution, configBlocks) }
+ ?: getArrayFromBlock(region, "visibleDefaultEngines", configBlocks)
+ ?: throw IllegalStateException("No visibleDefaultEngines using region $region and locale $locale")
+}
+
+private fun getSearchDefaultFromBlock(
+ region: RegionState,
+ configBlocks: Array<JSONObject>,
+): String? = getValueFromBlock(region, configBlocks) {
+ it.tryGetString("searchDefault")
+}
+
+private fun getSearchOrderFromBlock(
+ region: RegionState,
+ configBlocks: Array<JSONObject>,
+): JSONArray? = getArrayFromBlock(region, "searchOrder", configBlocks)
+
+private fun getArrayFromBlock(
+ region: RegionState,
+ key: String,
+ blocks: Array<JSONObject>,
+): JSONArray? = getValueFromBlock(region, blocks) {
+ it.optJSONArray(key)
+}
+
+/**
+ * This looks for a JSONObject in the config blocks it is passed that is able to be transformed
+ * into a value. It tries the permutations of locale and region from most specific to least
+ * specific.
+ *
+ * This has to be done on a value basis, not a configBlock basis, as the configuration for a
+ * given locale/region is not grouped into one object, but spread across the json file,
+ * according to these rules.
+ */
+private fun <T : Any> getValueFromBlock(
+ region: RegionState,
+ blocks: Array<JSONObject>,
+ transform: (JSONObject) -> T?,
+): T? {
+ val regions = arrayOf(region.home, "default")
+
+ return blocks
+ .flatMap { block ->
+ regions.mapNotNull { region -> block.optJSONObject(region) }
+ }
+ .mapNotNull(transform)
+ .firstOrNull()
+}
+
+private fun applyOverridesIfNeeded(
+ region: RegionState,
+ config: JSONObject,
+ jsonSearchEngineIdentifiers: JSONArray,
+): List<String> {
+ val overrides = config.getJSONObject("regionOverrides")
+ val searchEngineIdentifiers = mutableListOf<String>()
+ val regionOverrides = if (overrides.has(region.home)) {
+ overrides.getJSONObject(region.home)
+ } else {
+ null
+ }
+
+ for (i in 0 until jsonSearchEngineIdentifiers.length()) {
+ var identifier = jsonSearchEngineIdentifiers.getString(i)
+ if (regionOverrides != null && regionOverrides.has(identifier)) {
+ identifier = regionOverrides.getString(identifier)
+ }
+ searchEngineIdentifiers.add(identifier)
+ }
+
+ return searchEngineIdentifiers
+}
+
+@OptIn(DelicateCoroutinesApi::class)
+private suspend fun loadSearchEnginesFromList(
+ context: Context,
+ searchEngineIdentifiers: List<String>,
+ type: SearchEngine.Type,
+ searchExtraParams: SearchExtraParams?,
+ coroutineContext: CoroutineContext,
+): List<SearchEngine> {
+ val assets = context.assets
+ val reader = SearchEngineReader(type, searchExtraParams)
+
+ val deferredSearchEngines = mutableListOf<Deferred<SearchEngine?>>()
+
+ searchEngineIdentifiers.forEach { identifier ->
+ deferredSearchEngines.add(
+ GlobalScope.async(coroutineContext) {
+ loadSearchEngine(assets, reader, identifier)
+ },
+ )
+ }
+
+ return deferredSearchEngines.mapNotNull { it.await() }
+}
+
+@Suppress("TooGenericExceptionCaught")
+private fun loadSearchEngine(
+ assets: AssetManager,
+ reader: SearchEngineReader,
+ identifier: String,
+): SearchEngine? = try {
+ assets.open("searchplugins/$identifier.xml").use { stream ->
+ reader.loadStream(identifier, stream)
+ }
+} catch (e: Exception) {
+ // Handling all exceptions here (instead of just IOExceptions) as we're
+ // seeing crashes we can't explain currently. Letting the app launch
+ // will eventually help us understand the root cause:
+ // https://github.com/mozilla-mobile/android-components/issues/12304
+
+ // We should also consider logging these errors to Sentry:
+ // https://github.com/mozilla-mobile/android-components/issues/12313
+ logger.error("Could not load additional search engine with ID $identifier", e)
+ null
+}
+
+private val Locale.languageTag: String
+ get() = "$language-$country"
diff --git a/mobile/android/android-components/components/feature/search/src/main/java/mozilla/components/feature/search/storage/CustomSearchEnginesStorage.kt b/mobile/android/android-components/components/feature/search/src/main/java/mozilla/components/feature/search/storage/CustomSearchEnginesStorage.kt
new file mode 100644
index 0000000000..f0961d6b63
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/java/mozilla/components/feature/search/storage/CustomSearchEnginesStorage.kt
@@ -0,0 +1,66 @@
+/* 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.feature.search.storage
+
+import android.content.Context
+import android.util.AtomicFile
+import android.util.Base64
+import androidx.annotation.VisibleForTesting
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.withContext
+import mozilla.components.browser.state.search.SearchEngine
+import mozilla.components.feature.search.middleware.SearchMiddleware
+import java.io.File
+import kotlin.coroutines.CoroutineContext
+
+internal const val SEARCH_FILE_EXTENSION = ".xml"
+internal const val SEARCH_DIR_NAME = "search-engines"
+
+/**
+ * A storage implementation for organizing [SearchEngine]s. Its primary use case is for persisting
+ * custom search engines added by users.
+ */
+internal class CustomSearchEngineStorage(
+ private val context: Context,
+ private val coroutineContext: CoroutineContext = Dispatchers.IO,
+) : SearchMiddleware.CustomStorage {
+ private val reader = SearchEngineReader(SearchEngine.Type.CUSTOM)
+ private val writer = SearchEngineWriter()
+
+ override suspend fun loadSearchEngineList(): List<SearchEngine> = withContext(coroutineContext) {
+ val searchEngineList = mutableListOf<SearchEngine>()
+ getFileDirectory().listFiles()?.forEach {
+ val filename = it.name.removeSuffix(SEARCH_FILE_EXTENSION)
+ val identifier = String(Base64.decode(filename, Base64.NO_WRAP or Base64.URL_SAFE))
+ searchEngineList.add(loadSearchEngine(identifier))
+ }
+ searchEngineList.toList()
+ }
+
+ suspend fun loadSearchEngine(identifier: String): SearchEngine = withContext(coroutineContext) {
+ reader.loadFile(identifier, getSearchFile(identifier))
+ }
+
+ override suspend fun saveSearchEngine(searchEngine: SearchEngine): Boolean = withContext(coroutineContext) {
+ writer.saveSearchEngineXML(searchEngine, getSearchFile(searchEngine.id))
+ }
+
+ override suspend fun removeSearchEngine(identifier: String) = withContext(coroutineContext) {
+ getSearchFile(identifier).delete()
+ }
+
+ @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
+ internal fun getSearchFile(identifier: String): AtomicFile {
+ val encodedId = Base64.encodeToString(identifier.toByteArray(), Base64.NO_WRAP or Base64.URL_SAFE)
+ return AtomicFile(File(getFileDirectory(), encodedId + SEARCH_FILE_EXTENSION))
+ }
+
+ private fun getFileDirectory(): File =
+ File(context.filesDir, SEARCH_DIR_NAME).also {
+ if (!it.exists()) {
+ it.mkdirs()
+ }
+ }
+}
diff --git a/mobile/android/android-components/components/feature/search/src/main/java/mozilla/components/feature/search/storage/SearchEngineReader.kt b/mobile/android/android-components/components/feature/search/src/main/java/mozilla/components/feature/search/storage/SearchEngineReader.kt
new file mode 100644
index 0000000000..51d2ccec52
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/java/mozilla/components/feature/search/storage/SearchEngineReader.kt
@@ -0,0 +1,243 @@
+/* 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.feature.search.storage
+
+import android.graphics.Bitmap
+import android.graphics.BitmapFactory
+import android.net.Uri
+import android.util.AtomicFile
+import android.util.Base64
+import mozilla.components.browser.state.search.SearchEngine
+import mozilla.components.feature.search.middleware.SearchExtraParams
+import org.xmlpull.v1.XmlPullParser
+import org.xmlpull.v1.XmlPullParserException
+import org.xmlpull.v1.XmlPullParserFactory
+import java.io.IOException
+import java.io.InputStream
+import java.io.InputStreamReader
+import java.nio.charset.StandardCharsets
+
+internal const val URL_TYPE_SUGGEST_JSON = "application/x-suggestions+json"
+internal const val URL_TYPE_SEARCH_HTML = "text/html"
+internal const val URL_REL_MOBILE = "mobile"
+internal const val IMAGE_URI_PREFIX = "data:image/png;base64,"
+internal const val GOOGLE_ID = "google"
+
+// List of general search engine ids, taken from
+// https://searchfox.org/mozilla-central/rev/ef0aa879e94534ffd067a3748d034540a9fc10b0/toolkit/components/search/SearchUtils.sys.mjs#200
+internal val GENERAL_SEARCH_ENGINE_IDS = setOf(
+ GOOGLE_ID,
+ "ddg",
+ "bing",
+ "baidu",
+ "ecosia",
+ "qwant",
+ "yahoo-jp",
+ "seznam-cz",
+ "coccoc",
+ "baidu",
+)
+
+/**
+ * A simple XML reader for search engine plugins.
+ *
+ * @param type the [SearchEngine.Type] that the read [SearchEngine]s will get assigned.
+ * @param searchExtraParams Optional search extra params.
+ */
+internal class SearchEngineReader(
+ private val type: SearchEngine.Type,
+ private val searchExtraParams: SearchExtraParams? = null,
+) {
+ private class SearchEngineBuilder(
+ private val type: SearchEngine.Type,
+ private val identifier: String,
+ ) {
+ var resultsUrls: MutableList<String> = mutableListOf()
+ var suggestUrl: String? = null
+ var name: String? = null
+ var icon: Bitmap? = null
+ var inputEncoding: String? = null
+
+ fun toSearchEngine() = SearchEngine(
+ id = identifier,
+ name = name!!,
+ icon = icon!!,
+ type = type,
+ resultUrls = resultsUrls,
+ suggestUrl = suggestUrl,
+ inputEncoding = inputEncoding,
+ isGeneral = isGeneralSearchEngine(identifier, type),
+ )
+
+ /**
+ * Returns true if the provided [type] is a custom search engine or the [identifier] is
+ * included in [GENERAL_SEARCH_ENGINE_IDS].
+ */
+ private fun isGeneralSearchEngine(identifier: String, type: SearchEngine.Type): Boolean =
+ type == SearchEngine.Type.CUSTOM ||
+ identifier.startsWith(GOOGLE_ID) ||
+ GENERAL_SEARCH_ENGINE_IDS.contains(identifier)
+ }
+
+ /**
+ * Loads [SearchEngine] from a provided [file]
+ */
+ fun loadFile(identifier: String, file: AtomicFile): SearchEngine {
+ return loadStream(identifier, file.openRead())
+ }
+
+ /**
+ * Loads a <code>SearchEngine</code> from the given <code>stream</code> and assigns it the given
+ * <code>identifier</code>.
+ */
+ @Throws(IOException::class, XmlPullParserException::class)
+ fun loadStream(identifier: String, stream: InputStream): SearchEngine {
+ val builder = SearchEngineBuilder(type, identifier)
+
+ val parser = XmlPullParserFactory.newInstance().newPullParser()
+ parser.setInput(InputStreamReader(stream, StandardCharsets.UTF_8))
+ parser.next()
+
+ readSearchPlugin(parser, builder)
+
+ return builder.toSearchEngine()
+ }
+
+ @Throws(XmlPullParserException::class, IOException::class)
+ @Suppress("ComplexMethod")
+ private fun readSearchPlugin(parser: XmlPullParser, builder: SearchEngineBuilder) {
+ if (XmlPullParser.START_TAG != parser.eventType) {
+ throw XmlPullParserException("Expected start tag: " + parser.positionDescription)
+ }
+
+ val name = parser.name
+ if ("SearchPlugin" != name && "OpenSearchDescription" != name) {
+ throw XmlPullParserException(
+ "Expected <SearchPlugin> or <OpenSearchDescription> as root tag: ${parser.positionDescription}",
+ )
+ }
+
+ while (parser.next() != XmlPullParser.END_TAG) {
+ if (parser.eventType != XmlPullParser.START_TAG) {
+ continue
+ }
+
+ when (parser.name) {
+ "ShortName" -> readShortName(parser, builder)
+ "Url" -> readUrl(parser, builder)
+ "Image" -> readImage(parser, builder)
+ "InputEncoding" -> readInputEncoding(parser, builder)
+ else -> skip(parser)
+ }
+ }
+ }
+
+ @Throws(XmlPullParserException::class, IOException::class)
+ private fun readUrl(parser: XmlPullParser, builder: SearchEngineBuilder) {
+ parser.require(XmlPullParser.START_TAG, null, "Url")
+
+ val type = parser.getAttributeValue(null, "type")
+ val template = parser.getAttributeValue(null, "template")
+ val rel = parser.getAttributeValue(null, "rel")
+
+ val url = buildString {
+ append(readUri(parser, template))
+ searchExtraParams?.let {
+ with(it) {
+ if (builder.name == searchEngineName) {
+ featureEnablerParam?.let { append("&$featureEnablerName=$it") }
+ append("&$channelIdName=$channelIdParam")
+ }
+ }
+ }
+ }
+
+ if (type == URL_TYPE_SEARCH_HTML) {
+ // Prefer mobile URIs.
+ if (rel != null && rel == URL_REL_MOBILE) {
+ builder.resultsUrls.add(0, url)
+ } else {
+ builder.resultsUrls.add(url)
+ }
+ } else if (type == URL_TYPE_SUGGEST_JSON) {
+ builder.suggestUrl = url
+ }
+ }
+
+ @Throws(XmlPullParserException::class, IOException::class)
+ private fun readUri(parser: XmlPullParser, template: String): Uri {
+ var uri = Uri.parse(template)
+
+ while (parser.next() != XmlPullParser.END_TAG) {
+ if (parser.eventType != XmlPullParser.START_TAG) {
+ continue
+ }
+
+ if (parser.name == "Param") {
+ val name = parser.getAttributeValue(null, "name")
+ val value = parser.getAttributeValue(null, "value")
+ uri = uri.buildUpon().appendQueryParameter(name, value).build()
+ parser.nextTag()
+ } else {
+ skip(parser)
+ }
+ }
+
+ return uri
+ }
+
+ @Throws(XmlPullParserException::class, IOException::class)
+ private fun skip(parser: XmlPullParser) {
+ if (parser.eventType != XmlPullParser.START_TAG) {
+ throw IllegalStateException()
+ }
+ var depth = 1
+ while (depth != 0) {
+ when (parser.next()) {
+ XmlPullParser.END_TAG -> depth--
+ XmlPullParser.START_TAG -> depth++
+ // else: Do nothing - we're skipping content
+ }
+ }
+ }
+
+ @Throws(IOException::class, XmlPullParserException::class)
+ private fun readShortName(parser: XmlPullParser, builder: SearchEngineBuilder) {
+ parser.require(XmlPullParser.START_TAG, null, "ShortName")
+ if (parser.next() == XmlPullParser.TEXT) {
+ builder.name = parser.text
+ parser.nextTag()
+ }
+ }
+
+ @Throws(IOException::class, XmlPullParserException::class)
+ private fun readImage(parser: XmlPullParser, builder: SearchEngineBuilder) {
+ parser.require(XmlPullParser.START_TAG, null, "Image")
+
+ if (parser.next() != XmlPullParser.TEXT) {
+ return
+ }
+
+ val uri = parser.text
+ if (!uri.startsWith(IMAGE_URI_PREFIX)) {
+ return
+ }
+
+ val raw = Base64.decode(uri.substring(IMAGE_URI_PREFIX.length), Base64.DEFAULT)
+
+ builder.icon = BitmapFactory.decodeByteArray(raw, 0, raw.size)
+
+ parser.nextTag()
+ }
+
+ @Throws(IOException::class, XmlPullParserException::class)
+ private fun readInputEncoding(parser: XmlPullParser, builder: SearchEngineBuilder) {
+ parser.require(XmlPullParser.START_TAG, null, "InputEncoding")
+ if (parser.next() == XmlPullParser.TEXT) {
+ builder.inputEncoding = parser.text
+ parser.nextTag()
+ }
+ }
+}
diff --git a/mobile/android/android-components/components/feature/search/src/main/java/mozilla/components/feature/search/storage/SearchEngineWriter.kt b/mobile/android/android-components/components/feature/search/src/main/java/mozilla/components/feature/search/storage/SearchEngineWriter.kt
new file mode 100644
index 0000000000..15d7f17212
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/java/mozilla/components/feature/search/storage/SearchEngineWriter.kt
@@ -0,0 +1,115 @@
+/* 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.feature.search.storage
+
+import android.graphics.Bitmap
+import android.util.AtomicFile
+import android.util.Base64
+import androidx.annotation.VisibleForTesting
+import mozilla.components.browser.state.search.SearchEngine
+import org.w3c.dom.DOMException
+import org.w3c.dom.Document
+import java.io.ByteArrayOutputStream
+import java.io.File
+import javax.xml.parsers.DocumentBuilderFactory
+import javax.xml.parsers.ParserConfigurationException
+import javax.xml.transform.TransformerConfigurationException
+import javax.xml.transform.TransformerException
+import javax.xml.transform.TransformerFactory
+import javax.xml.transform.dom.DOMSource
+import javax.xml.transform.stream.StreamResult
+
+/**
+ * A simple XML writer for search engine plugins.
+ */
+internal class SearchEngineWriter {
+ /**
+ * Builds and save the XML document of [SearchEngine] to the provided [File].
+ *
+ * @param searchEngine the search engine to build XML with.
+ * @param file the file instance to save the search engine XML.
+ * @param document the document instance to build search engine XML with.
+ * @return true if the XML is built and saved successfully, false otherwise.
+ */
+ fun saveSearchEngineXML(
+ searchEngine: SearchEngine,
+ file: AtomicFile,
+ document: Document = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument(),
+ ): Boolean {
+ return try {
+ buildSearchEngineXML(searchEngine, document)
+ saveXMLDocumentToFile(document, file)
+ true
+ } catch (e: ParserConfigurationException) {
+ false
+ } catch (e: DOMException) {
+ false
+ } catch (e: TransformerConfigurationException) {
+ false
+ } catch (e: TransformerException) {
+ false
+ }
+ }
+
+ @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
+ @Throws(ParserConfigurationException::class, DOMException::class)
+ internal fun buildSearchEngineXML(
+ searchEngine: SearchEngine,
+ xmlDocument: Document,
+ ) {
+ val rootElement = xmlDocument.createElement("OpenSearchDescription")
+ rootElement.setAttribute("xmlns", "http://a9.com/-/spec/opensearch/1.1/")
+ rootElement.setAttribute("xmlns:moz", "http://www.mozilla.org/2006/browser/search/")
+ xmlDocument.appendChild(rootElement)
+
+ val shortNameElement = xmlDocument.createElement("ShortName")
+ shortNameElement.textContent = searchEngine.name
+ rootElement.appendChild(shortNameElement)
+
+ val descriptionElement = xmlDocument.createElement("Description")
+ descriptionElement.textContent = searchEngine.name
+ rootElement.appendChild(descriptionElement)
+
+ val imageElement = xmlDocument.createElement("Image")
+ imageElement.setAttribute("width", "16")
+ imageElement.setAttribute("height", "16")
+ imageElement.textContent = searchEngine.icon.toBase64()
+ rootElement.appendChild(imageElement)
+
+ searchEngine.inputEncoding?.let { inputEncoding ->
+ val inputEncodingElement = xmlDocument.createElement("InputEncoding")
+ inputEncodingElement.textContent = inputEncoding
+ rootElement.appendChild(inputEncodingElement)
+ }
+
+ searchEngine.resultUrls.forEach { url ->
+ val urlElement = xmlDocument.createElement("Url")
+ urlElement.setAttribute("type", URL_TYPE_SEARCH_HTML)
+ urlElement.setAttribute("template", url)
+ rootElement.appendChild(urlElement)
+ }
+
+ searchEngine.suggestUrl?.let { url ->
+ val urlElement = xmlDocument.createElement("Url")
+ urlElement.setAttribute("type", URL_TYPE_SUGGEST_JSON)
+ val templateSearchString = url.replace("%s", "{searchTerms}")
+ urlElement.setAttribute("template", templateSearchString)
+ rootElement.appendChild(urlElement)
+ }
+ }
+
+ @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
+ @Throws(TransformerConfigurationException::class, TransformerException::class)
+ internal fun saveXMLDocumentToFile(doc: Document, file: AtomicFile) =
+ TransformerFactory.newInstance().newTransformer().transform(DOMSource(doc), StreamResult(file.baseFile))
+}
+
+private const val BITMAP_COMPRESS_QUALITY = 100
+private fun Bitmap.toBase64(): String {
+ val stream = ByteArrayOutputStream()
+ compress(Bitmap.CompressFormat.PNG, BITMAP_COMPRESS_QUALITY, stream)
+ val encodedImage = Base64.encodeToString(stream.toByteArray(), Base64.DEFAULT)
+ return "data:image/png;base64,$encodedImage"
+}
diff --git a/mobile/android/android-components/components/feature/search/src/main/java/mozilla/components/feature/search/storage/SearchMetadataStorage.kt b/mobile/android/android-components/components/feature/search/src/main/java/mozilla/components/feature/search/storage/SearchMetadataStorage.kt
new file mode 100644
index 0000000000..b835f5ab37
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/java/mozilla/components/feature/search/storage/SearchMetadataStorage.kt
@@ -0,0 +1,103 @@
+/* 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.feature.search.storage
+
+import android.content.Context
+import android.content.SharedPreferences
+import mozilla.components.feature.search.middleware.SearchMiddleware
+
+private const val PREFERENCE_FILE = "mozac_feature_search_metadata"
+
+private const val PREFERENCE_KEY_USER_SELECTED_SEARCH_ENGINE_ID = "user_selected_search_engine_id"
+private const val PREFERENCE_KEY_USER_SELECTED_SEARCH_ENGINE_NAME = "user_selected_search_engine_name"
+private const val PREFERENCE_KEY_HIDDEN_SEARCH_ENGINES = "hidden_search_engines"
+private const val PREFERENCE_KEY_ADDITIONAL_SEARCH_ENGINES = "additional_search_engines"
+private const val PREFERENCE_KEY_DISABLED_SEARCH_ENGINE_ID = "preference_key_disabled_search_engine_id"
+
+/**
+ * Storage for saving additional search related metadata.
+ */
+internal class SearchMetadataStorage(
+ context: Context,
+ private val disabledByDefaultSearchEngineIds: Set<String> = emptySet(),
+ private val preferences: Lazy<SharedPreferences> = lazy {
+ context.getSharedPreferences(
+ PREFERENCE_FILE,
+ Context.MODE_PRIVATE,
+ )
+ },
+) : SearchMiddleware.MetadataStorage {
+ /**
+ * Gets the ID (and optinally name) of the default search engine the user has picked. Returns
+ * `null` if the user has not made a choice.
+ */
+ override suspend fun getUserSelectedSearchEngine(): SearchMiddleware.MetadataStorage.UserChoice? {
+ val id = preferences.value.getString(PREFERENCE_KEY_USER_SELECTED_SEARCH_ENGINE_ID, null)
+ ?: return null
+
+ return SearchMiddleware.MetadataStorage.UserChoice(
+ id,
+ preferences.value.getString(PREFERENCE_KEY_USER_SELECTED_SEARCH_ENGINE_NAME, null),
+ )
+ }
+
+ /**
+ * Sets the ID (and optionally name) of the default search engine the user has picked.
+ */
+ override suspend fun setUserSelectedSearchEngine(id: String, name: String?) {
+ preferences.value.edit()
+ .putString(PREFERENCE_KEY_USER_SELECTED_SEARCH_ENGINE_ID, id)
+ .putString(PREFERENCE_KEY_USER_SELECTED_SEARCH_ENGINE_NAME, name)
+ .apply()
+ }
+
+ /**
+ * Sets the list of IDs of hidden search engines.
+ */
+ override suspend fun setHiddenSearchEngines(ids: List<String>) {
+ preferences.value.edit()
+ .putStringSet(PREFERENCE_KEY_HIDDEN_SEARCH_ENGINES, ids.toSet())
+ .apply()
+ }
+
+ /**
+ * Gets the list of IDs of hidden search engines.
+ */
+ override suspend fun getHiddenSearchEngines(): List<String> {
+ return preferences.value
+ .getStringSet(PREFERENCE_KEY_HIDDEN_SEARCH_ENGINES, emptySet())
+ ?.toList() ?: emptyList()
+ }
+
+ /**
+ * Gets the list of IDs of additional search engines that the user explicitly added.
+ */
+ override suspend fun getAdditionalSearchEngines(): List<String> {
+ return preferences.value
+ .getStringSet(PREFERENCE_KEY_ADDITIONAL_SEARCH_ENGINES, emptySet())
+ ?.toList() ?: emptyList()
+ }
+
+ override suspend fun getDisabledSearchEngineIds(): List<String> {
+ return preferences.value
+ .getStringSet(PREFERENCE_KEY_DISABLED_SEARCH_ENGINE_ID, disabledByDefaultSearchEngineIds)
+ ?.toList() ?: emptyList()
+ }
+
+ override suspend fun setDisabledSearchEngineIds(ids: List<String>) {
+ preferences.value.edit()
+ .putStringSet(PREFERENCE_KEY_DISABLED_SEARCH_ENGINE_ID, ids.toSet())
+ .apply()
+ }
+
+ /**
+ * Sets the list of IDs of additional search engines that the user explicitly added.
+ */
+ override suspend fun setAdditionalSearchEngines(ids: List<String>) {
+ preferences.value.edit()
+ .putStringSet(PREFERENCE_KEY_ADDITIONAL_SEARCH_ENGINES, ids.toSet())
+ .apply()
+ }
+}
diff --git a/mobile/android/android-components/components/feature/search/src/main/java/mozilla/components/feature/search/suggestions/Parser.kt b/mobile/android/android-components/components/feature/search/src/main/java/mozilla/components/feature/search/suggestions/Parser.kt
new file mode 100644
index 0000000000..c52fdf1bdb
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/java/mozilla/components/feature/search/suggestions/Parser.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.feature.search.suggestions
+
+import mozilla.components.browser.state.search.SearchEngine
+import mozilla.components.support.ktx.android.org.json.asSequence
+import org.json.JSONArray
+import org.json.JSONObject
+
+/**
+ * The Parser is a function that takes a JSON Response and maps
+ * it to a Suggestion list.
+ */
+typealias JSONResponse = String
+typealias ResponseParser = (JSONResponse) -> List<String>
+
+/**
+ * Builds a Parser that pulls suggestions out of a given index
+ */
+private fun buildJSONArrayParser(resultsIndex: Int): ResponseParser {
+ return { input ->
+ JSONArray(input)
+ .getJSONArray(resultsIndex)
+ .asSequence()
+ .map { it as? String }
+ .filterNotNull()
+ .toList()
+ }
+}
+
+/**
+ * Builds a Parser that pulls suggestions out of a JSON object with the given key
+ */
+private fun buildJSONObjectParser(resultsKey: String): ResponseParser {
+ return { input ->
+ JSONObject(input)
+ .getJSONArray(resultsKey)
+ .asSequence()
+ .map { it as? String }
+ .filterNotNull()
+ .toList()
+ }
+}
+
+/**
+ * Builds a custom parser for Qwant
+ */
+private fun buildQwantParser(): ResponseParser {
+ return { input ->
+ JSONObject(input)
+ .getJSONObject("data")
+ .getJSONArray("items")
+ .asSequence()
+ .map { it as? JSONObject }
+ .map { it?.getString("value") }
+ .filterNotNull()
+ .toList()
+ }
+}
+
+/**
+ * The available Parsers
+ */
+internal val defaultResponseParser = buildJSONArrayParser(1)
+internal val azerdictResponseParser = buildJSONObjectParser("suggestions")
+internal val daumResponseParser = buildJSONObjectParser("items")
+internal val qwantResponseParser = buildQwantParser()
+
+/**
+ * Selects a Parser based on a SearchEngine
+ */
+internal fun selectResponseParser(searchEngine: SearchEngine): ResponseParser = when (searchEngine.name) {
+ "Azerdict" -> azerdictResponseParser
+ "다음지도" -> daumResponseParser
+ "Qwant" -> qwantResponseParser
+ else -> defaultResponseParser
+}
diff --git a/mobile/android/android-components/components/feature/search/src/main/java/mozilla/components/feature/search/suggestions/SearchSuggestionClient.kt b/mobile/android/android-components/components/feature/search/src/main/java/mozilla/components/feature/search/suggestions/SearchSuggestionClient.kt
new file mode 100644
index 0000000000..d4a0b5434b
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/java/mozilla/components/feature/search/suggestions/SearchSuggestionClient.kt
@@ -0,0 +1,101 @@
+/* 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.feature.search.suggestions
+
+import android.content.Context
+import mozilla.components.browser.state.search.SearchEngine
+import mozilla.components.browser.state.state.selectedOrDefaultSearchEngine
+import mozilla.components.browser.state.store.BrowserStore
+import mozilla.components.feature.search.ext.buildSuggestionsURL
+import mozilla.components.feature.search.ext.canProvideSearchSuggestions
+import mozilla.components.support.base.log.logger.Logger
+import org.json.JSONException
+import java.io.IOException
+
+/**
+ * Async function responsible for taking a URL and returning the results
+ */
+typealias SearchSuggestionFetcher = suspend (url: String) -> String?
+
+/**
+ * Provides an interface to get search suggestions from a given SearchEngine.
+ */
+class SearchSuggestionClient {
+ private val context: Context?
+ private val fetcher: SearchSuggestionFetcher
+ private val logger = Logger("SearchSuggestionClient")
+
+ val store: BrowserStore?
+ var searchEngine: SearchEngine? = null
+ private set
+
+ internal constructor(
+ context: Context?,
+ store: BrowserStore?,
+ searchEngine: SearchEngine?,
+ fetcher: SearchSuggestionFetcher,
+ ) {
+ this.context = context
+ this.store = store
+ this.searchEngine = searchEngine
+ this.fetcher = fetcher
+ }
+
+ constructor(searchEngine: SearchEngine, fetcher: SearchSuggestionFetcher) :
+ this (null, null, searchEngine, fetcher)
+
+ constructor(
+ context: Context,
+ store: BrowserStore,
+ fetcher: SearchSuggestionFetcher,
+ ) : this (context, store, null, fetcher)
+
+ /**
+ * Exception types for errors caught while getting a list of suggestions
+ */
+ class FetchException : Exception("There was a problem fetching suggestions")
+ class ResponseParserException : Exception("There was a problem parsing the suggestion response")
+
+ /**
+ * Gets search suggestions for a given query
+ */
+ suspend fun getSuggestions(query: String): List<String>? {
+ val searchEngine = searchEngine ?: run {
+ requireNotNull(store)
+ requireNotNull(context)
+
+ val searchEngine = store.state.search.selectedOrDefaultSearchEngine
+ if (searchEngine == null) {
+ logger.warn("No default search engine for fetching suggestions")
+ return emptyList()
+ } else {
+ this.searchEngine = searchEngine
+ searchEngine
+ }
+ }
+
+ if (!searchEngine.canProvideSearchSuggestions) {
+ // This search engine doesn't support suggestions. Let's only return a default suggestion
+ // for the entered text.
+ return emptyList()
+ }
+
+ val suggestionsURL = searchEngine.buildSuggestionsURL(query)
+
+ val parser = selectResponseParser(searchEngine)
+
+ val suggestionResults = try {
+ suggestionsURL?.let { fetcher(it) }
+ } catch (_: IOException) {
+ throw FetchException()
+ }
+
+ return try {
+ suggestionResults?.let(parser)
+ } catch (_: JSONException) {
+ throw ResponseParserException()
+ }
+ }
+}
diff --git a/mobile/android/android-components/components/feature/search/src/main/java/mozilla/components/feature/search/telemetry/BaseSearchTelemetry.kt b/mobile/android/android-components/components/feature/search/src/main/java/mozilla/components/feature/search/telemetry/BaseSearchTelemetry.kt
new file mode 100644
index 0000000000..971e41583a
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/java/mozilla/components/feature/search/telemetry/BaseSearchTelemetry.kt
@@ -0,0 +1,132 @@
+/* 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.feature.search.telemetry
+
+import androidx.annotation.VisibleForTesting
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.map
+import mozilla.components.browser.state.state.BrowserState
+import mozilla.components.browser.state.store.BrowserStore
+import mozilla.components.concept.engine.Engine
+import mozilla.components.concept.engine.EngineSession
+import mozilla.components.concept.engine.webextension.MessageHandler
+import mozilla.components.concept.engine.webextension.WebExtension
+import mozilla.components.lib.state.ext.flowScoped
+import mozilla.components.support.base.Component
+import mozilla.components.support.base.facts.Action.INTERACTION
+import mozilla.components.support.base.facts.Fact
+import mozilla.components.support.base.facts.collect
+import mozilla.components.support.base.log.logger.Logger
+import mozilla.components.support.ktx.kotlinx.coroutines.flow.filterChanged
+import org.json.JSONObject
+
+/**
+ * Main configuration and functionality for tracking ads / web searches with specific providers.
+ */
+abstract class BaseSearchTelemetry {
+ var providerList: List<SearchProviderModel>? = emptyList()
+
+ @VisibleForTesting(otherwise = VisibleForTesting.PROTECTED)
+ internal fun setProviderList(providerListSerp: List<SearchProviderModel>) {
+ providerList = providerListSerp
+ }
+
+ /**
+ * Finds provider among list of providers that matches regex in url.
+ * This may additionally return null if the provider list is still being initialized.
+ */
+ @VisibleForTesting(otherwise = VisibleForTesting.PROTECTED)
+ internal fun getProviderForUrl(url: String): SearchProviderModel? =
+ providerList?.find { provider -> provider.searchPageRegexp.containsMatchIn(url) }
+
+ /**
+ * Install the web extensions that this functionality is based on and start listening for updates.
+ */
+ abstract suspend fun install(
+ engine: Engine,
+ store: BrowserStore,
+ providerList: List<SearchProviderModel>,
+ )
+
+ @VisibleForTesting(otherwise = VisibleForTesting.PROTECTED)
+ internal fun installWebExtension(
+ engine: Engine,
+ store: BrowserStore,
+ extensionInfo: ExtensionInfo,
+ ) {
+ engine.installBuiltInWebExtension(
+ id = extensionInfo.id,
+ url = extensionInfo.resourceUrl,
+ onSuccess = { extension ->
+ store.flowScoped { flow ->
+ subscribeToUpdates(flow, extension, extensionInfo)
+ }
+ },
+ onError = { throwable ->
+ Logger.error("Could not install ${extensionInfo.id} extension", throwable)
+ },
+ )
+ }
+
+ protected fun emitFact(
+ event: String,
+ value: String,
+ metadata: Map<String, Any>? = null,
+ ) {
+ Fact(
+ Component.FEATURE_SEARCH,
+ INTERACTION,
+ event,
+ value,
+ metadata,
+ ).collect()
+ }
+
+ protected sealed class Action
+
+ private suspend fun subscribeToUpdates(
+ flow: Flow<BrowserState>,
+ extension: WebExtension,
+ extensionInfo: ExtensionInfo,
+ ) {
+ // Whenever we see a new EngineSession in the store then we register our content message
+ // handler if it has not been added yet.
+ flow.map { it.tabs }
+ .filterChanged { it.engineState.engineSession }
+ .collect { state ->
+ val engineSession = state.engineState.engineSession ?: return@collect
+
+ if (extension.hasContentMessageHandler(engineSession, extensionInfo.messageId)) {
+ return@collect
+ }
+ extension.registerContentMessageHandler(
+ engineSession,
+ extensionInfo.messageId,
+ SearchTelemetryMessageHandler(),
+ )
+ }
+ }
+
+ /**
+ * This method is used to process any valid json message coming from a web-extension.
+ */
+ @VisibleForTesting
+ internal abstract fun processMessage(message: JSONObject)
+
+ @VisibleForTesting
+ internal inner class SearchTelemetryMessageHandler : MessageHandler {
+
+ @Throws(IllegalStateException::class)
+ override fun onMessage(message: Any, source: EngineSession?): Any {
+ if (message is JSONObject) {
+ processMessage(message)
+ } else {
+ throw IllegalStateException("Received unexpected message: $message")
+ }
+
+ return Unit
+ }
+ }
+}
diff --git a/mobile/android/android-components/components/feature/search/src/main/java/mozilla/components/feature/search/telemetry/ExtensionInfo.kt b/mobile/android/android-components/components/feature/search/src/main/java/mozilla/components/feature/search/telemetry/ExtensionInfo.kt
new file mode 100644
index 0000000000..492bdf66f8
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/java/mozilla/components/feature/search/telemetry/ExtensionInfo.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.feature.search.telemetry
+
+/**
+ * Configuration data of web extensions used for the search / ads telemetry.
+ *
+ * @property id webExtension unique id.
+ * @property resourceUrl location of the webextension (may be local or web hosted).
+ * @property messageId message key used for communicating from the extension to the native app.
+ */
+internal data class ExtensionInfo(
+ val id: String,
+ val resourceUrl: String,
+ val messageId: String,
+)
diff --git a/mobile/android/android-components/components/feature/search/src/main/java/mozilla/components/feature/search/telemetry/SearchProviderCookie.kt b/mobile/android/android-components/components/feature/search/src/main/java/mozilla/components/feature/search/telemetry/SearchProviderCookie.kt
new file mode 100644
index 0000000000..eceae777f2
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/java/mozilla/components/feature/search/telemetry/SearchProviderCookie.kt
@@ -0,0 +1,24 @@
+/* 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.feature.search.telemetry
+
+/**
+ * Cookie details used to identify follow-on searches.
+ *
+ * @property extraCodeParamName the query parameter name in the URL that indicates
+ * this might be a follow-on search.
+ * @property extraCodePrefixes possible values for the query parameter in the URL that indicates
+ * this might be a follow-on search.
+ * @property host the hostname on which the cookie is stored.
+ * @property name the name of the cookie to check.
+ * @property codeParamName the name of parameter within the cookie.
+ */
+data class SearchProviderCookie(
+ val extraCodeParamName: String,
+ val extraCodePrefixes: List<String>,
+ val host: String,
+ val name: String,
+ val codeParamName: String,
+)
diff --git a/mobile/android/android-components/components/feature/search/src/main/java/mozilla/components/feature/search/telemetry/SearchProviderModel.kt b/mobile/android/android-components/components/feature/search/src/main/java/mozilla/components/feature/search/telemetry/SearchProviderModel.kt
new file mode 100644
index 0000000000..b45e17d231
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/java/mozilla/components/feature/search/telemetry/SearchProviderModel.kt
@@ -0,0 +1,80 @@
+/* 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.feature.search.telemetry
+
+/**
+ * All data needed to identify ads of a particular provider.
+ *
+ * @property taggedCodes array of partner codes to match against the partner code parameters in the url.
+ * @property telemetryId provider name e.g. "google", "duckduckgo".
+ * @property organicCodes array of partner codes to match against the parameters in the url.
+ * Matching these codes will report the SERP as organic:<partner code>, which means the search
+ * was performed organically rather than through a SAP.
+ * @property codeParamName name of the query parameter for the partner code.
+ * @property followOnCookies array of cookie details that are used to identify follow-on searches.
+ * @property queryParamNames list of names of the query parameters for the user's search string.
+ * @property searchPageRegexp regular expression used to match the provider.
+ * @property adServerAttributes an array of strings that potentially match data-attribute keys of anchors.
+ * @property followOnParamNames array of query parameter names that are used when a follow-on search occurs.
+ * @property extraAdServersRegexps array of regular expressions that match URLs of potential ad servers.
+ * @property expectedOrganicCodes array of partner codes to match against the parameters in the url.
+ * Matching these codes will report the SERP as organic:none which means the user has done a search
+ * through the search engine's website rather than through SAP.
+ */
+data class SearchProviderModel(
+ val schema: Long,
+ val taggedCodes: List<String>,
+ val telemetryId: String,
+ val organicCodes: List<String>?,
+ val codeParamName: String,
+ val followOnCookies: List<SearchProviderCookie>?,
+ val queryParamNames: List<String>?,
+ val searchPageRegexp: Regex,
+ val adServerAttributes: List<String>?,
+ val followOnParamNames: List<String>?,
+ val extraAdServersRegexps: List<Regex>,
+ val expectedOrganicCodes: List<String>?,
+
+) {
+
+ constructor(
+ schema: Long,
+ taggedCodes: List<String> = emptyList(),
+ telemetryId: String,
+ organicCodes: List<String>? = emptyList(),
+ codeParamName: String = "",
+ followOnCookies: List<SearchProviderCookie>? = emptyList(),
+ queryParamNames: List<String> = emptyList(),
+ searchPageRegexp: String,
+ adServerAttributes: List<String>? = emptyList(),
+ followOnParamNames: List<String>? = emptyList(),
+ extraAdServersRegexps: List<String> = emptyList(),
+ expectedOrganicCodes: List<String>? = emptyList(),
+
+ ) : this(
+ schema = schema,
+ taggedCodes = taggedCodes,
+ telemetryId = telemetryId,
+ organicCodes = organicCodes,
+ codeParamName = codeParamName,
+ followOnCookies = followOnCookies,
+ queryParamNames = queryParamNames,
+ searchPageRegexp = searchPageRegexp.toRegex(),
+ adServerAttributes = adServerAttributes,
+ followOnParamNames = followOnParamNames,
+ extraAdServersRegexps = extraAdServersRegexps.map { it.toRegex() },
+ expectedOrganicCodes = expectedOrganicCodes,
+
+ )
+
+ /**
+ * Checks if any of the given URLs represent an ad from the search engine.
+ * Used to check if a clicked link was for an ad.
+ */
+ fun containsAdLinks(urlList: List<String>) = urlList.any { url -> isAd(url) }
+
+ private fun isAd(url: String) =
+ extraAdServersRegexps.any { adsRegex -> adsRegex.containsMatchIn(url) }
+}
diff --git a/mobile/android/android-components/components/feature/search/src/main/java/mozilla/components/feature/search/telemetry/SerpTelemetryRepository.kt b/mobile/android/android-components/components/feature/search/src/main/java/mozilla/components/feature/search/telemetry/SerpTelemetryRepository.kt
new file mode 100644
index 0000000000..436b0e22db
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/java/mozilla/components/feature/search/telemetry/SerpTelemetryRepository.kt
@@ -0,0 +1,170 @@
+/* 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.feature.search.telemetry
+
+import mozilla.appservices.remotesettings.RemoteSettingsResponse
+import mozilla.components.support.base.log.logger.Logger
+import mozilla.components.support.ktx.android.org.json.asSequence
+import mozilla.components.support.ktx.android.org.json.toList
+import mozilla.components.support.remotesettings.RemoteSettingsClient
+import mozilla.components.support.remotesettings.RemoteSettingsResult
+import org.jetbrains.annotations.VisibleForTesting
+import org.json.JSONArray
+import org.json.JSONException
+import org.json.JSONObject
+import java.io.File
+
+internal const val REMOTE_PROD_ENDPOINT_URL = "https://firefox.settings.services.mozilla.com"
+internal const val REMOTE_ENDPOINT_BUCKET_NAME = "main"
+
+/**
+ * Parse SERP Telemetry json from remote config.
+ */
+class SerpTelemetryRepository(
+ rootStorageDirectory: File,
+ private val readJson: () -> JSONObject,
+ collectionName: String,
+ serverUrl: String = REMOTE_PROD_ENDPOINT_URL,
+ bucketName: String = REMOTE_ENDPOINT_BUCKET_NAME,
+) {
+ val logger = Logger("SerpTelemetryRepository")
+ private var providerList: List<SearchProviderModel> = emptyList()
+
+ @VisibleForTesting
+ internal var remoteSettingsClient = RemoteSettingsClient(
+ serverUrl = serverUrl,
+ bucketName = bucketName,
+ collectionName = collectionName,
+ storageRootDirectory = rootStorageDirectory,
+ )
+
+ /**
+ * Provides list of search providers from cache or dump and fetches from remotes server .
+ */
+ suspend fun updateProviderList(): List<SearchProviderModel> {
+ val (cacheLastModified, cacheResponse) = loadProvidersFromCache()
+ val localResponse = readJson()
+ if (cacheResponse.isEmpty() || cacheLastModified <= localResponse.getString("timestamp").toULong()) {
+ providerList = parseLocalPreinstalledData(localResponse)
+ } else if (cacheLastModified > localResponse.getString("timestamp").toULong()) {
+ providerList = cacheResponse
+ }
+ fetchRemoteResponse(cacheLastModified)
+ return providerList
+ }
+
+ @VisibleForTesting
+ internal suspend fun fetchRemoteResponse(
+ cacheLastModified: ULong?,
+ ) {
+ if (cacheLastModified == null) {
+ return
+ }
+ val remoteResponse = fetchRemoteResponse()
+ if (remoteResponse.lastModified > cacheLastModified) {
+ providerList = parseRemoteResponse(remoteResponse)
+ writeToCache(remoteResponse)
+ }
+ }
+
+ /**
+ * Writes data to local cache.
+ */
+ @VisibleForTesting
+ internal suspend fun writeToCache(records: RemoteSettingsResponse): RemoteSettingsResult {
+ return remoteSettingsClient.write(records)
+ }
+
+ /**
+ * Parses local json response.
+ */
+ @VisibleForTesting
+ internal fun parseLocalPreinstalledData(jsonObject: JSONObject): List<SearchProviderModel> {
+ return jsonObject.getJSONArray("data")
+ .asSequence()
+ .mapNotNull {
+ (it as JSONObject).toSearchProviderModel()
+ }
+ .toList()
+ }
+
+ /**
+ * Parses remote server response.
+ */
+ private fun parseRemoteResponse(response: RemoteSettingsResponse): List<SearchProviderModel> {
+ return response.records.mapNotNull {
+ it.fields.toSearchProviderModel()
+ }
+ }
+
+ /**
+ * Returns data from remote servers.
+ */
+ @VisibleForTesting
+ internal suspend fun fetchRemoteResponse(): RemoteSettingsResponse {
+ val result = remoteSettingsClient.fetch()
+ return if (result is RemoteSettingsResult.Success) {
+ result.response
+ } else {
+ RemoteSettingsResponse(emptyList(), 0u)
+ }
+ }
+
+ /**
+ * Returns search providers from local cache.
+ */
+ @VisibleForTesting
+ internal suspend fun loadProvidersFromCache(): Pair<ULong, List<SearchProviderModel>> {
+ val result = remoteSettingsClient.read()
+ return if (result is RemoteSettingsResult.Success) {
+ val response = result.response.records.mapNotNull {
+ it.fields.toSearchProviderModel()
+ }
+ val lastModified = result.response.lastModified
+ Pair(lastModified, response)
+ } else {
+ Pair(0u, emptyList())
+ }
+ }
+}
+
+@VisibleForTesting
+internal fun JSONObject.toSearchProviderModel(): SearchProviderModel? =
+ try {
+ SearchProviderModel(
+ schema = getLong("schema"),
+ taggedCodes = getJSONArray("taggedCodes").toList(),
+ telemetryId = optString("telemetryId"),
+ organicCodes = getJSONArray("organicCodes").toList(),
+ codeParamName = optString("codeParamName"),
+ followOnCookies = optJSONArray("followOnCookies")?.toListOfCookies(),
+ queryParamNames = optJSONArray("queryParamNames").toList(),
+ searchPageRegexp = optString("searchPageRegexp"),
+ adServerAttributes = optJSONArray("adServerAttributes").toList(),
+ followOnParamNames = optJSONArray("followOnParamNames")?.toList(),
+ extraAdServersRegexps = getJSONArray("extraAdServersRegexps").toList(),
+ expectedOrganicCodes = optJSONArray("expectedOrganicCodes")?.toList(),
+ )
+ } catch (e: JSONException) {
+ Logger("SerpTelemetryRepository").error("JSONException while trying to parse remote config", e)
+ null
+ }
+
+private fun JSONArray.toListOfCookies(): List<SearchProviderCookie> =
+ toList<JSONObject>().mapNotNull { jsonObject -> jsonObject.toSearchProviderCookie() }
+
+private fun JSONObject.toSearchProviderCookie(): SearchProviderCookie? =
+ try {
+ SearchProviderCookie(
+ extraCodeParamName = optString("extraCodeParamName"),
+ extraCodePrefixes = getJSONArray("extraCodePrefixes").toList(),
+ host = optString("host"),
+ name = optString("name"),
+ codeParamName = optString("codeParamName"),
+ )
+ } catch (e: JSONException) {
+ Logger("SerpTelemetryRepository").error("JSONException while trying to parse remote config", e)
+ null
+ }
diff --git a/mobile/android/android-components/components/feature/search/src/main/java/mozilla/components/feature/search/telemetry/TrackKeyInfo.kt b/mobile/android/android-components/components/feature/search/src/main/java/mozilla/components/feature/search/telemetry/TrackKeyInfo.kt
new file mode 100644
index 0000000000..c212c13b6f
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/java/mozilla/components/feature/search/telemetry/TrackKeyInfo.kt
@@ -0,0 +1,38 @@
+/* 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.feature.search.telemetry
+
+import java.util.Locale
+
+/**
+ * Key information about a Search Engine Result Page (SERP).
+ *
+ * @property provider The name of the search provider.
+ * @property type The search access point type (SAP). This is either "organic", "sap" or
+ * "sap-follow-on".
+ * @property code The search URL's `code` query parameter.
+ * @property channel The search URL's `channel` query parameter.
+ */
+internal data class TrackKeyInfo(
+ var provider: String,
+ var type: String,
+ var code: String?,
+ var channel: String? = null,
+) {
+ /**
+ * Returns the track key information into the following string format:
+ * `<provider>.in-content.[sap|sap-follow-on|organic].[code|none](.[channel])?`.
+ */
+ fun createTrackKey(): String {
+ return "${provider.lowercase(Locale.ROOT)}.in-content" +
+ ".${type.lowercase(Locale.ROOT)}" +
+ ".${code?.lowercase(Locale.ROOT) ?: "none"}" +
+ if (!channel?.lowercase(Locale.ROOT).isNullOrBlank()) {
+ ".${channel?.lowercase(Locale.ROOT)}"
+ } else {
+ ""
+ }
+ }
+}
diff --git a/mobile/android/android-components/components/feature/search/src/main/java/mozilla/components/feature/search/telemetry/Utils.kt b/mobile/android/android-components/components/feature/search/src/main/java/mozilla/components/feature/search/telemetry/Utils.kt
new file mode 100644
index 0000000000..b541c83d5f
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/java/mozilla/components/feature/search/telemetry/Utils.kt
@@ -0,0 +1,116 @@
+/* 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.feature.search.telemetry
+
+import android.net.Uri
+import org.json.JSONObject
+
+private const val SEARCH_TYPE_SAP_FOLLOW_ON = "sap-follow-on"
+private const val SEARCH_TYPE_SAP = "sap"
+private const val SEARCH_TYPE_ORGANIC = "organic"
+private const val CHANNEL_KEY = "channel"
+private val validChannelSet = setOf("ts")
+
+/**
+ * Get a String in a specific format allowing to identify how an ads/search provider was used.
+ *
+ * @see [TrackKeyInfo.createTrackKey]
+ */
+@Suppress("NestedBlockDepth", "ComplexMethod")
+internal fun getTrackKey(
+ provider: SearchProviderModel,
+ uri: Uri,
+ cookies: List<JSONObject>,
+): String {
+ var type = SEARCH_TYPE_ORGANIC
+ val paramSet = uri.queryParameterNames
+ var code: String? = "none"
+
+ if (provider.codeParamName.isNotEmpty()) {
+ code = uri.getQueryParameter(provider.codeParamName)
+ if (code.isNullOrEmpty() &&
+ provider.telemetryId == "baidu" &&
+ uri.toString().contains("from=")
+ ) {
+ code = uri.toString().substringAfter("from=", "")
+ .substringBefore("/", "")
+ }
+ if (code != null) {
+ // The code is only included if it matches one of the specific ones.
+ if (provider.taggedCodes.contains(code)) {
+ type = SEARCH_TYPE_SAP
+ if (provider.followOnParamNames?.any { p -> paramSet.contains(p) } == true) {
+ type = SEARCH_TYPE_SAP_FOLLOW_ON
+ }
+ } else if (provider.organicCodes?.contains(code) == true) {
+ type = SEARCH_TYPE_ORGANIC
+ } else if (provider.expectedOrganicCodes?.contains(code) == true) {
+ code = "none"
+ } else {
+ code = "other"
+ }
+ } else if (provider.followOnCookies != null) {
+ // Try cookies first because Bing has followOnCookies and valid code, but no
+ // followOnParams => would track organic instead of sap-follow-on
+ getTrackKeyFromCookies(provider, uri, cookies)?.let {
+ return it.createTrackKey()
+ }
+ }
+
+ // For Bing if it didn't have a valid cookie and for all the other search engines
+ if (hasValidCode(uri.getQueryParameter(provider.codeParamName), provider)) {
+ var channel = uri.getQueryParameter(CHANNEL_KEY)
+
+ // For Bug 1751955
+ if (!validChannelSet.contains(channel)) {
+ channel = null
+ }
+ return TrackKeyInfo(provider.telemetryId, type, code, channel).createTrackKey()
+ }
+ }
+ return TrackKeyInfo(provider.telemetryId, type, code).createTrackKey()
+}
+
+private fun getTrackKeyFromCookies(
+ provider: SearchProviderModel,
+ uri: Uri,
+ cookies: List<JSONObject>,
+): TrackKeyInfo? {
+ // Especially Bing requires lots of extra work related to cookies.
+ provider.followOnCookies?.forEach { followOnCookie ->
+ val eCode = uri.getQueryParameter(followOnCookie.extraCodeParamName)
+
+ if (eCode == null || !followOnCookie.extraCodePrefixes.any { prefix ->
+ eCode.startsWith(prefix)
+ }
+ ) {
+ return@forEach
+ }
+
+ // If this cookie is present, it's probably an SAP follow-on.
+ // This might be an organic follow-on in the same session, but there
+ // is no way to tell the difference.
+ for (cookie in cookies) {
+ if (cookie.getString("name") != followOnCookie.name) {
+ continue
+ }
+ val valueList = cookie.getString("value")
+ .split("=")
+ .map { item -> item.trim() }
+
+ if (valueList.size == 2 && valueList[0] == followOnCookie.codeParamName &&
+ provider.taggedCodes.any { prefix ->
+ valueList[1] == prefix
+ }
+ ) {
+ return TrackKeyInfo(provider.telemetryId, SEARCH_TYPE_SAP_FOLLOW_ON, valueList[1])
+ }
+ }
+ }
+ return null
+}
+
+private fun hasValidCode(code: String?, provider: SearchProviderModel): Boolean =
+ code != null && provider.taggedCodes.any { prefix -> code == prefix }
diff --git a/mobile/android/android-components/components/feature/search/src/main/java/mozilla/components/feature/search/telemetry/ads/AdsTelemetry.kt b/mobile/android/android-components/components/feature/search/src/main/java/mozilla/components/feature/search/telemetry/ads/AdsTelemetry.kt
new file mode 100644
index 0000000000..810baeff67
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/java/mozilla/components/feature/search/telemetry/ads/AdsTelemetry.kt
@@ -0,0 +1,124 @@
+/* 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.feature.search.telemetry.ads
+
+import android.net.Uri
+import androidx.annotation.VisibleForTesting
+import mozilla.components.browser.state.store.BrowserStore
+import mozilla.components.concept.engine.Engine
+import mozilla.components.feature.search.telemetry.BaseSearchTelemetry
+import mozilla.components.feature.search.telemetry.ExtensionInfo
+import mozilla.components.feature.search.telemetry.SearchProviderModel
+import mozilla.components.feature.search.telemetry.getTrackKey
+import mozilla.components.support.base.facts.Fact
+import mozilla.components.support.ktx.android.org.json.toList
+import org.json.JSONObject
+
+/**
+ * Telemetry for knowing how often users see/click ads in search and from which provider.
+ *
+ * Implemented as a browser extension based on the WebExtension API:
+ * https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions
+ */
+class AdsTelemetry : BaseSearchTelemetry() {
+
+ // SERP cached cookies used to check whether an ad was clicked.
+ @VisibleForTesting
+ internal var cachedCookies = listOf<JSONObject>()
+
+ override suspend fun install(
+ engine: Engine,
+ store: BrowserStore,
+ providerList: List<SearchProviderModel>,
+ ) {
+ val info = ExtensionInfo(
+ id = ADS_EXTENSION_ID,
+ resourceUrl = ADS_EXTENSION_RESOURCE_URL,
+ messageId = ADS_MESSAGE_ID,
+ )
+ installWebExtension(engine, store, info)
+ setProviderList(providerList)
+ }
+
+ override fun processMessage(message: JSONObject) {
+ // Cache the cookies list when the extension sends a message.
+ cachedCookies = message.getJSONArray(ADS_MESSAGE_COOKIES_KEY).toList()
+
+ val urls = message.getJSONArray(ADS_MESSAGE_DOCUMENT_URLS_KEY).toList<String>()
+ val uri = Uri.parse(message.getString(ADS_MESSAGE_SESSION_URL_KEY))
+ val provider = getProviderForUrl(message.getString(ADS_MESSAGE_SESSION_URL_KEY))
+
+ provider?.let {
+ if (it.containsAdLinks(urls)) {
+ emitFact(
+ SERP_SHOWN_WITH_ADDS,
+ getTrackKey(it, uri, cachedCookies),
+ )
+ }
+ }
+ }
+
+ /**
+ * To be called when the browser is navigating to a new URL, which may be a search ad.
+ *
+ * @param url The URL of the page before the search ad was clicked.
+ * This will be used to determine the originating search provider.
+ * @param urlPath A list of the URLs and load requests collected in between location changes.
+ * Clicking on a search ad generates a list of redirects from the originating search provider
+ * to the ad source. This is used to determine if there was an ad click.
+ */
+ @Suppress("ReturnCount")
+ fun checkIfAddWasClicked(url: String?, urlPath: List<String>) {
+ if (url == null) {
+ return
+ }
+ val uri = Uri.parse(url) ?: return
+ val provider = getProviderForUrl(url) ?: return
+ val paramSet = uri.queryParameterNames
+ val containsQueryParam = provider.queryParamNames?.any { paramSet.contains(it) }
+
+ if (containsQueryParam == false || !provider.containsAdLinks(urlPath)) {
+ // Do nothing if the URL does not have the search provider's query parameter or
+ // there were no ad clicks.
+ return
+ }
+
+ emitFact(
+ SERP_ADD_CLICKED,
+ getTrackKey(provider, uri, cachedCookies),
+ )
+ }
+
+ companion object {
+ /**
+ * [Fact] property indicating the user open a Search Engine Result Page
+ * of one of our search providers which contains ads.
+ */
+ const val SERP_SHOWN_WITH_ADDS = "SERP shown with adds"
+
+ /**
+ * [Fact] property indicating that an ad was clicked in a Search Engine Result Page.
+ */
+ const val SERP_ADD_CLICKED = "SERP add clicked"
+
+ @VisibleForTesting
+ internal const val ADS_EXTENSION_ID = "ads@mozac.org"
+
+ @VisibleForTesting
+ internal const val ADS_EXTENSION_RESOURCE_URL = "resource://android/assets/extensions/ads/"
+
+ @VisibleForTesting
+ internal const val ADS_MESSAGE_SESSION_URL_KEY = "url"
+
+ @VisibleForTesting
+ internal const val ADS_MESSAGE_DOCUMENT_URLS_KEY = "urls"
+
+ @VisibleForTesting
+ internal const val ADS_MESSAGE_COOKIES_KEY = "cookies"
+
+ @VisibleForTesting
+ internal const val ADS_MESSAGE_ID = "MozacBrowserAdsMessage"
+ }
+}
diff --git a/mobile/android/android-components/components/feature/search/src/main/java/mozilla/components/feature/search/telemetry/incontent/InContentTelemetry.kt b/mobile/android/android-components/components/feature/search/src/main/java/mozilla/components/feature/search/telemetry/incontent/InContentTelemetry.kt
new file mode 100644
index 0000000000..5a888b6ebb
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/java/mozilla/components/feature/search/telemetry/incontent/InContentTelemetry.kt
@@ -0,0 +1,86 @@
+/* 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.feature.search.telemetry.incontent
+
+import android.net.Uri
+import androidx.annotation.VisibleForTesting
+import mozilla.components.browser.state.store.BrowserStore
+import mozilla.components.concept.engine.Engine
+import mozilla.components.feature.search.telemetry.BaseSearchTelemetry
+import mozilla.components.feature.search.telemetry.ExtensionInfo
+import mozilla.components.feature.search.telemetry.SearchProviderModel
+import mozilla.components.feature.search.telemetry.getTrackKey
+import mozilla.components.support.base.facts.Fact
+import mozilla.components.support.ktx.android.org.json.toList
+import org.json.JSONObject
+
+/**
+ * Telemetry for knowing of in-web-content searches (including follow-on searches) and the provider used.
+ *
+ * Implemented as a browser extension based on the WebExtension API:
+ * https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions
+ */
+class InContentTelemetry : BaseSearchTelemetry() {
+
+ override suspend fun install(
+ engine: Engine,
+ store: BrowserStore,
+ providerList: List<SearchProviderModel>,
+ ) {
+ val info = ExtensionInfo(
+ id = SEARCH_EXTENSION_ID,
+ resourceUrl = SEARCH_EXTENSION_RESOURCE_URL,
+ messageId = SEARCH_MESSAGE_ID,
+ )
+ installWebExtension(engine, store, info)
+ setProviderList(providerList)
+ }
+
+ /**
+ * Processes a message containing search-related information.
+ */
+ override fun processMessage(message: JSONObject) {
+ val cookies = message.getJSONArray(SEARCH_MESSAGE_LIST_KEY).toList<JSONObject>()
+ trackPartnerUrlTypeMetric(message.getString(SEARCH_MESSAGE_SESSION_URL_KEY), cookies)
+ }
+
+ @VisibleForTesting
+ internal fun trackPartnerUrlTypeMetric(url: String, cookies: List<JSONObject>) {
+ val provider = getProviderForUrl(url) ?: return
+ val uri = Uri.parse(url)
+ val paramSet = uri.queryParameterNames
+ val containsQueryParam = provider.queryParamNames?.any { paramSet.contains(it) }
+ if (containsQueryParam == false) {
+ return
+ }
+ emitFact(
+ IN_CONTENT_SEARCH,
+ getTrackKey(provider, uri, cookies),
+ )
+ }
+
+ companion object {
+ /**
+ * [Fact] property indicating that the user did a search, be it a new one
+ * or continuing from an existing search.
+ */
+ const val IN_CONTENT_SEARCH = "in content search"
+
+ @VisibleForTesting
+ internal const val SEARCH_EXTENSION_ID = "cookies@mozac.org"
+
+ @VisibleForTesting
+ internal const val SEARCH_EXTENSION_RESOURCE_URL = "resource://android/assets/extensions/search/"
+
+ @VisibleForTesting
+ internal const val SEARCH_MESSAGE_SESSION_URL_KEY = "url"
+
+ @VisibleForTesting
+ internal const val SEARCH_MESSAGE_LIST_KEY = "cookies"
+
+ @VisibleForTesting
+ internal const val SEARCH_MESSAGE_ID = "MozacBrowserSearchMessage"
+ }
+}
diff --git a/mobile/android/android-components/components/feature/search/src/main/java/mozilla/components/feature/search/widget/AppSearchWidgetProvider.kt b/mobile/android/android-components/components/feature/search/src/main/java/mozilla/components/feature/search/widget/AppSearchWidgetProvider.kt
new file mode 100644
index 0000000000..62a4e2d83e
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/java/mozilla/components/feature/search/widget/AppSearchWidgetProvider.kt
@@ -0,0 +1,312 @@
+/* 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.feature.search.widget
+
+import android.app.PendingIntent
+import android.appwidget.AppWidgetManager
+import android.appwidget.AppWidgetManager.OPTION_APPWIDGET_MIN_WIDTH
+import android.appwidget.AppWidgetProvider
+import android.content.ComponentName
+import android.content.Context
+import android.content.Intent
+import android.os.Build
+import android.os.Bundle
+import android.view.View
+import android.widget.RemoteViews
+import androidx.annotation.Dimension
+import androidx.annotation.Dimension.Companion.DP
+import androidx.annotation.VisibleForTesting
+import androidx.appcompat.content.res.AppCompatResources
+import androidx.core.graphics.drawable.toBitmap
+import mozilla.components.feature.search.R
+import mozilla.components.feature.search.widget.BaseVoiceSearchActivity.Companion.SPEECH_PROCESSING
+import mozilla.components.support.utils.PendingIntentUtils
+
+/**
+ * An abstract [AppWidgetProvider] that implements core behaviour needed to support a Search Widget
+ * on the launcher.
+ */
+abstract class AppSearchWidgetProvider : AppWidgetProvider() {
+
+ override fun onUpdate(
+ context: Context,
+ appWidgetManager: AppWidgetManager,
+ appWidgetIds: IntArray,
+ ) {
+ val textSearchIntent = createTextSearchIntent(context)
+ val voiceSearchIntent = createVoiceSearchIntent(context)
+
+ appWidgetIds.forEach { appWidgetId ->
+ updateWidgetLayout(
+ context = context,
+ appWidgetId = appWidgetId,
+ appWidgetManager = appWidgetManager,
+ voiceSearchIntent = voiceSearchIntent,
+ textSearchIntent = textSearchIntent,
+ )
+ }
+ }
+
+ override fun onAppWidgetOptionsChanged(
+ context: Context,
+ appWidgetManager: AppWidgetManager,
+ appWidgetId: Int,
+ newOptions: Bundle?,
+ ) {
+ val textSearchIntent = createTextSearchIntent(context)
+ val voiceSearchIntent = createVoiceSearchIntent(context)
+
+ updateWidgetLayout(
+ context = context,
+ appWidgetId = appWidgetId,
+ appWidgetManager = appWidgetManager,
+ voiceSearchIntent = voiceSearchIntent,
+ textSearchIntent = textSearchIntent,
+ )
+ }
+
+ /**
+ * Builds pending intent that opens the browser and starts a new text search.
+ */
+ abstract fun createTextSearchIntent(context: Context): PendingIntent
+
+ /**
+ * If the microphone will appear on the Search Widget and the user can perform a voice search.
+ */
+ abstract fun shouldShowVoiceSearch(context: Context): Boolean
+
+ /**
+ * Activity that extends BaseVoiceSearchActivity.
+ */
+ abstract fun voiceSearchActivity(): Class<out BaseVoiceSearchActivity>
+
+ /**
+ * Config that sets the icons and the strings for search widget.
+ */
+ abstract val config: SearchWidgetConfig
+
+ /**
+ * Builds pending intent that starts a new voice search.
+ */
+ @VisibleForTesting
+ internal fun createVoiceSearchIntent(context: Context): PendingIntent? {
+ if (!shouldShowVoiceSearch(context)) {
+ return null
+ }
+
+ val voiceIntent = Intent(context, voiceSearchActivity()).apply {
+ flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
+ putExtra(SPEECH_PROCESSING, true)
+ }
+
+ return PendingIntent.getActivity(
+ context,
+ REQUEST_CODE_VOICE,
+ voiceIntent,
+ PendingIntentUtils.defaultFlags,
+ )
+ }
+
+ private fun updateWidgetLayout(
+ context: Context,
+ appWidgetId: Int,
+ appWidgetManager: AppWidgetManager,
+ voiceSearchIntent: PendingIntent?,
+ textSearchIntent: PendingIntent,
+ ) {
+ val currentWidth =
+ appWidgetManager.getAppWidgetOptions(appWidgetId).getInt(OPTION_APPWIDGET_MIN_WIDTH)
+ val layoutSize = getLayoutSize(currentWidth)
+ // It's not enough to just hide the microphone on the "small" sized widget due to its design.
+ // The "small" widget needs a complete redesign, meaning it needs a new layout file.
+ val showMic = (voiceSearchIntent != null)
+ val layout = getLayout(layoutSize, showMic)
+ val text = getText(layoutSize, context)
+
+ val views =
+ createRemoteViews(context, layout, textSearchIntent, voiceSearchIntent, text)
+ appWidgetManager.updateAppWidget(appWidgetId, views)
+ }
+
+ private fun createRemoteViews(
+ context: Context,
+ layout: Int,
+ textSearchIntent: PendingIntent,
+ voiceSearchIntent: PendingIntent?,
+ text: String?,
+ ): RemoteViews {
+ return RemoteViews(context.packageName, layout).apply {
+ setSearchWidgetIcon(context)
+ setMicrophoneIcon(context)
+ when (layout) {
+ R.layout.mozac_search_widget_extra_small_v1,
+ R.layout.mozac_search_widget_extra_small_v2,
+ R.layout.mozac_search_widget_small_no_mic,
+ -> {
+ setOnClickPendingIntent(
+ R.id.mozac_button_search_widget_new_tab,
+ textSearchIntent,
+ )
+ }
+ R.layout.mozac_search_widget_small -> {
+ setOnClickPendingIntent(
+ R.id.mozac_button_search_widget_new_tab,
+ textSearchIntent,
+ )
+ setOnClickPendingIntent(
+ R.id.mozac_button_search_widget_voice,
+ voiceSearchIntent,
+ )
+ }
+ R.layout.mozac_search_widget_medium,
+ R.layout.mozac_search_widget_large,
+ -> {
+ setOnClickPendingIntent(
+ R.id.mozac_button_search_widget_new_tab,
+ textSearchIntent,
+ )
+ setOnClickPendingIntent(
+ R.id.mozac_button_search_widget_voice,
+ voiceSearchIntent,
+ )
+ setOnClickPendingIntent(
+ R.id.mozac_button_search_widget_new_tab_icon,
+ textSearchIntent,
+ )
+ setTextViewText(R.id.mozac_button_search_widget_new_tab, text)
+
+ // Unlike "small" widget, "medium" and "large" sizes do not have separate layouts
+ // that exclude the microphone icon, which is why we must hide it accordingly here.
+ if (voiceSearchIntent == null) {
+ setViewVisibility(R.id.mozac_button_search_widget_voice, View.GONE)
+ }
+ }
+ }
+ }
+ }
+
+ private fun RemoteViews.setMicrophoneIcon(context: Context) {
+ setImageView(
+ context,
+ R.id.mozac_button_search_widget_voice,
+ config.searchWidgetMicrophoneResource,
+ )
+ }
+
+ private fun RemoteViews.setSearchWidgetIcon(context: Context) {
+ setImageView(
+ context,
+ R.id.mozac_button_search_widget_new_tab_icon,
+ config.searchWidgetIconResource,
+ )
+ val appName = context.getString(config.appName)
+ setContentDescription(
+ R.id.mozac_button_search_widget_new_tab_icon,
+ context.getString(R.string.search_widget_content_description, appName),
+ )
+ }
+
+ private fun RemoteViews.setImageView(context: Context, viewId: Int, resourceId: Int) {
+ // gradient color available for android:fillColor only on SDK 24+
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
+ setImageViewResource(
+ viewId,
+ resourceId,
+ )
+ } else {
+ setImageViewBitmap(
+ viewId,
+ AppCompatResources.getDrawable(
+ context,
+ resourceId,
+ )?.toBitmap(),
+ )
+ }
+ }
+
+ // Cell sizes obtained from the actual dimensions listed in search widget specs.
+ companion object {
+ private const val DP_EXTRA_SMALL = 64
+ private const val DP_SMALL = 100
+ private const val DP_MEDIUM = 192
+ private const val DP_LARGE = 256
+ private const val REQUEST_CODE_VOICE = 1
+
+ /**
+ * It updates AppSearchWidgetProvider size and microphone icon visibility.
+ */
+ fun updateAllWidgets(context: Context, clazz: Class<out AppSearchWidgetProvider>) {
+ val widgetManager = AppWidgetManager.getInstance(context)
+ val widgetIds = widgetManager.getAppWidgetIds(
+ ComponentName(
+ context,
+ clazz,
+ ),
+ )
+ if (widgetIds.isNotEmpty()) {
+ context.sendBroadcast(
+ Intent(context, clazz).apply {
+ action = AppWidgetManager.ACTION_APPWIDGET_UPDATE
+ putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, widgetIds)
+ },
+ )
+ }
+ }
+
+ @VisibleForTesting
+ internal fun getLayoutSize(@Dimension(unit = DP) dp: Int) = when {
+ dp >= DP_LARGE -> SearchWidgetProviderSize.LARGE
+ dp >= DP_MEDIUM -> SearchWidgetProviderSize.MEDIUM
+ dp >= DP_SMALL -> SearchWidgetProviderSize.SMALL
+ dp >= DP_EXTRA_SMALL -> SearchWidgetProviderSize.EXTRA_SMALL_V2
+ else -> SearchWidgetProviderSize.EXTRA_SMALL_V1
+ }
+
+ /**
+ * Get the layout resource to use for the search widget.
+ */
+ @VisibleForTesting
+ internal fun getLayout(size: SearchWidgetProviderSize, showMic: Boolean) = when (size) {
+ SearchWidgetProviderSize.LARGE -> R.layout.mozac_search_widget_large
+ SearchWidgetProviderSize.MEDIUM -> R.layout.mozac_search_widget_medium
+ SearchWidgetProviderSize.SMALL -> {
+ if (showMic) {
+ R.layout.mozac_search_widget_small
+ } else {
+ R.layout.mozac_search_widget_small_no_mic
+ }
+ }
+ SearchWidgetProviderSize.EXTRA_SMALL_V2 -> R.layout.mozac_search_widget_extra_small_v2
+ SearchWidgetProviderSize.EXTRA_SMALL_V1 -> R.layout.mozac_search_widget_extra_small_v1
+ }
+
+ /**
+ * Get the text to place in the search widget.
+ */
+ @VisibleForTesting
+ internal fun getText(layout: SearchWidgetProviderSize, context: Context) = when (layout) {
+ SearchWidgetProviderSize.MEDIUM -> context.getString(R.string.search_widget_text_short)
+ SearchWidgetProviderSize.LARGE -> context.getString(R.string.search_widget_text_long)
+ else -> null
+ }
+ }
+}
+
+/**
+ * Client App can set from this config icons and the app name for search widget.
+ */
+data class SearchWidgetConfig(
+ val searchWidgetIconResource: Int,
+ val searchWidgetMicrophoneResource: Int,
+ val appName: Int,
+)
+
+internal enum class SearchWidgetProviderSize {
+ EXTRA_SMALL_V1,
+ EXTRA_SMALL_V2,
+ SMALL,
+ MEDIUM,
+ LARGE,
+}
diff --git a/mobile/android/android-components/components/feature/search/src/main/java/mozilla/components/feature/search/widget/BaseVoiceSearchActivity.kt b/mobile/android/android-components/components/feature/search/src/main/java/mozilla/components/feature/search/widget/BaseVoiceSearchActivity.kt
new file mode 100644
index 0000000000..1c70f9809d
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/java/mozilla/components/feature/search/widget/BaseVoiceSearchActivity.kt
@@ -0,0 +1,134 @@
+/* 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.feature.search.widget
+
+import android.app.Activity
+import android.content.ActivityNotFoundException
+import android.content.Intent
+import android.os.Bundle
+import android.speech.RecognizerIntent
+import androidx.activity.result.ActivityResult
+import androidx.activity.result.ActivityResultLauncher
+import androidx.activity.result.contract.ActivityResultContracts
+import androidx.annotation.VisibleForTesting
+import androidx.appcompat.app.AppCompatActivity
+import mozilla.components.support.base.log.logger.Logger
+import mozilla.components.support.utils.ext.getParcelableCompat
+import java.util.Locale
+
+/**
+ * Launches voice recognition then uses it to start a new web search.
+ */
+abstract class BaseVoiceSearchActivity : AppCompatActivity() {
+
+ /**
+ * Holds the intent that initially started this activity
+ * so that it can persist through the speech activity.
+ */
+ private var previousIntent: Intent? = null
+
+ private var activityResultLauncher: ActivityResultLauncher<Intent> = getActivityResultLauncher()
+
+ override fun onSaveInstanceState(outState: Bundle) {
+ super.onSaveInstanceState(outState)
+ outState.putParcelable(PREVIOUS_INTENT, previousIntent)
+ }
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ // Retrieve the previous intent from the saved state
+ previousIntent = savedInstanceState?.getParcelableCompat(PREVIOUS_INTENT, Intent::class.java)
+ if (previousIntent.isForSpeechProcessing()) {
+ // Don't reopen the speech recognizer
+ return
+ }
+
+ // The intent property is nullable, but the rest of the code below assumes it is not.
+ val intent = intent?.let { Intent(intent) } ?: Intent()
+ if (intent.isForSpeechProcessing()) {
+ previousIntent = intent
+ displaySpeechRecognizer()
+ } else {
+ finish()
+ }
+ }
+
+ /**
+ * Language locale for Voice Search.
+ */
+ abstract fun getCurrentLocale(): Locale
+
+ /**
+ * Speech recognizer popup is shown.
+ */
+ abstract fun onSpeechRecognitionStarted()
+
+ /**
+ * Start intent after voice search ,for example a browser page is open with the spokenText.
+ * @param spokenText what the user voice search
+ */
+ abstract fun onSpeechRecognitionEnded(spokenText: String)
+
+ @VisibleForTesting
+ internal fun activityResultImplementation(activityResult: ActivityResult) {
+ if (activityResult.resultCode == Activity.RESULT_OK) {
+ val spokenText =
+ activityResult.data?.getStringArrayListExtra(RecognizerIntent.EXTRA_RESULTS)
+ ?.first()
+ previousIntent?.apply {
+ spokenText?.let { onSpeechRecognitionEnded(it) }
+ }
+ }
+ finish()
+ }
+
+ private fun getActivityResultLauncher(): ActivityResultLauncher<Intent> {
+ return registerForActivityResult(
+ ActivityResultContracts.StartActivityForResult(),
+ ) {
+ activityResultImplementation(it)
+ }
+ }
+
+ /**
+ * Displays a speech recognizer popup that listens for input from the user.
+ */
+ private fun displaySpeechRecognizer() {
+ val intentSpeech = Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH).apply {
+ putExtra(
+ RecognizerIntent.EXTRA_LANGUAGE_MODEL,
+ RecognizerIntent.LANGUAGE_MODEL_FREE_FORM,
+ )
+ putExtra(
+ RecognizerIntent.EXTRA_LANGUAGE,
+ getCurrentLocale(),
+ )
+ }
+ onSpeechRecognitionStarted()
+ try {
+ activityResultLauncher.launch(intentSpeech)
+ } catch (e: ActivityNotFoundException) {
+ Logger(TAG).error("ActivityNotFoundException " + e.message.toString())
+ finish()
+ }
+ }
+
+ /**
+ * Returns true if the [SPEECH_PROCESSING] extra is present and set to true.
+ * Returns false if the intent is null.
+ */
+ private fun Intent?.isForSpeechProcessing(): Boolean =
+ this?.getBooleanExtra(SPEECH_PROCESSING, false) == true
+
+ companion object {
+ const val PREVIOUS_INTENT = "org.mozilla.components.previous_intent"
+
+ /**
+ * In [BaseVoiceSearchActivity] activity, used to store if the speech processing should start.
+ */
+ const val SPEECH_PROCESSING = "speech_processing"
+ const val TAG = "BaseVoiceSearchActivity"
+ }
+}
diff --git a/mobile/android/android-components/components/feature/search/src/main/res/drawable/mozac_rounded_search_widget_background.xml b/mobile/android/android-components/components/feature/search/src/main/res/drawable/mozac_rounded_search_widget_background.xml
new file mode 100644
index 0000000000..fd61fe2557
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/res/drawable/mozac_rounded_search_widget_background.xml
@@ -0,0 +1,9 @@
+<?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/. -->
+
+<shape xmlns:android="http://schemas.android.com/apk/res/android">
+ <solid android:color="@color/mozac_feature_search_widget_background_color" />
+ <corners android:radius="@dimen/mozac_tab_corner_radius"/>
+</shape>
diff --git a/mobile/android/android-components/components/feature/search/src/main/res/layout/mozac_search_widget_extra_small_v1.xml b/mobile/android/android-components/components/feature/search/src/main/res/layout/mozac_search_widget_extra_small_v1.xml
new file mode 100644
index 0000000000..ee95021031
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/res/layout/mozac_search_widget_extra_small_v1.xml
@@ -0,0 +1,20 @@
+<?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/. -->
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@id/mozac_button_search_widget_new_tab"
+ android:layout_width="match_parent"
+ android:layout_height="50dp"
+ android:layout_gravity="center"
+ android:background="@drawable/mozac_rounded_search_widget_background">
+
+ <ImageView
+ android:id="@+id/mozac_button_search_widget_new_tab_icon"
+ android:layout_width="50dp"
+ android:layout_height="50dp"
+ android:layout_gravity="center"
+ android:contentDescription="@string/search_widget_content_description"
+ android:scaleType="centerInside" />
+
+</FrameLayout>
diff --git a/mobile/android/android-components/components/feature/search/src/main/res/layout/mozac_search_widget_extra_small_v2.xml b/mobile/android/android-components/components/feature/search/src/main/res/layout/mozac_search_widget_extra_small_v2.xml
new file mode 100644
index 0000000000..468df05b75
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/res/layout/mozac_search_widget_extra_small_v2.xml
@@ -0,0 +1,19 @@
+<?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/. -->
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@id/mozac_button_search_widget_new_tab"
+ android:layout_width="match_parent"
+ android:layout_height="50dp"
+ android:layout_gravity="center"
+ android:background="@drawable/mozac_rounded_search_widget_background">
+
+ <ImageView
+ android:id="@+id/mozac_button_search_widget_new_tab_icon"
+ android:layout_width="50dp"
+ android:layout_height="50dp"
+ android:layout_gravity="center"
+ android:contentDescription="@string/search_widget_content_description"
+ android:scaleType="centerInside" />
+</FrameLayout>
diff --git a/mobile/android/android-components/components/feature/search/src/main/res/layout/mozac_search_widget_large.xml b/mobile/android/android-components/components/feature/search/src/main/res/layout/mozac_search_widget_large.xml
new file mode 100644
index 0000000000..7801adb460
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/res/layout/mozac_search_widget_large.xml
@@ -0,0 +1,45 @@
+<?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/. -->
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tools="http://schemas.android.com/tools"
+ android:layout_width="match_parent"
+ android:layout_height="50dp"
+ android:layout_gravity="center"
+ android:background="@drawable/mozac_rounded_search_widget_background">
+
+ <ImageView
+ android:id="@+id/mozac_button_search_widget_new_tab_icon"
+ android:layout_width="50dp"
+ android:layout_height="50dp"
+ android:layout_alignParentStart="true"
+ android:contentDescription="@string/search_widget_content_description"
+ android:scaleType="centerInside" />
+
+ <TextView
+ android:id="@+id/mozac_button_search_widget_new_tab"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:layout_alignEnd="@id/mozac_button_search_widget_voice"
+ android:layout_marginStart="9dp"
+ android:layout_toEndOf="@id/mozac_button_search_widget_new_tab_icon"
+ android:gravity="start|center_vertical"
+ android:letterSpacing="-0.025"
+ android:textAlignment="viewStart"
+ android:textColor="@color/mozac_feature_search_widget_text_color"
+ android:textSize="15sp"
+ tools:text="Search the web" />
+
+ <ImageButton
+ android:id="@+id/mozac_button_search_widget_voice"
+ android:layout_width="48dp"
+ android:layout_height="48dp"
+ android:layout_alignParentEnd="true"
+ android:background="@android:color/transparent"
+ android:layout_centerVertical="true"
+ android:padding="8dp"
+ android:layout_marginEnd="1dp"
+ android:contentDescription="@string/search_widget_voice" />
+
+</RelativeLayout>
diff --git a/mobile/android/android-components/components/feature/search/src/main/res/layout/mozac_search_widget_medium.xml b/mobile/android/android-components/components/feature/search/src/main/res/layout/mozac_search_widget_medium.xml
new file mode 100644
index 0000000000..5cbcdffd84
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/res/layout/mozac_search_widget_medium.xml
@@ -0,0 +1,45 @@
+<?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/. -->
+
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tools="http://schemas.android.com/tools"
+ android:layout_width="match_parent"
+ android:layout_height="50dp"
+ android:layout_gravity="center"
+ android:background="@drawable/mozac_rounded_search_widget_background">
+
+ <ImageView
+ android:id="@+id/mozac_button_search_widget_new_tab_icon"
+ android:layout_width="50dp"
+ android:layout_height="50dp"
+ android:layout_alignParentStart="true"
+ android:contentDescription="@string/search_widget_content_description"
+ android:scaleType="centerInside" />
+
+ <TextView
+ android:id="@+id/mozac_button_search_widget_new_tab"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:layout_alignEnd="@id/mozac_button_search_widget_voice"
+ android:layout_marginStart="9dp"
+ android:layout_toEndOf="@id/mozac_button_search_widget_new_tab_icon"
+ android:gravity="start|center_vertical"
+ android:letterSpacing="-0.025"
+ android:textAlignment="viewStart"
+ android:textColor="@color/mozac_feature_search_widget_text_color"
+ android:textSize="15sp"
+ tools:text="Search" />
+
+ <ImageButton
+ android:id="@+id/mozac_button_search_widget_voice"
+ android:layout_width="48dp"
+ android:layout_height="48dp"
+ android:layout_alignParentEnd="true"
+ android:layout_centerVertical="true"
+ android:padding="8dp"
+ android:background="@android:color/transparent"
+ android:layout_marginEnd="1dp"
+ android:contentDescription="@string/search_widget_voice" />
+
+</RelativeLayout>
diff --git a/mobile/android/android-components/components/feature/search/src/main/res/layout/mozac_search_widget_small.xml b/mobile/android/android-components/components/feature/search/src/main/res/layout/mozac_search_widget_small.xml
new file mode 100644
index 0000000000..c75217e90f
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/res/layout/mozac_search_widget_small.xml
@@ -0,0 +1,27 @@
+<?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/. -->
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="50dp"
+ android:background="@drawable/mozac_rounded_search_widget_background" >
+
+ <ImageView
+ android:id="@+id/mozac_button_search_widget_new_tab_icon"
+ android:layout_alignParentStart="true"
+ android:layout_width="50dp"
+ android:layout_height="50dp"
+ android:contentDescription="@string/search_widget_content_description"
+ android:scaleType="centerInside" />
+
+ <ImageView
+ android:id="@+id/mozac_button_search_widget_voice"
+ android:layout_alignParentEnd="true"
+ android:layout_width="50dp"
+ android:layout_height="50dp"
+ android:contentDescription="@string/search_widget_voice"
+ android:padding="10dp"
+ android:background="@android:color/transparent"
+ android:scaleType="centerInside" />
+
+</RelativeLayout>
diff --git a/mobile/android/android-components/components/feature/search/src/main/res/layout/mozac_search_widget_small_no_mic.xml b/mobile/android/android-components/components/feature/search/src/main/res/layout/mozac_search_widget_small_no_mic.xml
new file mode 100644
index 0000000000..61d2152b4b
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/res/layout/mozac_search_widget_small_no_mic.xml
@@ -0,0 +1,19 @@
+<?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/. -->
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@id/mozac_button_search_widget_new_tab"
+ android:layout_width="match_parent"
+ android:layout_height="50dp"
+ android:layout_gravity="center"
+ android:background="@drawable/mozac_rounded_search_widget_background"
+ android:orientation="vertical">
+
+ <ImageView
+ android:id="@+id/mozac_button_search_widget_new_tab_icon"
+ android:layout_width="40dp"
+ android:layout_height="40dp"
+ android:layout_gravity="center"
+ android:contentDescription="@string/search_widget_content_description" />
+</FrameLayout>
diff --git a/mobile/android/android-components/components/feature/search/src/main/res/values-am/strings.xml b/mobile/android/android-components/components/feature/search/src/main/res/values-am/strings.xml
new file mode 100644
index 0000000000..05a821675e
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/res/values-am/strings.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Search Widget -->
+ <!-- Content description for searching with a widget. The first parameter is the name of the application.-->
+ <string name="search_widget_content_description">አዲስ %1$s ትር ክፈት</string>
+ <!-- Text preview for smaller sized widgets -->
+ <string name="search_widget_text_short">ፈልግ</string>
+ <!-- Text preview for larger sized widgets -->
+ <string name="search_widget_text_long">ድሩን ይፈልጉ</string>
+ <!-- Content description (not visible, for screen readers etc.): Voice search -->
+ <string name="search_widget_voice">የድምጽ ፍለጋ</string>
+</resources>
diff --git a/mobile/android/android-components/components/feature/search/src/main/res/values-ar/strings.xml b/mobile/android/android-components/components/feature/search/src/main/res/values-ar/strings.xml
new file mode 100644
index 0000000000..d75141a022
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/res/values-ar/strings.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Search Widget -->
+ <!-- Content description for searching with a widget. The first parameter is the name of the application.-->
+ <string name="search_widget_content_description">افتح لسان %1$s جديد</string>
+ <!-- Text preview for smaller sized widgets -->
+ <string name="search_widget_text_short">ابحث</string>
+ <!-- Text preview for larger sized widgets -->
+ <string name="search_widget_text_long">ابحث في الوِب</string>
+ <!-- Content description (not visible, for screen readers etc.): Voice search -->
+ <string name="search_widget_voice">البحث الصوتي</string>
+</resources>
diff --git a/mobile/android/android-components/components/feature/search/src/main/res/values-ast/strings.xml b/mobile/android/android-components/components/feature/search/src/main/res/values-ast/strings.xml
new file mode 100644
index 0000000000..dab4e3690a
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/res/values-ast/strings.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Search Widget -->
+ <!-- Content description for searching with a widget. The first parameter is the name of the application.-->
+ <string name="search_widget_content_description">Abrir nuna llingüeta de %1$s nueva</string>
+ <!-- Text preview for smaller sized widgets -->
+ <string name="search_widget_text_short">Buscar</string>
+ <!-- Text preview for larger sized widgets -->
+ <string name="search_widget_text_long">Buscar na web</string>
+ <!-- Content description (not visible, for screen readers etc.): Voice search -->
+ <string name="search_widget_voice">Busca pela voz</string>
+</resources>
diff --git a/mobile/android/android-components/components/feature/search/src/main/res/values-azb/strings.xml b/mobile/android/android-components/components/feature/search/src/main/res/values-azb/strings.xml
new file mode 100644
index 0000000000..dad76ea236
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/res/values-azb/strings.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Search Widget -->
+ <!-- Content description for searching with a widget. The first parameter is the name of the application.-->
+ <string name="search_widget_content_description">یئنی بیر %1$s تاغی آچین</string>
+ <!-- Text preview for smaller sized widgets -->
+ <string name="search_widget_text_short">آختاریش</string>
+ <!-- Text preview for larger sized widgets -->
+ <string name="search_widget_text_long">وب‌ده آختار</string>
+ <!-- Content description (not visible, for screen readers etc.): Voice search -->
+ <string name="search_widget_voice">سس‌لی آختاریش</string>
+</resources>
diff --git a/mobile/android/android-components/components/feature/search/src/main/res/values-be/strings.xml b/mobile/android/android-components/components/feature/search/src/main/res/values-be/strings.xml
new file mode 100644
index 0000000000..d01b3ed8ac
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/res/values-be/strings.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Search Widget -->
+ <!-- Content description for searching with a widget. The first parameter is the name of the application.-->
+ <string name="search_widget_content_description">Адкрыць новую картку %1$s</string>
+ <!-- Text preview for smaller sized widgets -->
+ <string name="search_widget_text_short">Пошук</string>
+ <!-- Text preview for larger sized widgets -->
+ <string name="search_widget_text_long">Пошук у інтэрнэце</string>
+ <!-- Content description (not visible, for screen readers etc.): Voice search -->
+ <string name="search_widget_voice">Галасавы пошук</string>
+</resources>
diff --git a/mobile/android/android-components/components/feature/search/src/main/res/values-bg/strings.xml b/mobile/android/android-components/components/feature/search/src/main/res/values-bg/strings.xml
new file mode 100644
index 0000000000..62aa6628d4
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/res/values-bg/strings.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Search Widget -->
+ <!-- Content description for searching with a widget. The first parameter is the name of the application.-->
+ <string name="search_widget_content_description">Отваряне на раздел с %1$s</string>
+ <!-- Text preview for smaller sized widgets -->
+ <string name="search_widget_text_short">Търсене</string>
+ <!-- Text preview for larger sized widgets -->
+ <string name="search_widget_text_long">Търсене в интернет</string>
+ <!-- Content description (not visible, for screen readers etc.): Voice search -->
+ <string name="search_widget_voice">Гласово търсене</string>
+</resources>
diff --git a/mobile/android/android-components/components/feature/search/src/main/res/values-br/strings.xml b/mobile/android/android-components/components/feature/search/src/main/res/values-br/strings.xml
new file mode 100644
index 0000000000..efdc6aa03a
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/res/values-br/strings.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Search Widget -->
+ <!-- Content description for searching with a widget. The first parameter is the name of the application.-->
+ <string name="search_widget_content_description">Digeriñ un ivinell %1$s nevez</string>
+ <!-- Text preview for smaller sized widgets -->
+ <string name="search_widget_text_short">Klask</string>
+ <!-- Text preview for larger sized widgets -->
+ <string name="search_widget_text_long">Klask er web</string>
+ <!-- Content description (not visible, for screen readers etc.): Voice search -->
+ <string name="search_widget_voice">Klask dre vouezh</string>
+</resources>
diff --git a/mobile/android/android-components/components/feature/search/src/main/res/values-bs/strings.xml b/mobile/android/android-components/components/feature/search/src/main/res/values-bs/strings.xml
new file mode 100644
index 0000000000..8d89c63779
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/res/values-bs/strings.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Search Widget -->
+ <!-- Content description for searching with a widget. The first parameter is the name of the application.-->
+ <string name="search_widget_content_description">Otvori novi %1$s tab</string>
+ <!-- Text preview for smaller sized widgets -->
+ <string name="search_widget_text_short">Traži</string>
+ <!-- Text preview for larger sized widgets -->
+ <string name="search_widget_text_long">Pretraži web</string>
+ <!-- Content description (not visible, for screen readers etc.): Voice search -->
+ <string name="search_widget_voice">Glasovna pretraga</string>
+</resources>
diff --git a/mobile/android/android-components/components/feature/search/src/main/res/values-ca/strings.xml b/mobile/android/android-components/components/feature/search/src/main/res/values-ca/strings.xml
new file mode 100644
index 0000000000..1821b2b9f4
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/res/values-ca/strings.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Search Widget -->
+ <!-- Content description for searching with a widget. The first parameter is the name of the application.-->
+ <string name="search_widget_content_description">Obre en una pestanya nova en %1$s</string>
+ <!-- Text preview for smaller sized widgets -->
+ <string name="search_widget_text_short">Cerca</string>
+ <!-- Text preview for larger sized widgets -->
+ <string name="search_widget_text_long">Cerca al web</string>
+ <!-- Content description (not visible, for screen readers etc.): Voice search -->
+ <string name="search_widget_voice">Cerca per veu</string>
+</resources>
diff --git a/mobile/android/android-components/components/feature/search/src/main/res/values-cak/strings.xml b/mobile/android/android-components/components/feature/search/src/main/res/values-cak/strings.xml
new file mode 100644
index 0000000000..c4630b9637
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/res/values-cak/strings.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Search Widget -->
+ <!-- Content description for searching with a widget. The first parameter is the name of the application.-->
+ <string name="search_widget_content_description">Tijaq jun k\'ak\'a\' %1$s ruwi\'</string>
+ <!-- Text preview for smaller sized widgets -->
+ <string name="search_widget_text_short">Tikanöx</string>
+ <!-- Text preview for larger sized widgets -->
+ <string name="search_widget_text_long">Tikanöx pan ajk\'amaya\'l</string>
+ <!-- Content description (not visible, for screen readers etc.): Voice search -->
+ <string name="search_widget_voice">Tikanöx chi ch\'ab\'äl</string>
+</resources>
diff --git a/mobile/android/android-components/components/feature/search/src/main/res/values-ckb/strings.xml b/mobile/android/android-components/components/feature/search/src/main/res/values-ckb/strings.xml
new file mode 100644
index 0000000000..4f31f2232f
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/res/values-ckb/strings.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Search Widget -->
+ <!-- Content description for searching with a widget. The first parameter is the name of the application.-->
+ <string name="search_widget_content_description">بازدەرێکی %1$sی نوێ بکەرەوە</string>
+ <!-- Text preview for smaller sized widgets -->
+ <string name="search_widget_text_short">گەڕان</string>
+ <!-- Text preview for larger sized widgets -->
+ <string name="search_widget_text_long">بە وێبدا بگەڕێ</string>
+ <!-- Content description (not visible, for screen readers etc.): Voice search -->
+ <string name="search_widget_voice">گەڕانی دەنگی</string>
+</resources>
diff --git a/mobile/android/android-components/components/feature/search/src/main/res/values-co/strings.xml b/mobile/android/android-components/components/feature/search/src/main/res/values-co/strings.xml
new file mode 100644
index 0000000000..a38dd9e634
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/res/values-co/strings.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Search Widget -->
+ <!-- Content description for searching with a widget. The first parameter is the name of the application.-->
+ <string name="search_widget_content_description">Apre una nova unghjetta in %1$s</string>
+ <!-- Text preview for smaller sized widgets -->
+ <string name="search_widget_text_short">Ricercà</string>
+ <!-- Text preview for larger sized widgets -->
+ <string name="search_widget_text_long">Ricercà nant’à u web</string>
+ <!-- Content description (not visible, for screen readers etc.): Voice search -->
+ <string name="search_widget_voice">Ricerca vucale</string>
+</resources>
diff --git a/mobile/android/android-components/components/feature/search/src/main/res/values-cs/strings.xml b/mobile/android/android-components/components/feature/search/src/main/res/values-cs/strings.xml
new file mode 100644
index 0000000000..b889d8f9a6
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/res/values-cs/strings.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Search Widget -->
+ <!-- Content description for searching with a widget. The first parameter is the name of the application.-->
+ <string name="search_widget_content_description">Otevřít nový panel v aplikaci %1$s</string>
+ <!-- Text preview for smaller sized widgets -->
+ <string name="search_widget_text_short">Hledat</string>
+ <!-- Text preview for larger sized widgets -->
+ <string name="search_widget_text_long">Vyhledat na webu</string>
+ <!-- Content description (not visible, for screen readers etc.): Voice search -->
+ <string name="search_widget_voice">Hlasové vyhledávání</string>
+</resources>
diff --git a/mobile/android/android-components/components/feature/search/src/main/res/values-cy/strings.xml b/mobile/android/android-components/components/feature/search/src/main/res/values-cy/strings.xml
new file mode 100644
index 0000000000..5c8f73d4bc
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/res/values-cy/strings.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Search Widget -->
+ <!-- Content description for searching with a widget. The first parameter is the name of the application.-->
+ <string name="search_widget_content_description">Agor tab %1$s newydd</string>
+ <!-- Text preview for smaller sized widgets -->
+ <string name="search_widget_text_short">Chwilio</string>
+ <!-- Text preview for larger sized widgets -->
+ <string name="search_widget_text_long">Chwilio’r we</string>
+ <!-- Content description (not visible, for screen readers etc.): Voice search -->
+ <string name="search_widget_voice">Chwilio llais</string>
+</resources>
diff --git a/mobile/android/android-components/components/feature/search/src/main/res/values-da/strings.xml b/mobile/android/android-components/components/feature/search/src/main/res/values-da/strings.xml
new file mode 100644
index 0000000000..a8af438d90
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/res/values-da/strings.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Search Widget -->
+ <!-- Content description for searching with a widget. The first parameter is the name of the application.-->
+ <string name="search_widget_content_description">Åbn et nyt %1$s-faneblad</string>
+ <!-- Text preview for smaller sized widgets -->
+ <string name="search_widget_text_short">Søg</string>
+ <!-- Text preview for larger sized widgets -->
+ <string name="search_widget_text_long">Søg på nettet</string>
+ <!-- Content description (not visible, for screen readers etc.): Voice search -->
+ <string name="search_widget_voice">Stemme-søgning</string>
+</resources>
diff --git a/mobile/android/android-components/components/feature/search/src/main/res/values-de/strings.xml b/mobile/android/android-components/components/feature/search/src/main/res/values-de/strings.xml
new file mode 100644
index 0000000000..0b98201168
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/res/values-de/strings.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Search Widget -->
+ <!-- Content description for searching with a widget. The first parameter is the name of the application.-->
+ <string name="search_widget_content_description">Neuen %1$s-Tab öffnen</string>
+ <!-- Text preview for smaller sized widgets -->
+ <string name="search_widget_text_short">Suche</string>
+ <!-- Text preview for larger sized widgets -->
+ <string name="search_widget_text_long">Das Web durchsuchen</string>
+ <!-- Content description (not visible, for screen readers etc.): Voice search -->
+ <string name="search_widget_voice">Sprachsuche</string>
+</resources>
diff --git a/mobile/android/android-components/components/feature/search/src/main/res/values-dsb/strings.xml b/mobile/android/android-components/components/feature/search/src/main/res/values-dsb/strings.xml
new file mode 100644
index 0000000000..c5b19b7f83
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/res/values-dsb/strings.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Search Widget -->
+ <!-- Content description for searching with a widget. The first parameter is the name of the application.-->
+ <string name="search_widget_content_description">Nowy rejtarik %1$s wócyniś</string>
+ <!-- Text preview for smaller sized widgets -->
+ <string name="search_widget_text_short">Pytaś</string>
+ <!-- Text preview for larger sized widgets -->
+ <string name="search_widget_text_long">Web pśepytaś</string>
+ <!-- Content description (not visible, for screen readers etc.): Voice search -->
+ <string name="search_widget_voice">Głosowe pytanje</string>
+</resources>
diff --git a/mobile/android/android-components/components/feature/search/src/main/res/values-el/strings.xml b/mobile/android/android-components/components/feature/search/src/main/res/values-el/strings.xml
new file mode 100644
index 0000000000..d5ef9aeb67
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/res/values-el/strings.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Search Widget -->
+ <!-- Content description for searching with a widget. The first parameter is the name of the application.-->
+ <string name="search_widget_content_description">Άνοιγμα νέας καρτέλας %1$s</string>
+ <!-- Text preview for smaller sized widgets -->
+ <string name="search_widget_text_short">Αναζήτηση</string>
+ <!-- Text preview for larger sized widgets -->
+ <string name="search_widget_text_long">Αναζήτηση στο διαδίκτυο</string>
+ <!-- Content description (not visible, for screen readers etc.): Voice search -->
+ <string name="search_widget_voice">Φωνητική αναζήτηση</string>
+</resources>
diff --git a/mobile/android/android-components/components/feature/search/src/main/res/values-en-rCA/strings.xml b/mobile/android/android-components/components/feature/search/src/main/res/values-en-rCA/strings.xml
new file mode 100644
index 0000000000..93a653aed7
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/res/values-en-rCA/strings.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Search Widget -->
+ <!-- Content description for searching with a widget. The first parameter is the name of the application.-->
+ <string name="search_widget_content_description">Open a new %1$s tab</string>
+ <!-- Text preview for smaller sized widgets -->
+ <string name="search_widget_text_short">Search</string>
+ <!-- Text preview for larger sized widgets -->
+ <string name="search_widget_text_long">Search the web</string>
+ <!-- Content description (not visible, for screen readers etc.): Voice search -->
+ <string name="search_widget_voice">Voice search</string>
+</resources>
diff --git a/mobile/android/android-components/components/feature/search/src/main/res/values-en-rGB/strings.xml b/mobile/android/android-components/components/feature/search/src/main/res/values-en-rGB/strings.xml
new file mode 100644
index 0000000000..93a653aed7
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/res/values-en-rGB/strings.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Search Widget -->
+ <!-- Content description for searching with a widget. The first parameter is the name of the application.-->
+ <string name="search_widget_content_description">Open a new %1$s tab</string>
+ <!-- Text preview for smaller sized widgets -->
+ <string name="search_widget_text_short">Search</string>
+ <!-- Text preview for larger sized widgets -->
+ <string name="search_widget_text_long">Search the web</string>
+ <!-- Content description (not visible, for screen readers etc.): Voice search -->
+ <string name="search_widget_voice">Voice search</string>
+</resources>
diff --git a/mobile/android/android-components/components/feature/search/src/main/res/values-eo/strings.xml b/mobile/android/android-components/components/feature/search/src/main/res/values-eo/strings.xml
new file mode 100644
index 0000000000..5ab8dc03ec
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/res/values-eo/strings.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Search Widget -->
+ <!-- Content description for searching with a widget. The first parameter is the name of the application.-->
+ <string name="search_widget_content_description">Malfermi novan langeton de %1$s</string>
+ <!-- Text preview for smaller sized widgets -->
+ <string name="search_widget_text_short">Serĉi</string>
+ <!-- Text preview for larger sized widgets -->
+ <string name="search_widget_text_long">Serĉi en la reto</string>
+ <!-- Content description (not visible, for screen readers etc.): Voice search -->
+ <string name="search_widget_voice">Voĉa serĉo</string>
+</resources>
diff --git a/mobile/android/android-components/components/feature/search/src/main/res/values-es-rAR/strings.xml b/mobile/android/android-components/components/feature/search/src/main/res/values-es-rAR/strings.xml
new file mode 100644
index 0000000000..f68109e762
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/res/values-es-rAR/strings.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Search Widget -->
+ <!-- Content description for searching with a widget. The first parameter is the name of the application.-->
+ <string name="search_widget_content_description">Abrir una nueva pestaña de %1$s</string>
+ <!-- Text preview for smaller sized widgets -->
+ <string name="search_widget_text_short">Buscar</string>
+ <!-- Text preview for larger sized widgets -->
+ <string name="search_widget_text_long">Buscar en la web</string>
+ <!-- Content description (not visible, for screen readers etc.): Voice search -->
+ <string name="search_widget_voice">Búsqueda por voz</string>
+</resources>
diff --git a/mobile/android/android-components/components/feature/search/src/main/res/values-es-rCL/strings.xml b/mobile/android/android-components/components/feature/search/src/main/res/values-es-rCL/strings.xml
new file mode 100644
index 0000000000..f68109e762
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/res/values-es-rCL/strings.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Search Widget -->
+ <!-- Content description for searching with a widget. The first parameter is the name of the application.-->
+ <string name="search_widget_content_description">Abrir una nueva pestaña de %1$s</string>
+ <!-- Text preview for smaller sized widgets -->
+ <string name="search_widget_text_short">Buscar</string>
+ <!-- Text preview for larger sized widgets -->
+ <string name="search_widget_text_long">Buscar en la web</string>
+ <!-- Content description (not visible, for screen readers etc.): Voice search -->
+ <string name="search_widget_voice">Búsqueda por voz</string>
+</resources>
diff --git a/mobile/android/android-components/components/feature/search/src/main/res/values-es-rES/strings.xml b/mobile/android/android-components/components/feature/search/src/main/res/values-es-rES/strings.xml
new file mode 100644
index 0000000000..60b93ee599
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/res/values-es-rES/strings.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Search Widget -->
+ <!-- Content description for searching with a widget. The first parameter is the name of the application.-->
+ <string name="search_widget_content_description">Abrir una pestaña nueva de %1$s</string>
+ <!-- Text preview for smaller sized widgets -->
+ <string name="search_widget_text_short">Buscar</string>
+ <!-- Text preview for larger sized widgets -->
+ <string name="search_widget_text_long">Buscar en la web</string>
+ <!-- Content description (not visible, for screen readers etc.): Voice search -->
+ <string name="search_widget_voice">Búsqueda por voz</string>
+</resources>
diff --git a/mobile/android/android-components/components/feature/search/src/main/res/values-es-rMX/strings.xml b/mobile/android/android-components/components/feature/search/src/main/res/values-es-rMX/strings.xml
new file mode 100644
index 0000000000..3fb6e2091c
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/res/values-es-rMX/strings.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Search Widget -->
+ <!-- Content description for searching with a widget. The first parameter is the name of the application.-->
+ <string name="search_widget_content_description">Abrir una nueva pestaña en %1$s</string>
+ <!-- Text preview for smaller sized widgets -->
+ <string name="search_widget_text_short">Buscar</string>
+ <!-- Text preview for larger sized widgets -->
+ <string name="search_widget_text_long">Buscar en la web</string>
+ <!-- Content description (not visible, for screen readers etc.): Voice search -->
+ <string name="search_widget_voice">Búsqueda por voz</string>
+</resources>
diff --git a/mobile/android/android-components/components/feature/search/src/main/res/values-es/strings.xml b/mobile/android/android-components/components/feature/search/src/main/res/values-es/strings.xml
new file mode 100644
index 0000000000..60b93ee599
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/res/values-es/strings.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Search Widget -->
+ <!-- Content description for searching with a widget. The first parameter is the name of the application.-->
+ <string name="search_widget_content_description">Abrir una pestaña nueva de %1$s</string>
+ <!-- Text preview for smaller sized widgets -->
+ <string name="search_widget_text_short">Buscar</string>
+ <!-- Text preview for larger sized widgets -->
+ <string name="search_widget_text_long">Buscar en la web</string>
+ <!-- Content description (not visible, for screen readers etc.): Voice search -->
+ <string name="search_widget_voice">Búsqueda por voz</string>
+</resources>
diff --git a/mobile/android/android-components/components/feature/search/src/main/res/values-et/strings.xml b/mobile/android/android-components/components/feature/search/src/main/res/values-et/strings.xml
new file mode 100644
index 0000000000..077b8a047c
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/res/values-et/strings.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Search Widget -->
+ <!-- Content description for searching with a widget. The first parameter is the name of the application.-->
+ <string name="search_widget_content_description">Ava uus kaart %1$sis</string>
+ <!-- Text preview for smaller sized widgets -->
+ <string name="search_widget_text_short">Otsing</string>
+ <!-- Text preview for larger sized widgets -->
+ <string name="search_widget_text_long">Otsi veebist</string>
+ <!-- Content description (not visible, for screen readers etc.): Voice search -->
+ <string name="search_widget_voice">Häälotsing</string>
+</resources>
diff --git a/mobile/android/android-components/components/feature/search/src/main/res/values-eu/strings.xml b/mobile/android/android-components/components/feature/search/src/main/res/values-eu/strings.xml
new file mode 100644
index 0000000000..9550d75f1f
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/res/values-eu/strings.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Search Widget -->
+ <!-- Content description for searching with a widget. The first parameter is the name of the application.-->
+ <string name="search_widget_content_description">Ireki %1$s fitxa berria</string>
+ <!-- Text preview for smaller sized widgets -->
+ <string name="search_widget_text_short">Bilatu</string>
+ <!-- Text preview for larger sized widgets -->
+ <string name="search_widget_text_long">Bilatu webean</string>
+ <!-- Content description (not visible, for screen readers etc.): Voice search -->
+ <string name="search_widget_voice">Ahots bidezko bilaketa</string>
+</resources>
diff --git a/mobile/android/android-components/components/feature/search/src/main/res/values-fa/strings.xml b/mobile/android/android-components/components/feature/search/src/main/res/values-fa/strings.xml
new file mode 100644
index 0000000000..9c2489d604
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/res/values-fa/strings.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Search Widget -->
+ <!-- Content description for searching with a widget. The first parameter is the name of the application.-->
+ <string name="search_widget_content_description">گشودن یک زبانهٔ جدید %1$s</string>
+ <!-- Text preview for smaller sized widgets -->
+ <string name="search_widget_text_short">جست‌وجو</string>
+ <!-- Text preview for larger sized widgets -->
+ <string name="search_widget_text_long">جست‌وجوی وب</string>
+ <!-- Content description (not visible, for screen readers etc.): Voice search -->
+ <string name="search_widget_voice">جست‌وجوی صوتی</string>
+</resources>
diff --git a/mobile/android/android-components/components/feature/search/src/main/res/values-ff/strings.xml b/mobile/android/android-components/components/feature/search/src/main/res/values-ff/strings.xml
new file mode 100644
index 0000000000..c22e74b613
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/res/values-ff/strings.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Search Widget -->
+ <!-- Content description for searching with a widget. The first parameter is the name of the application.-->
+ <string name="search_widget_content_description">Uddit tabbere hesre %1$s</string>
+ <!-- Content description (not visible, for screen readers etc.): Voice search -->
+ <string name="search_widget_voice">Njiilaw sawto</string>
+</resources>
diff --git a/mobile/android/android-components/components/feature/search/src/main/res/values-fi/strings.xml b/mobile/android/android-components/components/feature/search/src/main/res/values-fi/strings.xml
new file mode 100644
index 0000000000..ab054f5e6e
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/res/values-fi/strings.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Search Widget -->
+ <!-- Content description for searching with a widget. The first parameter is the name of the application.-->
+ <string name="search_widget_content_description">Avaa uusi %1$s-välilehti</string>
+ <!-- Text preview for smaller sized widgets -->
+ <string name="search_widget_text_short">Hae</string>
+ <!-- Text preview for larger sized widgets -->
+ <string name="search_widget_text_long">Hae verkosta</string>
+ <!-- Content description (not visible, for screen readers etc.): Voice search -->
+ <string name="search_widget_voice">Äänihaku</string>
+</resources>
diff --git a/mobile/android/android-components/components/feature/search/src/main/res/values-fr/strings.xml b/mobile/android/android-components/components/feature/search/src/main/res/values-fr/strings.xml
new file mode 100644
index 0000000000..4785d484bd
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/res/values-fr/strings.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Search Widget -->
+ <!-- Content description for searching with a widget. The first parameter is the name of the application.-->
+ <string name="search_widget_content_description">Ouvrir un nouvel onglet %1$s</string>
+ <!-- Text preview for smaller sized widgets -->
+ <string name="search_widget_text_short">Rechercher</string>
+ <!-- Text preview for larger sized widgets -->
+ <string name="search_widget_text_long">Rechercher sur le Web</string>
+ <!-- Content description (not visible, for screen readers etc.): Voice search -->
+ <string name="search_widget_voice">Recherche vocale</string>
+</resources>
diff --git a/mobile/android/android-components/components/feature/search/src/main/res/values-fur/strings.xml b/mobile/android/android-components/components/feature/search/src/main/res/values-fur/strings.xml
new file mode 100644
index 0000000000..29ec17dd5b
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/res/values-fur/strings.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Search Widget -->
+ <!-- Content description for searching with a widget. The first parameter is the name of the application.-->
+ <string name="search_widget_content_description">Vierç intune gnove schede in %1$s</string>
+ <!-- Text preview for smaller sized widgets -->
+ <string name="search_widget_text_short">Cîr</string>
+ <!-- Text preview for larger sized widgets -->
+ <string name="search_widget_text_long">Cîr tal web</string>
+ <!-- Content description (not visible, for screen readers etc.): Voice search -->
+ <string name="search_widget_voice">Ricercje vocâl</string>
+</resources>
diff --git a/mobile/android/android-components/components/feature/search/src/main/res/values-fy-rNL/strings.xml b/mobile/android/android-components/components/feature/search/src/main/res/values-fy-rNL/strings.xml
new file mode 100644
index 0000000000..3fd2614b8a
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/res/values-fy-rNL/strings.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Search Widget -->
+ <!-- Content description for searching with a widget. The first parameter is the name of the application.-->
+ <string name="search_widget_content_description">In nij %1$s-ljepblêd iepenje</string>
+ <!-- Text preview for smaller sized widgets -->
+ <string name="search_widget_text_short">Sykje</string>
+ <!-- Text preview for larger sized widgets -->
+ <string name="search_widget_text_long">Sykje op it web</string>
+ <!-- Content description (not visible, for screen readers etc.): Voice search -->
+ <string name="search_widget_voice">Sprutsen sykopdracht</string>
+</resources>
diff --git a/mobile/android/android-components/components/feature/search/src/main/res/values-gd/strings.xml b/mobile/android/android-components/components/feature/search/src/main/res/values-gd/strings.xml
new file mode 100644
index 0000000000..9bf121ff5c
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/res/values-gd/strings.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Search Widget -->
+ <!-- Content description for searching with a widget. The first parameter is the name of the application.-->
+ <string name="search_widget_content_description">Fosgail taba %1$s ùr</string>
+ <!-- Text preview for smaller sized widgets -->
+ <string name="search_widget_text_short">Lorg</string>
+ <!-- Text preview for larger sized widgets -->
+ <string name="search_widget_text_long">Lorg air an lìon</string>
+ <!-- Content description (not visible, for screen readers etc.): Voice search -->
+ <string name="search_widget_voice">Lorg-gutha</string>
+</resources>
diff --git a/mobile/android/android-components/components/feature/search/src/main/res/values-gl/strings.xml b/mobile/android/android-components/components/feature/search/src/main/res/values-gl/strings.xml
new file mode 100644
index 0000000000..3915de9a04
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/res/values-gl/strings.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Search Widget -->
+ <!-- Content description for searching with a widget. The first parameter is the name of the application.-->
+ <string name="search_widget_content_description">Abrir unha nova lapela en %1$s</string>
+ <!-- Text preview for smaller sized widgets -->
+ <string name="search_widget_text_short">Buscar</string>
+ <!-- Text preview for larger sized widgets -->
+ <string name="search_widget_text_long">Buscar na web</string>
+ <!-- Content description (not visible, for screen readers etc.): Voice search -->
+ <string name="search_widget_voice">Busca por voz</string>
+</resources>
diff --git a/mobile/android/android-components/components/feature/search/src/main/res/values-gn/strings.xml b/mobile/android/android-components/components/feature/search/src/main/res/values-gn/strings.xml
new file mode 100644
index 0000000000..7dc6496f36
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/res/values-gn/strings.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Search Widget -->
+ <!-- Content description for searching with a widget. The first parameter is the name of the application.-->
+ <string name="search_widget_content_description">Embojuruja tendayke pyahu %1$s-pe</string>
+ <!-- Text preview for smaller sized widgets -->
+ <string name="search_widget_text_short">Heka</string>
+ <!-- Text preview for larger sized widgets -->
+ <string name="search_widget_text_long">Eheka ñandutípe</string>
+ <!-- Content description (not visible, for screen readers etc.): Voice search -->
+ <string name="search_widget_voice">Ayvu rupi jeheka</string>
+</resources>
diff --git a/mobile/android/android-components/components/feature/search/src/main/res/values-hr/strings.xml b/mobile/android/android-components/components/feature/search/src/main/res/values-hr/strings.xml
new file mode 100644
index 0000000000..a5a05a0f6a
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/res/values-hr/strings.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Search Widget -->
+ <!-- Content description for searching with a widget. The first parameter is the name of the application.-->
+ <string name="search_widget_content_description">Otvori novu %1$s karticu</string>
+ <!-- Text preview for smaller sized widgets -->
+ <string name="search_widget_text_short">Traži</string>
+ <!-- Text preview for larger sized widgets -->
+ <string name="search_widget_text_long">Pretraži web</string>
+ <!-- Content description (not visible, for screen readers etc.): Voice search -->
+ <string name="search_widget_voice">Glasovno pretraživanje</string>
+</resources>
diff --git a/mobile/android/android-components/components/feature/search/src/main/res/values-hsb/strings.xml b/mobile/android/android-components/components/feature/search/src/main/res/values-hsb/strings.xml
new file mode 100644
index 0000000000..56a86b500b
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/res/values-hsb/strings.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Search Widget -->
+ <!-- Content description for searching with a widget. The first parameter is the name of the application.-->
+ <string name="search_widget_content_description">Nowy rajtark %1$s wočinić</string>
+ <!-- Text preview for smaller sized widgets -->
+ <string name="search_widget_text_short">Pytać</string>
+ <!-- Text preview for larger sized widgets -->
+ <string name="search_widget_text_long">Web přepytać</string>
+ <!-- Content description (not visible, for screen readers etc.): Voice search -->
+ <string name="search_widget_voice">Hłosowe pytanje</string>
+</resources>
diff --git a/mobile/android/android-components/components/feature/search/src/main/res/values-hu/strings.xml b/mobile/android/android-components/components/feature/search/src/main/res/values-hu/strings.xml
new file mode 100644
index 0000000000..ec925efad6
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/res/values-hu/strings.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Search Widget -->
+ <!-- Content description for searching with a widget. The first parameter is the name of the application.-->
+ <string name="search_widget_content_description">Új %1$s lap megnyitása</string>
+ <!-- Text preview for smaller sized widgets -->
+ <string name="search_widget_text_short">Keresés</string>
+ <!-- Text preview for larger sized widgets -->
+ <string name="search_widget_text_long">Keresés a weben</string>
+ <!-- Content description (not visible, for screen readers etc.): Voice search -->
+ <string name="search_widget_voice">Hangalapú keresés</string>
+</resources>
diff --git a/mobile/android/android-components/components/feature/search/src/main/res/values-hy-rAM/strings.xml b/mobile/android/android-components/components/feature/search/src/main/res/values-hy-rAM/strings.xml
new file mode 100644
index 0000000000..c069279db8
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/res/values-hy-rAM/strings.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Search Widget -->
+ <!-- Content description for searching with a widget. The first parameter is the name of the application.-->
+ <string name="search_widget_content_description">Բացել նոր %1$s ներդիր</string>
+ <!-- Text preview for smaller sized widgets -->
+ <string name="search_widget_text_short">Որոնում</string>
+ <!-- Text preview for larger sized widgets -->
+ <string name="search_widget_text_long">Որոնել համացանցում</string>
+ <!-- Content description (not visible, for screen readers etc.): Voice search -->
+ <string name="search_widget_voice">Ձայնային որոնում</string>
+</resources>
diff --git a/mobile/android/android-components/components/feature/search/src/main/res/values-ia/strings.xml b/mobile/android/android-components/components/feature/search/src/main/res/values-ia/strings.xml
new file mode 100644
index 0000000000..89c47c731e
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/res/values-ia/strings.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Search Widget -->
+ <!-- Content description for searching with a widget. The first parameter is the name of the application.-->
+ <string name="search_widget_content_description">Aperir un nove scheda %1$s</string>
+ <!-- Text preview for smaller sized widgets -->
+ <string name="search_widget_text_short">Cercar</string>
+ <!-- Text preview for larger sized widgets -->
+ <string name="search_widget_text_long">Cercar in le web</string>
+ <!-- Content description (not visible, for screen readers etc.): Voice search -->
+ <string name="search_widget_voice">Recerca vocal</string>
+</resources>
diff --git a/mobile/android/android-components/components/feature/search/src/main/res/values-in/strings.xml b/mobile/android/android-components/components/feature/search/src/main/res/values-in/strings.xml
new file mode 100644
index 0000000000..19650ec7ec
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/res/values-in/strings.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Search Widget -->
+ <!-- Content description for searching with a widget. The first parameter is the name of the application.-->
+ <string name="search_widget_content_description">Buka di tab %1$s baru</string>
+ <!-- Text preview for smaller sized widgets -->
+ <string name="search_widget_text_short">Cari</string>
+ <!-- Text preview for larger sized widgets -->
+ <string name="search_widget_text_long">Cari di Web</string>
+ <!-- Content description (not visible, for screen readers etc.): Voice search -->
+ <string name="search_widget_voice">Pencarian suara</string>
+</resources>
diff --git a/mobile/android/android-components/components/feature/search/src/main/res/values-is/strings.xml b/mobile/android/android-components/components/feature/search/src/main/res/values-is/strings.xml
new file mode 100644
index 0000000000..ba5965b35c
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/res/values-is/strings.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Search Widget -->
+ <!-- Content description for searching with a widget. The first parameter is the name of the application.-->
+ <string name="search_widget_content_description">Opna nýjan %1$s-flipa</string>
+ <!-- Text preview for smaller sized widgets -->
+ <string name="search_widget_text_short">Leita</string>
+ <!-- Text preview for larger sized widgets -->
+ <string name="search_widget_text_long">Leita á vefnum</string>
+ <!-- Content description (not visible, for screen readers etc.): Voice search -->
+ <string name="search_widget_voice">Raddleit</string>
+</resources>
diff --git a/mobile/android/android-components/components/feature/search/src/main/res/values-it/strings.xml b/mobile/android/android-components/components/feature/search/src/main/res/values-it/strings.xml
new file mode 100644
index 0000000000..ccc30fb548
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/res/values-it/strings.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Search Widget -->
+ <!-- Content description for searching with a widget. The first parameter is the name of the application.-->
+ <string name="search_widget_content_description">Apri una nuova scheda in %1$s</string>
+ <!-- Text preview for smaller sized widgets -->
+ <string name="search_widget_text_short">Cerca</string>
+ <!-- Text preview for larger sized widgets -->
+ <string name="search_widget_text_long">Cerca sul Web</string>
+ <!-- Content description (not visible, for screen readers etc.): Voice search -->
+ <string name="search_widget_voice">Ricerca vocale</string>
+</resources>
diff --git a/mobile/android/android-components/components/feature/search/src/main/res/values-iw/strings.xml b/mobile/android/android-components/components/feature/search/src/main/res/values-iw/strings.xml
new file mode 100644
index 0000000000..cb0f9346ac
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/res/values-iw/strings.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Search Widget -->
+ <!-- Content description for searching with a widget. The first parameter is the name of the application.-->
+ <string name="search_widget_content_description">פתיחת לשונית %1$s חדשה</string>
+ <!-- Text preview for smaller sized widgets -->
+ <string name="search_widget_text_short">חיפוש</string>
+ <!-- Text preview for larger sized widgets -->
+ <string name="search_widget_text_long">חיפוש ברשת</string>
+ <!-- Content description (not visible, for screen readers etc.): Voice search -->
+ <string name="search_widget_voice">חיפוש קולי</string>
+</resources>
diff --git a/mobile/android/android-components/components/feature/search/src/main/res/values-ja/strings.xml b/mobile/android/android-components/components/feature/search/src/main/res/values-ja/strings.xml
new file mode 100644
index 0000000000..bc9d0bf5b9
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/res/values-ja/strings.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Search Widget -->
+ <!-- Content description for searching with a widget. The first parameter is the name of the application.-->
+ <string name="search_widget_content_description">%1$s の新しいタブで開く</string>
+ <!-- Text preview for smaller sized widgets -->
+ <string name="search_widget_text_short">検索</string>
+ <!-- Text preview for larger sized widgets -->
+ <string name="search_widget_text_long">ウェブを検索</string>
+ <!-- Content description (not visible, for screen readers etc.): Voice search -->
+ <string name="search_widget_voice">音声検索</string>
+</resources>
diff --git a/mobile/android/android-components/components/feature/search/src/main/res/values-ka/strings.xml b/mobile/android/android-components/components/feature/search/src/main/res/values-ka/strings.xml
new file mode 100644
index 0000000000..e815df0a74
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/res/values-ka/strings.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Search Widget -->
+ <!-- Content description for searching with a widget. The first parameter is the name of the application.-->
+ <string name="search_widget_content_description">ახალი %1$s-ჩანართის გახსნა</string>
+ <!-- Text preview for smaller sized widgets -->
+ <string name="search_widget_text_short">მოიძიეთ</string>
+ <!-- Text preview for larger sized widgets -->
+ <string name="search_widget_text_long">მოიძიეთ ინტერნეტში</string>
+ <!-- Content description (not visible, for screen readers etc.): Voice search -->
+ <string name="search_widget_voice">ხმოვანი ძიება</string>
+</resources>
diff --git a/mobile/android/android-components/components/feature/search/src/main/res/values-kaa/strings.xml b/mobile/android/android-components/components/feature/search/src/main/res/values-kaa/strings.xml
new file mode 100644
index 0000000000..e968e33430
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/res/values-kaa/strings.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Search Widget -->
+ <!-- Content description for searching with a widget. The first parameter is the name of the application.-->
+ <string name="search_widget_content_description">Jańa%1$sbetin ashıw</string>
+ <!-- Text preview for smaller sized widgets -->
+ <string name="search_widget_text_short">Izlew</string>
+ <!-- Text preview for larger sized widgets -->
+ <string name="search_widget_text_long">Internetten izlew</string>
+ <!-- Content description (not visible, for screen readers etc.): Voice search -->
+ <string name="search_widget_voice">Dawıslı izlew</string>
+</resources>
diff --git a/mobile/android/android-components/components/feature/search/src/main/res/values-kab/strings.xml b/mobile/android/android-components/components/feature/search/src/main/res/values-kab/strings.xml
new file mode 100644
index 0000000000..db660eeff2
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/res/values-kab/strings.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Search Widget -->
+ <!-- Content description for searching with a widget. The first parameter is the name of the application.-->
+ <string name="search_widget_content_description">Ldi-t iccer amaynut %1$s</string>
+ <!-- Text preview for smaller sized widgets -->
+ <string name="search_widget_text_short">Nadi</string>
+ <!-- Text preview for larger sized widgets -->
+ <string name="search_widget_text_long">Nadi di web</string>
+ <!-- Content description (not visible, for screen readers etc.): Voice search -->
+ <string name="search_widget_voice">Anadi aɣectan</string>
+</resources>
diff --git a/mobile/android/android-components/components/feature/search/src/main/res/values-kk/strings.xml b/mobile/android/android-components/components/feature/search/src/main/res/values-kk/strings.xml
new file mode 100644
index 0000000000..bd9f756463
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/res/values-kk/strings.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Search Widget -->
+ <!-- Content description for searching with a widget. The first parameter is the name of the application.-->
+ <string name="search_widget_content_description">Жаңа %1$s бетін ашу</string>
+ <!-- Text preview for smaller sized widgets -->
+ <string name="search_widget_text_short">Іздеу</string>
+ <!-- Text preview for larger sized widgets -->
+ <string name="search_widget_text_long">Интернетте іздеу</string>
+ <!-- Content description (not visible, for screen readers etc.): Voice search -->
+ <string name="search_widget_voice">Дауыстық іздеу</string>
+</resources>
diff --git a/mobile/android/android-components/components/feature/search/src/main/res/values-kmr/strings.xml b/mobile/android/android-components/components/feature/search/src/main/res/values-kmr/strings.xml
new file mode 100644
index 0000000000..6c7ebf5a20
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/res/values-kmr/strings.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Search Widget -->
+ <!-- Content description for searching with a widget. The first parameter is the name of the application.-->
+ <string name="search_widget_content_description">Hilpekînek nû ya %1$s `ê veke</string>
+ <!-- Text preview for smaller sized widgets -->
+ <string name="search_widget_text_short">Lêgerîn</string>
+ <!-- Text preview for larger sized widgets -->
+ <string name="search_widget_text_long">Di webê de bigere</string>
+ <!-- Content description (not visible, for screen readers etc.): Voice search -->
+ <string name="search_widget_voice">Lêgerîna dengî</string>
+</resources>
diff --git a/mobile/android/android-components/components/feature/search/src/main/res/values-ko/strings.xml b/mobile/android/android-components/components/feature/search/src/main/res/values-ko/strings.xml
new file mode 100644
index 0000000000..65c8238a99
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/res/values-ko/strings.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Search Widget -->
+ <!-- Content description for searching with a widget. The first parameter is the name of the application.-->
+ <string name="search_widget_content_description">새 %1$s 탭 열기</string>
+ <!-- Text preview for smaller sized widgets -->
+ <string name="search_widget_text_short">검색</string>
+ <!-- Text preview for larger sized widgets -->
+ <string name="search_widget_text_long">웹 검색</string>
+ <!-- Content description (not visible, for screen readers etc.): Voice search -->
+ <string name="search_widget_voice">음성 검색</string>
+</resources>
diff --git a/mobile/android/android-components/components/feature/search/src/main/res/values-lo/strings.xml b/mobile/android/android-components/components/feature/search/src/main/res/values-lo/strings.xml
new file mode 100644
index 0000000000..119d048839
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/res/values-lo/strings.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Search Widget -->
+ <!-- Content description for searching with a widget. The first parameter is the name of the application.-->
+ <string name="search_widget_content_description">ເປີດແຖບ %1$s ໃໝ່</string>
+ <!-- Text preview for smaller sized widgets -->
+ <string name="search_widget_text_short">ຄົ້ນຫາ</string>
+ <!-- Text preview for larger sized widgets -->
+ <string name="search_widget_text_long">ຄົ້ນຫາເວັບໄຊທ</string>
+ <!-- Content description (not visible, for screen readers etc.): Voice search -->
+ <string name="search_widget_voice">ຄົ້ນຫາດ້ວຍສຽງ</string>
+</resources>
diff --git a/mobile/android/android-components/components/feature/search/src/main/res/values-lt/strings.xml b/mobile/android/android-components/components/feature/search/src/main/res/values-lt/strings.xml
new file mode 100644
index 0000000000..6387d888d2
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/res/values-lt/strings.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Search Widget -->
+ <!-- Content description for searching with a widget. The first parameter is the name of the application.-->
+ <string name="search_widget_content_description">Atverti naują „%1$s“ kortelę</string>
+ <!-- Text preview for smaller sized widgets -->
+ <string name="search_widget_text_short">Ieškoti</string>
+ <!-- Text preview for larger sized widgets -->
+ <string name="search_widget_text_long">Ieškokite internete</string>
+ <!-- Content description (not visible, for screen readers etc.): Voice search -->
+ <string name="search_widget_voice">Paieška balsu</string>
+</resources>
diff --git a/mobile/android/android-components/components/feature/search/src/main/res/values-my/strings.xml b/mobile/android/android-components/components/feature/search/src/main/res/values-my/strings.xml
new file mode 100644
index 0000000000..4b497f553d
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/res/values-my/strings.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Search Widget -->
+ <!-- Content description for searching with a widget. The first parameter is the name of the application.-->
+ <string name="search_widget_content_description">တပ်ဘ်%1$s အသစ်ဖွင့်မည်</string>
+ <!-- Text preview for smaller sized widgets -->
+ <string name="search_widget_text_short">ရှာဖွေမည်</string>
+ <!-- Text preview for larger sized widgets -->
+ <string name="search_widget_text_long">ဝက်ဘ်တွင်ရှာမည်</string>
+ <!-- Content description (not visible, for screen readers etc.): Voice search -->
+ <string name="search_widget_voice">အသံဖြင့်ရှာမည်</string>
+</resources>
diff --git a/mobile/android/android-components/components/feature/search/src/main/res/values-nb-rNO/strings.xml b/mobile/android/android-components/components/feature/search/src/main/res/values-nb-rNO/strings.xml
new file mode 100644
index 0000000000..2093f48242
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/res/values-nb-rNO/strings.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Search Widget -->
+ <!-- Content description for searching with a widget. The first parameter is the name of the application.-->
+ <string name="search_widget_content_description">Åpne en ny %1$s-fane</string>
+ <!-- Text preview for smaller sized widgets -->
+ <string name="search_widget_text_short">Søk</string>
+ <!-- Text preview for larger sized widgets -->
+ <string name="search_widget_text_long">Søk på nettet</string>
+ <!-- Content description (not visible, for screen readers etc.): Voice search -->
+ <string name="search_widget_voice">Stemmesøk</string>
+</resources>
diff --git a/mobile/android/android-components/components/feature/search/src/main/res/values-night/colors.xml b/mobile/android/android-components/components/feature/search/src/main/res/values-night/colors.xml
new file mode 100644
index 0000000000..50b0875a99
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/res/values-night/colors.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>
+ <color name="mozac_feature_search_widget_background_color">@color/photonDarkGrey60</color>
+ <color name="mozac_feature_search_widget_color">@color/photonLightGrey05</color>
+ <color name="mozac_feature_search_widget_text_color">@color/photonLightGrey05</color>
+
+</resources>
diff --git a/mobile/android/android-components/components/feature/search/src/main/res/values-nl/strings.xml b/mobile/android/android-components/components/feature/search/src/main/res/values-nl/strings.xml
new file mode 100644
index 0000000000..dc238c1191
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/res/values-nl/strings.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Search Widget -->
+ <!-- Content description for searching with a widget. The first parameter is the name of the application.-->
+ <string name="search_widget_content_description">Een nieuw %1$s-tabblad openen</string>
+ <!-- Text preview for smaller sized widgets -->
+ <string name="search_widget_text_short">Zoeken</string>
+ <!-- Text preview for larger sized widgets -->
+ <string name="search_widget_text_long">Zoeken op het web</string>
+ <!-- Content description (not visible, for screen readers etc.): Voice search -->
+ <string name="search_widget_voice">Gesproken zoekopdracht</string>
+</resources>
diff --git a/mobile/android/android-components/components/feature/search/src/main/res/values-nn-rNO/strings.xml b/mobile/android/android-components/components/feature/search/src/main/res/values-nn-rNO/strings.xml
new file mode 100644
index 0000000000..dfad13db60
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/res/values-nn-rNO/strings.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Search Widget -->
+ <!-- Content description for searching with a widget. The first parameter is the name of the application.-->
+ <string name="search_widget_content_description">Opne ei ny %1$s-fane</string>
+ <!-- Text preview for smaller sized widgets -->
+ <string name="search_widget_text_short">Søk</string>
+ <!-- Text preview for larger sized widgets -->
+ <string name="search_widget_text_long">Søk på nettet</string>
+ <!-- Content description (not visible, for screen readers etc.): Voice search -->
+ <string name="search_widget_voice">Stemmesøk</string>
+</resources>
diff --git a/mobile/android/android-components/components/feature/search/src/main/res/values-oc/strings.xml b/mobile/android/android-components/components/feature/search/src/main/res/values-oc/strings.xml
new file mode 100644
index 0000000000..9d63b2eb12
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/res/values-oc/strings.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Search Widget -->
+ <!-- Content description for searching with a widget. The first parameter is the name of the application.-->
+ <string name="search_widget_content_description">Dobrir dins un onglet %1$s novèl</string>
+ <!-- Text preview for smaller sized widgets -->
+ <string name="search_widget_text_short">Recèrca</string>
+ <!-- Text preview for larger sized widgets -->
+ <string name="search_widget_text_long">Recercar sul web</string>
+ <!-- Content description (not visible, for screen readers etc.): Voice search -->
+ <string name="search_widget_voice">Recèrca a la votz</string>
+</resources>
diff --git a/mobile/android/android-components/components/feature/search/src/main/res/values-pa-rIN/strings.xml b/mobile/android/android-components/components/feature/search/src/main/res/values-pa-rIN/strings.xml
new file mode 100644
index 0000000000..4a35511cdc
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/res/values-pa-rIN/strings.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Search Widget -->
+ <!-- Content description for searching with a widget. The first parameter is the name of the application.-->
+ <string name="search_widget_content_description">ਨਵੀਂ %1$s ਟੈਬ ਖੋਲ੍ਹੋ</string>
+ <!-- Text preview for smaller sized widgets -->
+ <string name="search_widget_text_short">ਖੋਜ</string>
+ <!-- Text preview for larger sized widgets -->
+ <string name="search_widget_text_long">ਵੈੱਬ ‘ਤੇ ਖੋਜੋ</string>
+ <!-- Content description (not visible, for screen readers etc.): Voice search -->
+ <string name="search_widget_voice">ਆਵਾਜ਼ ਰਾਹੀਂ ਖੋਜੋ</string>
+</resources>
diff --git a/mobile/android/android-components/components/feature/search/src/main/res/values-pa-rPK/strings.xml b/mobile/android/android-components/components/feature/search/src/main/res/values-pa-rPK/strings.xml
new file mode 100644
index 0000000000..961ba1dcc4
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/res/values-pa-rPK/strings.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Search Widget -->
+ <!-- Content description for searching with a widget. The first parameter is the name of the application.-->
+ <string name="search_widget_content_description">%1$s نال نویں ٹیب کھولھو</string>
+ <!-- Text preview for smaller sized widgets -->
+ <string name="search_widget_text_short">کھوج</string>
+ <!-- Text preview for larger sized widgets -->
+ <string name="search_widget_text_long">ویب دی کھوج</string>
+ <!-- Content description (not visible, for screen readers etc.): Voice search -->
+ <string name="search_widget_voice">آواز دی کھوج</string>
+</resources>
diff --git a/mobile/android/android-components/components/feature/search/src/main/res/values-pl/strings.xml b/mobile/android/android-components/components/feature/search/src/main/res/values-pl/strings.xml
new file mode 100644
index 0000000000..eb4e6c3b1c
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/res/values-pl/strings.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Search Widget -->
+ <!-- Content description for searching with a widget. The first parameter is the name of the application.-->
+ <string name="search_widget_content_description">Otwórz nową kartę w przeglądarce %1$s</string>
+ <!-- Text preview for smaller sized widgets -->
+ <string name="search_widget_text_short">Szukaj</string>
+ <!-- Text preview for larger sized widgets -->
+ <string name="search_widget_text_long">Szukaj w Internecie</string>
+ <!-- Content description (not visible, for screen readers etc.): Voice search -->
+ <string name="search_widget_voice">Wyszukiwanie głosowe</string>
+</resources>
diff --git a/mobile/android/android-components/components/feature/search/src/main/res/values-pt-rBR/strings.xml b/mobile/android/android-components/components/feature/search/src/main/res/values-pt-rBR/strings.xml
new file mode 100644
index 0000000000..8f34cd8284
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/res/values-pt-rBR/strings.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Search Widget -->
+ <!-- Content description for searching with a widget. The first parameter is the name of the application.-->
+ <string name="search_widget_content_description">Abrir nova aba no %1$s</string>
+ <!-- Text preview for smaller sized widgets -->
+ <string name="search_widget_text_short">Pesquisar</string>
+ <!-- Text preview for larger sized widgets -->
+ <string name="search_widget_text_long">Pesquisar na web</string>
+ <!-- Content description (not visible, for screen readers etc.): Voice search -->
+ <string name="search_widget_voice">Pesquisa por voz</string>
+</resources>
diff --git a/mobile/android/android-components/components/feature/search/src/main/res/values-pt-rPT/strings.xml b/mobile/android/android-components/components/feature/search/src/main/res/values-pt-rPT/strings.xml
new file mode 100644
index 0000000000..b8d8f409b6
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/res/values-pt-rPT/strings.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Search Widget -->
+ <!-- Content description for searching with a widget. The first parameter is the name of the application.-->
+ <string name="search_widget_content_description">Abrir um novo separador do %1$s</string>
+ <!-- Text preview for smaller sized widgets -->
+ <string name="search_widget_text_short">Pesquisar</string>
+ <!-- Text preview for larger sized widgets -->
+ <string name="search_widget_text_long">Pesquisar na Internet</string>
+ <!-- Content description (not visible, for screen readers etc.): Voice search -->
+ <string name="search_widget_voice">Pesquisa por voz</string>
+</resources>
diff --git a/mobile/android/android-components/components/feature/search/src/main/res/values-rm/strings.xml b/mobile/android/android-components/components/feature/search/src/main/res/values-rm/strings.xml
new file mode 100644
index 0000000000..c4af7423be
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/res/values-rm/strings.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Search Widget -->
+ <!-- Content description for searching with a widget. The first parameter is the name of the application.-->
+ <string name="search_widget_content_description">Avrir in nov tab da %1$s</string>
+ <!-- Text preview for smaller sized widgets -->
+ <string name="search_widget_text_short">Tschertgar</string>
+ <!-- Text preview for larger sized widgets -->
+ <string name="search_widget_text_long">Tschertgar en il web</string>
+ <!-- Content description (not visible, for screen readers etc.): Voice search -->
+ <string name="search_widget_voice">Tschertga vocala</string>
+</resources>
diff --git a/mobile/android/android-components/components/feature/search/src/main/res/values-ru/strings.xml b/mobile/android/android-components/components/feature/search/src/main/res/values-ru/strings.xml
new file mode 100644
index 0000000000..057ba662d6
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/res/values-ru/strings.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Search Widget -->
+ <!-- Content description for searching with a widget. The first parameter is the name of the application.-->
+ <string name="search_widget_content_description">Открыть новую вкладку %1$s</string>
+ <!-- Text preview for smaller sized widgets -->
+ <string name="search_widget_text_short">Поиск</string>
+ <!-- Text preview for larger sized widgets -->
+ <string name="search_widget_text_long">Поиск в Интернете</string>
+ <!-- Content description (not visible, for screen readers etc.): Voice search -->
+ <string name="search_widget_voice">Голосовой поиск</string>
+</resources>
diff --git a/mobile/android/android-components/components/feature/search/src/main/res/values-sat/strings.xml b/mobile/android/android-components/components/feature/search/src/main/res/values-sat/strings.xml
new file mode 100644
index 0000000000..c7d64349f0
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/res/values-sat/strings.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Search Widget -->
+ <!-- Content description for searching with a widget. The first parameter is the name of the application.-->
+ <string name="search_widget_content_description">ᱱᱟᱶᱟ ᱴᱮᱵᱽ %1$s ᱡᱷᱤᱡᱽ ᱢᱮ</string>
+ <!-- Text preview for smaller sized widgets -->
+ <string name="search_widget_text_short">ᱥᱮᱸᱫᱽᱨᱟ</string>
+ <!-- Text preview for larger sized widgets -->
+ <string name="search_widget_text_long">ᱣᱮᱵᱽ ᱨᱮ ᱥᱮᱸᱫᱽᱨᱟᱭ ᱢᱮ</string>
+ <!-- Content description (not visible, for screen readers etc.): Voice search -->
+ <string name="search_widget_voice">ᱨᱚᱲ ᱥᱮᱸᱫᱽᱨᱟ</string>
+</resources>
diff --git a/mobile/android/android-components/components/feature/search/src/main/res/values-sc/strings.xml b/mobile/android/android-components/components/feature/search/src/main/res/values-sc/strings.xml
new file mode 100644
index 0000000000..6c458d92a3
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/res/values-sc/strings.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Search Widget -->
+ <!-- Content description for searching with a widget. The first parameter is the name of the application.-->
+ <string name="search_widget_content_description">Aberi in un’ischeda de %1$s noa</string>
+ <!-- Text preview for smaller sized widgets -->
+ <string name="search_widget_text_short">Chirca</string>
+ <!-- Text preview for larger sized widgets -->
+ <string name="search_widget_text_long">Chirca in sa rete</string>
+ <!-- Content description (not visible, for screen readers etc.): Voice search -->
+ <string name="search_widget_voice">Chirca cun sa boghe</string>
+</resources>
diff --git a/mobile/android/android-components/components/feature/search/src/main/res/values-si/strings.xml b/mobile/android/android-components/components/feature/search/src/main/res/values-si/strings.xml
new file mode 100644
index 0000000000..7a6ddb27e5
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/res/values-si/strings.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Search Widget -->
+ <!-- Content description for searching with a widget. The first parameter is the name of the application.-->
+ <string name="search_widget_content_description">නව %1$s පටිත්තක් අරින්න</string>
+ <!-- Text preview for smaller sized widgets -->
+ <string name="search_widget_text_short">සොයන්න</string>
+ <!-- Text preview for larger sized widgets -->
+ <string name="search_widget_text_long">වියමනහි සොයන්න</string>
+ <!-- Content description (not visible, for screen readers etc.): Voice search -->
+ <string name="search_widget_voice">හඬ සෙවුම</string>
+</resources>
diff --git a/mobile/android/android-components/components/feature/search/src/main/res/values-sk/strings.xml b/mobile/android/android-components/components/feature/search/src/main/res/values-sk/strings.xml
new file mode 100644
index 0000000000..8cc11bc103
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/res/values-sk/strings.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Search Widget -->
+ <!-- Content description for searching with a widget. The first parameter is the name of the application.-->
+ <string name="search_widget_content_description">Otvoriť novú kartu %1$su</string>
+ <!-- Text preview for smaller sized widgets -->
+ <string name="search_widget_text_short">Hľadať</string>
+ <!-- Text preview for larger sized widgets -->
+ <string name="search_widget_text_long">Vyhľadávanie na webe</string>
+ <!-- Content description (not visible, for screen readers etc.): Voice search -->
+ <string name="search_widget_voice">Hlasové vyhľadávanie</string>
+</resources>
diff --git a/mobile/android/android-components/components/feature/search/src/main/res/values-skr/strings.xml b/mobile/android/android-components/components/feature/search/src/main/res/values-skr/strings.xml
new file mode 100644
index 0000000000..f2dbedb987
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/res/values-skr/strings.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Search Widget -->
+ <!-- Content description for searching with a widget. The first parameter is the name of the application.-->
+ <string name="search_widget_content_description">نویں %1$s ٹیب کھولو</string>
+ <!-- Text preview for smaller sized widgets -->
+ <string name="search_widget_text_short">ڳولو</string>
+ <!-- Text preview for larger sized widgets -->
+ <string name="search_widget_text_long">ویب ڳولو</string>
+ <!-- Content description (not visible, for screen readers etc.): Voice search -->
+ <string name="search_widget_voice">آواز نال ڳولݨ</string>
+</resources>
diff --git a/mobile/android/android-components/components/feature/search/src/main/res/values-sl/strings.xml b/mobile/android/android-components/components/feature/search/src/main/res/values-sl/strings.xml
new file mode 100644
index 0000000000..96d3701731
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/res/values-sl/strings.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Search Widget -->
+ <!-- Content description for searching with a widget. The first parameter is the name of the application.-->
+ <string name="search_widget_content_description">Odpri nov zavihek v %1$su</string>
+ <!-- Text preview for smaller sized widgets -->
+ <string name="search_widget_text_short">Išči</string>
+ <!-- Text preview for larger sized widgets -->
+ <string name="search_widget_text_long">Iskanje po spletu</string>
+ <!-- Content description (not visible, for screen readers etc.): Voice search -->
+ <string name="search_widget_voice">Glasovno iskanje</string>
+</resources>
diff --git a/mobile/android/android-components/components/feature/search/src/main/res/values-sq/strings.xml b/mobile/android/android-components/components/feature/search/src/main/res/values-sq/strings.xml
new file mode 100644
index 0000000000..cfe062bbc3
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/res/values-sq/strings.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Search Widget -->
+ <!-- Content description for searching with a widget. The first parameter is the name of the application.-->
+ <string name="search_widget_content_description">Hapni një skedë të re %1$s</string>
+ <!-- Text preview for smaller sized widgets -->
+ <string name="search_widget_text_short">Kërko</string>
+ <!-- Text preview for larger sized widgets -->
+ <string name="search_widget_text_long">Kërkoni në web</string>
+ <!-- Content description (not visible, for screen readers etc.): Voice search -->
+ <string name="search_widget_voice">Kërkim zanor</string>
+</resources>
diff --git a/mobile/android/android-components/components/feature/search/src/main/res/values-sr/strings.xml b/mobile/android/android-components/components/feature/search/src/main/res/values-sr/strings.xml
new file mode 100644
index 0000000000..2cc2c10161
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/res/values-sr/strings.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Search Widget -->
+ <!-- Content description for searching with a widget. The first parameter is the name of the application.-->
+ <string name="search_widget_content_description">Отвори нови %1$s језичак</string>
+ <!-- Text preview for smaller sized widgets -->
+ <string name="search_widget_text_short">Претражи</string>
+ <!-- Text preview for larger sized widgets -->
+ <string name="search_widget_text_long">Претражи веб</string>
+ <!-- Content description (not visible, for screen readers etc.): Voice search -->
+ <string name="search_widget_voice">Гласовна претрага</string>
+</resources>
diff --git a/mobile/android/android-components/components/feature/search/src/main/res/values-su/strings.xml b/mobile/android/android-components/components/feature/search/src/main/res/values-su/strings.xml
new file mode 100644
index 0000000000..f180cfabf5
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/res/values-su/strings.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Search Widget -->
+ <!-- Content description for searching with a widget. The first parameter is the name of the application.-->
+ <string name="search_widget_content_description">Buka dina tab %1$s anyar</string>
+ <!-- Text preview for smaller sized widgets -->
+ <string name="search_widget_text_short">Paluruh</string>
+ <!-- Text preview for larger sized widgets -->
+ <string name="search_widget_text_long">Paluruh raramat</string>
+ <!-- Content description (not visible, for screen readers etc.): Voice search -->
+ <string name="search_widget_voice">Paluruh sora</string>
+</resources>
diff --git a/mobile/android/android-components/components/feature/search/src/main/res/values-sv-rSE/strings.xml b/mobile/android/android-components/components/feature/search/src/main/res/values-sv-rSE/strings.xml
new file mode 100644
index 0000000000..9c3f5f1428
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/res/values-sv-rSE/strings.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Search Widget -->
+ <!-- Content description for searching with a widget. The first parameter is the name of the application.-->
+ <string name="search_widget_content_description">Öppna en ny %1$s-flik</string>
+ <!-- Text preview for smaller sized widgets -->
+ <string name="search_widget_text_short">Sök</string>
+ <!-- Text preview for larger sized widgets -->
+ <string name="search_widget_text_long">Sök på webben</string>
+ <!-- Content description (not visible, for screen readers etc.): Voice search -->
+ <string name="search_widget_voice">Röstsökning</string>
+</resources>
diff --git a/mobile/android/android-components/components/feature/search/src/main/res/values-ta/strings.xml b/mobile/android/android-components/components/feature/search/src/main/res/values-ta/strings.xml
new file mode 100644
index 0000000000..d04a02b330
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/res/values-ta/strings.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Search Widget -->
+ <!-- Content description for searching with a widget. The first parameter is the name of the application.-->
+ <string name="search_widget_content_description">%1$s ஐ புதிய கீற்றில் திற</string>
+ <!-- Text preview for smaller sized widgets -->
+ <string name="search_widget_text_short">தேடு</string>
+ <!-- Text preview for larger sized widgets -->
+ <string name="search_widget_text_long">இணையத்தில் தேடு</string>
+ <!-- Content description (not visible, for screen readers etc.): Voice search -->
+ <string name="search_widget_voice">குரல் தேடல்</string>
+</resources>
diff --git a/mobile/android/android-components/components/feature/search/src/main/res/values-te/strings.xml b/mobile/android/android-components/components/feature/search/src/main/res/values-te/strings.xml
new file mode 100644
index 0000000000..dae1fcac80
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/res/values-te/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Text preview for smaller sized widgets -->
+ <string name="search_widget_text_short">వెతకండి</string>
+ <!-- Text preview for larger sized widgets -->
+ <string name="search_widget_text_long">జాలంలో వెతకండి</string>
+ </resources>
diff --git a/mobile/android/android-components/components/feature/search/src/main/res/values-tg/strings.xml b/mobile/android/android-components/components/feature/search/src/main/res/values-tg/strings.xml
new file mode 100644
index 0000000000..b25dee92ec
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/res/values-tg/strings.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Search Widget -->
+ <!-- Content description for searching with a widget. The first parameter is the name of the application.-->
+ <string name="search_widget_content_description">Кушодани варақаи нави %1$s</string>
+ <!-- Text preview for smaller sized widgets -->
+ <string name="search_widget_text_short">Ҷустуҷӯ</string>
+ <!-- Text preview for larger sized widgets -->
+ <string name="search_widget_text_long">Ҷустуҷӯ дар Интернет</string>
+ <!-- Content description (not visible, for screen readers etc.): Voice search -->
+ <string name="search_widget_voice">Ҷустуҷӯи овозӣ</string>
+</resources>
diff --git a/mobile/android/android-components/components/feature/search/src/main/res/values-th/strings.xml b/mobile/android/android-components/components/feature/search/src/main/res/values-th/strings.xml
new file mode 100644
index 0000000000..224c92e420
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/res/values-th/strings.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Search Widget -->
+ <!-- Content description for searching with a widget. The first parameter is the name of the application.-->
+ <string name="search_widget_content_description">เปิดแท็บ %1$s ใหม่</string>
+ <!-- Text preview for smaller sized widgets -->
+ <string name="search_widget_text_short">ค้นหา</string>
+ <!-- Text preview for larger sized widgets -->
+ <string name="search_widget_text_long">ค้นหาเว็บ</string>
+ <!-- Content description (not visible, for screen readers etc.): Voice search -->
+ <string name="search_widget_voice">ค้นหาด้วยเสียง</string>
+</resources>
diff --git a/mobile/android/android-components/components/feature/search/src/main/res/values-tl/strings.xml b/mobile/android/android-components/components/feature/search/src/main/res/values-tl/strings.xml
new file mode 100644
index 0000000000..28f70ae9be
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/res/values-tl/strings.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Search Widget -->
+ <!-- Content description for searching with a widget. The first parameter is the name of the application.-->
+ <string name="search_widget_content_description">Buksan ang bagong %1$s tab</string>
+ <!-- Text preview for smaller sized widgets -->
+ <string name="search_widget_text_short">Hanapin</string>
+ <!-- Text preview for larger sized widgets -->
+ <string name="search_widget_text_long">Hanapin sa web</string>
+ <!-- Content description (not visible, for screen readers etc.): Voice search -->
+ <string name="search_widget_voice">Paghanap gamit ang boses</string>
+</resources>
diff --git a/mobile/android/android-components/components/feature/search/src/main/res/values-tr/strings.xml b/mobile/android/android-components/components/feature/search/src/main/res/values-tr/strings.xml
new file mode 100644
index 0000000000..92c352702a
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/res/values-tr/strings.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Search Widget -->
+ <!-- Content description for searching with a widget. The first parameter is the name of the application.-->
+ <string name="search_widget_content_description">Yeni %1$s sekmesi aç</string>
+ <!-- Text preview for smaller sized widgets -->
+ <string name="search_widget_text_short">Ara</string>
+ <!-- Text preview for larger sized widgets -->
+ <string name="search_widget_text_long">Web’de ara</string>
+ <!-- Content description (not visible, for screen readers etc.): Voice search -->
+ <string name="search_widget_voice">Sesle ara</string>
+</resources>
diff --git a/mobile/android/android-components/components/feature/search/src/main/res/values-trs/strings.xml b/mobile/android/android-components/components/feature/search/src/main/res/values-trs/strings.xml
new file mode 100644
index 0000000000..c42a2fe23b
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/res/values-trs/strings.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Search Widget -->
+ <!-- Content description for searching with a widget. The first parameter is the name of the application.-->
+ <string name="search_widget_content_description">Nā\'nïn riña rakïj ñanj nakàa %1$s</string>
+ <!-- Text preview for smaller sized widgets -->
+ <string name="search_widget_text_short">Nānà\'huì\'</string>
+ <!-- Text preview for larger sized widgets -->
+ <string name="search_widget_text_long">Nānà\'huì\' riña web</string>
+ <!-- Content description (not visible, for screen readers etc.): Voice search -->
+ <string name="search_widget_voice">Nānà\'huì\' ngà nanèt</string>
+</resources>
diff --git a/mobile/android/android-components/components/feature/search/src/main/res/values-tt/strings.xml b/mobile/android/android-components/components/feature/search/src/main/res/values-tt/strings.xml
new file mode 100644
index 0000000000..e2b8d1f5b6
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/res/values-tt/strings.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Search Widget -->
+ <!-- Content description for searching with a widget. The first parameter is the name of the application.-->
+ <string name="search_widget_content_description">Яңа %1$s табын ачу</string>
+ <!-- Text preview for smaller sized widgets -->
+ <string name="search_widget_text_short">Эзләү</string>
+ <!-- Text preview for larger sized widgets -->
+ <string name="search_widget_text_long">Интернетта эзләү</string>
+ <!-- Content description (not visible, for screen readers etc.): Voice search -->
+ <string name="search_widget_voice">Тавышлы эзләү</string>
+</resources>
diff --git a/mobile/android/android-components/components/feature/search/src/main/res/values-ug/strings.xml b/mobile/android/android-components/components/feature/search/src/main/res/values-ug/strings.xml
new file mode 100644
index 0000000000..27df6dae14
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/res/values-ug/strings.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Search Widget -->
+ <!-- Content description for searching with a widget. The first parameter is the name of the application.-->
+ <string name="search_widget_content_description">يېڭى%1$sبەتكۈچىنى ئېچىش</string>
+ <!-- Text preview for smaller sized widgets -->
+ <string name="search_widget_text_short">ئىزدەش</string>
+ <!-- Text preview for larger sized widgets -->
+ <string name="search_widget_text_long">توردىن ئىزدەش</string>
+ <!-- Content description (not visible, for screen readers etc.): Voice search -->
+ <string name="search_widget_voice">ئاۋازلىق ئىزدەش</string>
+</resources>
diff --git a/mobile/android/android-components/components/feature/search/src/main/res/values-uk/strings.xml b/mobile/android/android-components/components/feature/search/src/main/res/values-uk/strings.xml
new file mode 100644
index 0000000000..b3060b0b0a
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/res/values-uk/strings.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Search Widget -->
+ <!-- Content description for searching with a widget. The first parameter is the name of the application.-->
+ <string name="search_widget_content_description">Відкрити нову вкладку %1$s</string>
+ <!-- Text preview for smaller sized widgets -->
+ <string name="search_widget_text_short">Пошук</string>
+ <!-- Text preview for larger sized widgets -->
+ <string name="search_widget_text_long">Пошук в Інтернеті</string>
+ <!-- Content description (not visible, for screen readers etc.): Voice search -->
+ <string name="search_widget_voice">Голосовий пошук</string>
+</resources>
diff --git a/mobile/android/android-components/components/feature/search/src/main/res/values-uz/strings.xml b/mobile/android/android-components/components/feature/search/src/main/res/values-uz/strings.xml
new file mode 100644
index 0000000000..9ecebb4caa
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/res/values-uz/strings.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Search Widget -->
+ <!-- Content description for searching with a widget. The first parameter is the name of the application.-->
+ <string name="search_widget_content_description">Yangi %1$s ta varaqni ochish</string>
+ <!-- Text preview for smaller sized widgets -->
+ <string name="search_widget_text_short">Qidirish</string>
+ <!-- Text preview for larger sized widgets -->
+ <string name="search_widget_text_long">Internetdan qidirish</string>
+ <!-- Content description (not visible, for screen readers etc.): Voice search -->
+ <string name="search_widget_voice">Ovozli qidiruv</string>
+</resources>
diff --git a/mobile/android/android-components/components/feature/search/src/main/res/values-vi/strings.xml b/mobile/android/android-components/components/feature/search/src/main/res/values-vi/strings.xml
new file mode 100644
index 0000000000..361cbdc149
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/res/values-vi/strings.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Search Widget -->
+ <!-- Content description for searching with a widget. The first parameter is the name of the application.-->
+ <string name="search_widget_content_description">Mở thẻ %1$s mới</string>
+ <!-- Text preview for smaller sized widgets -->
+ <string name="search_widget_text_short">Tìm kiếm</string>
+ <!-- Text preview for larger sized widgets -->
+ <string name="search_widget_text_long">Tìm kiếm trên mạng</string>
+ <!-- Content description (not visible, for screen readers etc.): Voice search -->
+ <string name="search_widget_voice">Tìm kiếm bằng giọng nói</string>
+</resources>
diff --git a/mobile/android/android-components/components/feature/search/src/main/res/values-yo/strings.xml b/mobile/android/android-components/components/feature/search/src/main/res/values-yo/strings.xml
new file mode 100644
index 0000000000..e530cea4a6
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/res/values-yo/strings.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Search Widget -->
+ <!-- Content description for searching with a widget. The first parameter is the name of the application.-->
+ <string name="search_widget_content_description">Ṣí táàbù tuntun %1$s</string>
+ <!-- Text preview for smaller sized widgets -->
+ <string name="search_widget_text_short">Ṣàwarí</string>
+ <!-- Text preview for larger sized widgets -->
+ <string name="search_widget_text_long">Wá lórí wẹ́ẹ̀bù</string>
+ <!-- Content description (not visible, for screen readers etc.): Voice search -->
+ <string name="search_widget_voice">Wíwá pẹ̀lú ohùn</string>
+</resources>
diff --git a/mobile/android/android-components/components/feature/search/src/main/res/values-zh-rCN/strings.xml b/mobile/android/android-components/components/feature/search/src/main/res/values-zh-rCN/strings.xml
new file mode 100644
index 0000000000..0fd0474f78
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/res/values-zh-rCN/strings.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Search Widget -->
+ <!-- Content description for searching with a widget. The first parameter is the name of the application.-->
+ <string name="search_widget_content_description">新建 %1$s 标签页</string>
+ <!-- Text preview for smaller sized widgets -->
+ <string name="search_widget_text_short">搜索</string>
+ <!-- Text preview for larger sized widgets -->
+ <string name="search_widget_text_long">网上搜索</string>
+ <!-- Content description (not visible, for screen readers etc.): Voice search -->
+ <string name="search_widget_voice">语音搜索</string>
+</resources>
diff --git a/mobile/android/android-components/components/feature/search/src/main/res/values-zh-rTW/strings.xml b/mobile/android/android-components/components/feature/search/src/main/res/values-zh-rTW/strings.xml
new file mode 100644
index 0000000000..a4baf4e3d8
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/res/values-zh-rTW/strings.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Search Widget -->
+ <!-- Content description for searching with a widget. The first parameter is the name of the application.-->
+ <string name="search_widget_content_description">開啟新 %1$s 分頁</string>
+ <!-- Text preview for smaller sized widgets -->
+ <string name="search_widget_text_short">搜尋</string>
+ <!-- Text preview for larger sized widgets -->
+ <string name="search_widget_text_long">搜尋 Web</string>
+ <!-- Content description (not visible, for screen readers etc.): Voice search -->
+ <string name="search_widget_voice">語音搜尋</string>
+</resources>
diff --git a/mobile/android/android-components/components/feature/search/src/main/res/values/colors.xml b/mobile/android/android-components/components/feature/search/src/main/res/values/colors.xml
new file mode 100644
index 0000000000..07c5961bbe
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/res/values/colors.xml
@@ -0,0 +1,9 @@
+<?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>
+ <color name="mozac_feature_search_widget_background_color">@color/photonLightGrey10</color>
+ <color name="mozac_feature_search_widget_text_color">@color/photonDarkGrey90</color>
+ <color name="mozac_feature_search_widget_color">@color/photonDarkGrey90</color>
+</resources>
diff --git a/mobile/android/android-components/components/feature/search/src/main/res/values/dimens.xml b/mobile/android/android-components/components/feature/search/src/main/res/values/dimens.xml
new file mode 100644
index 0000000000..52c1f7545a
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/res/values/dimens.xml
@@ -0,0 +1,7 @@
+<?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>
+ <dimen name="mozac_tab_corner_radius">8dp</dimen>
+</resources>
diff --git a/mobile/android/android-components/components/feature/search/src/main/res/values/strings.xml b/mobile/android/android-components/components/feature/search/src/main/res/values/strings.xml
new file mode 100644
index 0000000000..6f1f2b42e7
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/main/res/values/strings.xml
@@ -0,0 +1,16 @@
+<?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>
+ <!-- Search Widget -->
+ <!-- Content description for searching with a widget. The first parameter is the name of the application.-->
+ <string name="search_widget_content_description">Open a new %1$s tab</string>
+ <!-- Text preview for smaller sized widgets -->
+ <string name="search_widget_text_short">Search</string>
+ <!-- Text preview for larger sized widgets -->
+ <string name="search_widget_text_long">Search the web</string>
+ <!-- Content description (not visible, for screen readers etc.): Voice search -->
+ <string name="search_widget_voice">Voice search</string>
+</resources>
diff --git a/mobile/android/android-components/components/feature/search/src/test/java/mozilla/components/feature/search/BrowserStoreSeachAdapterTest.kt b/mobile/android/android-components/components/feature/search/src/test/java/mozilla/components/feature/search/BrowserStoreSeachAdapterTest.kt
new file mode 100644
index 0000000000..37c2f83468
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/test/java/mozilla/components/feature/search/BrowserStoreSeachAdapterTest.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.feature.search
+
+import mozilla.components.browser.state.action.ContentAction
+import mozilla.components.browser.state.state.BrowserState
+import mozilla.components.browser.state.state.SessionState
+import mozilla.components.browser.state.state.createCustomTab
+import mozilla.components.browser.state.state.createTab
+import mozilla.components.browser.state.store.BrowserStore
+import mozilla.components.concept.engine.search.SearchRequest
+import mozilla.components.support.test.any
+import mozilla.components.support.test.mock
+import mozilla.components.support.test.whenever
+import org.junit.Assert.assertFalse
+import org.junit.Assert.assertTrue
+import org.junit.Before
+import org.junit.Test
+import org.mockito.Mockito.never
+import org.mockito.Mockito.verify
+
+private const val SELECTED_TAB_ID = "1"
+private const val CUSTOM_TAB_ID = "2"
+
+class BrowserStoreSearchAdapterTest {
+
+ private lateinit var browserStore: BrowserStore
+ private val state = BrowserState(
+ tabs = listOf(createTab(id = SELECTED_TAB_ID, url = "https://mozilla.org", private = true)),
+ customTabs = listOf(createCustomTab(id = CUSTOM_TAB_ID, url = "https://firefox.com", source = SessionState.Source.Internal.CustomTab)),
+ selectedTabId = SELECTED_TAB_ID,
+ )
+
+ @Before
+ fun setup() {
+ browserStore = mock()
+ whenever(browserStore.state).thenReturn(state)
+ }
+
+ @Test
+ fun `adapter does nothing with null tab`() {
+ whenever(browserStore.state).thenReturn(BrowserState())
+ val searchAdapter = BrowserStoreSearchAdapter(browserStore)
+
+ searchAdapter.sendSearch(isPrivate = false, text = "normal search")
+ searchAdapter.sendSearch(isPrivate = true, text = "private search")
+
+ verify(browserStore, never()).dispatch(any())
+ assertFalse(searchAdapter.isPrivateSession())
+ }
+
+ @Test
+ fun `sendSearch with selected tab`() {
+ val searchAdapter = BrowserStoreSearchAdapter(browserStore)
+ searchAdapter.sendSearch(isPrivate = false, text = "normal search")
+ verify(browserStore).dispatch(
+ ContentAction.UpdateSearchRequestAction(
+ SELECTED_TAB_ID,
+ SearchRequest(isPrivate = false, query = "normal search"),
+ ),
+ )
+
+ searchAdapter.sendSearch(isPrivate = true, text = "private search")
+ verify(browserStore).dispatch(
+ ContentAction.UpdateSearchRequestAction(
+ SELECTED_TAB_ID,
+ SearchRequest(isPrivate = true, query = "private search"),
+ ),
+ )
+
+ assertTrue(searchAdapter.isPrivateSession())
+ }
+
+ @Test
+ fun `sendSearch with custom tab`() {
+ val searchAdapter = BrowserStoreSearchAdapter(browserStore, CUSTOM_TAB_ID)
+ searchAdapter.sendSearch(isPrivate = false, text = "normal search")
+ verify(browserStore).dispatch(
+ ContentAction.UpdateSearchRequestAction(
+ CUSTOM_TAB_ID,
+ SearchRequest(isPrivate = false, query = "normal search"),
+ ),
+ )
+
+ searchAdapter.sendSearch(isPrivate = true, text = "private search")
+ verify(browserStore).dispatch(
+ ContentAction.UpdateSearchRequestAction(
+ CUSTOM_TAB_ID,
+ SearchRequest(isPrivate = true, query = "private search"),
+ ),
+ )
+
+ assertFalse(searchAdapter.isPrivateSession())
+ }
+}
diff --git a/mobile/android/android-components/components/feature/search/src/test/java/mozilla/components/feature/search/SearchFeatureTest.kt b/mobile/android/android-components/components/feature/search/src/test/java/mozilla/components/feature/search/SearchFeatureTest.kt
new file mode 100644
index 0000000000..17d6d9bfe3
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/test/java/mozilla/components/feature/search/SearchFeatureTest.kt
@@ -0,0 +1,134 @@
+/* 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.feature.search
+
+import mozilla.components.browser.state.action.ContentAction
+import mozilla.components.browser.state.action.TabListAction
+import mozilla.components.browser.state.selector.selectedTab
+import mozilla.components.browser.state.state.BrowserState
+import mozilla.components.browser.state.state.createTab
+import mozilla.components.browser.state.store.BrowserStore
+import mozilla.components.concept.engine.search.SearchRequest
+import mozilla.components.support.test.any
+import mozilla.components.support.test.eq
+import mozilla.components.support.test.ext.joinBlocking
+import mozilla.components.support.test.libstate.ext.waitUntilIdle
+import mozilla.components.support.test.mock
+import mozilla.components.support.test.rule.MainCoroutineRule
+import org.junit.After
+import org.junit.Assert.assertNull
+import org.junit.Before
+import org.junit.Rule
+import org.junit.Test
+import org.mockito.Mockito.times
+import org.mockito.Mockito.verify
+
+private const val SELECTED_TAB_ID = "1"
+
+class SearchFeatureTest {
+
+ @get:Rule
+ val coroutinesTestRule = MainCoroutineRule()
+
+ private lateinit var performSearch: (SearchRequest, String) -> Unit
+ private lateinit var store: BrowserStore
+ private lateinit var searchFeature: SearchFeature
+
+ @Before
+ fun before() {
+ store = BrowserStore(
+ mockBrowserState(),
+ )
+ performSearch = mock()
+ searchFeature = SearchFeature(store, null, performSearch).apply {
+ start()
+ }
+ }
+
+ private fun mockBrowserState(): BrowserState {
+ return BrowserState(
+ tabs = listOf(
+ createTab("https://www.duckduckgo.com", id = "0"),
+ createTab("https://www.mozilla.org", id = SELECTED_TAB_ID),
+ createTab("https://www.wikipedia.org", id = "2"),
+ ),
+ selectedTabId = SELECTED_TAB_ID,
+ )
+ }
+
+ @After
+ fun after() {
+ searchFeature.stop()
+ }
+
+ @Test
+ fun `GIVEN a tab is selected WHEN a search request is sent THEN a search should be performed`() {
+ verify(performSearch, times(0)).invoke(any(), eq(SELECTED_TAB_ID))
+
+ val normalSearchRequest = SearchRequest(isPrivate = false, query = "query")
+ store.dispatch(ContentAction.UpdateSearchRequestAction(SELECTED_TAB_ID, normalSearchRequest)).joinBlocking()
+
+ verify(performSearch, times(1)).invoke(any(), eq(SELECTED_TAB_ID))
+ verify(performSearch, times(1)).invoke(normalSearchRequest, SELECTED_TAB_ID)
+
+ val privateSearchRequest = SearchRequest(isPrivate = true, query = "query")
+ store.dispatch(ContentAction.UpdateSearchRequestAction(SELECTED_TAB_ID, privateSearchRequest)).joinBlocking()
+
+ verify(performSearch, times(2)).invoke(any(), eq(SELECTED_TAB_ID))
+ verify(performSearch, times(1)).invoke(privateSearchRequest, SELECTED_TAB_ID)
+ }
+
+ @Test
+ fun `GIVEN no tab is selected WHEN a search request is sent THEN no search should be performed`() {
+ store.dispatch(TabListAction.RemoveTabAction(tabId = SELECTED_TAB_ID, selectParentIfExists = false))
+
+ verify(performSearch, times(0)).invoke(any(), eq(SELECTED_TAB_ID))
+
+ val normalSearchRequest = SearchRequest(isPrivate = false, query = "query")
+ store.dispatch(ContentAction.UpdateSearchRequestAction(SELECTED_TAB_ID, normalSearchRequest)).joinBlocking()
+
+ verify(performSearch, times(0)).invoke(any(), eq(SELECTED_TAB_ID))
+ verify(performSearch, times(0)).invoke(normalSearchRequest, SELECTED_TAB_ID)
+
+ val privateSearchRequest = SearchRequest(isPrivate = true, query = "query")
+ store.dispatch(ContentAction.UpdateSearchRequestAction(SELECTED_TAB_ID, privateSearchRequest)).joinBlocking()
+
+ verify(performSearch, times(0)).invoke(any(), eq(SELECTED_TAB_ID))
+ verify(performSearch, times(0)).invoke(privateSearchRequest, SELECTED_TAB_ID)
+ }
+
+ @Test
+ fun `WHEN a search request has been handled THEN that request should have been consumed`() {
+ val normalSearchRequest = SearchRequest(isPrivate = false, query = "query")
+ store.dispatch(ContentAction.UpdateSearchRequestAction(SELECTED_TAB_ID, normalSearchRequest)).joinBlocking()
+ store.waitUntilIdle()
+
+ assertNull(store.state.selectedTab!!.content.searchRequest)
+
+ val privateSearchRequest = SearchRequest(isPrivate = true, query = "query")
+ store.dispatch(ContentAction.UpdateSearchRequestAction(SELECTED_TAB_ID, privateSearchRequest)).joinBlocking()
+ store.waitUntilIdle()
+
+ assertNull(store.state.selectedTab!!.content.searchRequest)
+ }
+
+ @Test
+ fun `WHEN the same search is requested two times THEN both search requests are preformed and consumed`() {
+ val searchRequest = SearchRequest(isPrivate = false, query = "query")
+ verify(performSearch, times(0)).invoke(searchRequest, SELECTED_TAB_ID)
+
+ store.dispatch(ContentAction.UpdateSearchRequestAction(SELECTED_TAB_ID, searchRequest)).joinBlocking()
+ store.waitUntilIdle()
+
+ verify(performSearch, times(1)).invoke(searchRequest, SELECTED_TAB_ID)
+ assertNull(store.state.selectedTab!!.content.searchRequest)
+
+ store.dispatch(ContentAction.UpdateSearchRequestAction(SELECTED_TAB_ID, searchRequest)).joinBlocking()
+ store.waitUntilIdle()
+
+ verify(performSearch, times(2)).invoke(searchRequest, SELECTED_TAB_ID)
+ assertNull(store.state.selectedTab!!.content.searchRequest)
+ }
+}
diff --git a/mobile/android/android-components/components/feature/search/src/test/java/mozilla/components/feature/search/SearchUseCasesTest.kt b/mobile/android/android-components/components/feature/search/src/test/java/mozilla/components/feature/search/SearchUseCasesTest.kt
new file mode 100644
index 0000000000..0168491b0b
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/test/java/mozilla/components/feature/search/SearchUseCasesTest.kt
@@ -0,0 +1,663 @@
+/* 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.feature.search
+
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import mozilla.components.browser.state.action.BrowserAction
+import mozilla.components.browser.state.action.ContentAction
+import mozilla.components.browser.state.action.EngineAction
+import mozilla.components.browser.state.action.TabListAction
+import mozilla.components.browser.state.search.RegionState
+import mozilla.components.browser.state.search.SearchEngine
+import mozilla.components.browser.state.state.BrowserState
+import mozilla.components.browser.state.state.SearchState
+import mozilla.components.browser.state.state.SessionState
+import mozilla.components.browser.state.state.availableSearchEngines
+import mozilla.components.browser.state.state.createTab
+import mozilla.components.browser.state.state.searchEngines
+import mozilla.components.browser.state.store.BrowserStore
+import mozilla.components.concept.engine.EngineSession.LoadUrlFlags
+import mozilla.components.feature.search.ext.createSearchEngine
+import mozilla.components.feature.session.SessionUseCases
+import mozilla.components.feature.tabs.TabsUseCases
+import mozilla.components.support.test.ext.joinBlocking
+import mozilla.components.support.test.libstate.ext.waitUntilIdle
+import mozilla.components.support.test.middleware.CaptureActionsMiddleware
+import mozilla.components.support.test.mock
+import mozilla.components.support.test.whenever
+import org.junit.After
+import org.junit.Assert.assertEquals
+import org.junit.Assert.assertNull
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.Mockito.doReturn
+import org.mockito.Mockito.verify
+
+@RunWith(AndroidJUnit4::class)
+class SearchUseCasesTest {
+
+ private lateinit var searchEngine: SearchEngine
+ private lateinit var store: BrowserStore
+ private lateinit var useCases: SearchUseCases
+ private lateinit var tabsUseCases: TabsUseCases
+ private lateinit var sessionUseCases: SessionUseCases
+ private lateinit var loadUrlUseCase: SessionUseCases.DefaultLoadUrlUseCase
+
+ private val middleware = CaptureActionsMiddleware<BrowserState, BrowserAction>()
+
+ private val searchTerms = "mozilla android"
+ private val searchUrl = "https://example.org/?q=mozilla%20android"
+ private val searchEngineName = "Test"
+
+ @Before
+ fun setup() {
+ searchEngine = createSearchEngine(
+ name = searchEngineName,
+ url = "https://example.org/?q={searchTerms}",
+ icon = mock(),
+ )
+
+ tabsUseCases = mock()
+ sessionUseCases = mock()
+ loadUrlUseCase = mock()
+ doReturn(loadUrlUseCase).`when`(sessionUseCases).loadUrl
+
+ store = BrowserStore(
+ initialState = BrowserState(
+ search = SearchState(
+ regionSearchEngines = listOf(searchEngine),
+ ),
+ ),
+ middleware = listOf(middleware),
+ )
+
+ useCases = SearchUseCases(
+ store,
+ tabsUseCases,
+ sessionUseCases,
+ )
+ }
+
+ @After
+ fun tearDown() {
+ middleware.reset()
+ }
+
+ @Test
+ fun `GIVEN existing Session and Tab WHEN default search invoked THEN expected actions are dispatched`() {
+ val id = "mozilla"
+ store.dispatch(
+ TabListAction.AddTabAction(
+ tab = createTab(url = "https://www.mozilla.org", id = id),
+ select = true,
+ ),
+ ).joinBlocking()
+
+ useCases.defaultSearch(
+ searchTerms = searchTerms,
+ searchEngine = searchEngine,
+ )
+ store.waitUntilIdle()
+
+ val isSearchAction = middleware.findFirstAction(ContentAction.UpdateIsSearchAction::class)
+ assertEquals(id, isSearchAction.sessionId)
+ assertEquals(true, isSearchAction.isSearch)
+ assertEquals(searchEngineName, isSearchAction.searchEngineName)
+
+ middleware.assertLastAction(EngineAction.LoadUrlAction::class) { action ->
+ assertEquals(id, action.tabId)
+ assertEquals(searchUrl, action.url)
+ }
+ }
+
+ @Test
+ fun `GIVEN existing Session, no existing Tab WHEN default search invoked THEN add tab is called`() {
+ val newTabUseCase: TabsUseCases.AddNewTabUseCase = mock()
+ whenever(tabsUseCases.addTab).thenReturn(newTabUseCase)
+ val newTabId = "9876"
+ whenever(
+ newTabUseCase(
+ url = searchUrl,
+ isSearch = true,
+ searchEngineName = searchEngineName,
+ ),
+ ).thenReturn(newTabId)
+
+ useCases.defaultSearch(
+ searchTerms = searchTerms,
+ sessionId = "mozilla",
+ searchEngine = searchEngine,
+ )
+ store.waitUntilIdle()
+
+ verify(newTabUseCase).invoke(
+ url = searchUrl,
+ isSearch = true,
+ searchEngineName = searchEngineName,
+ )
+
+ middleware.assertLastAction(ContentAction.UpdateSearchTermsAction::class) { action ->
+ assertEquals(newTabId, action.sessionId)
+ assertEquals(searchTerms, action.searchTerms)
+ }
+ }
+
+ @Test
+ fun defaultSearchOnNewSession() {
+ val searchTerms = "mozilla android"
+
+ val newTabUseCase: TabsUseCases.AddNewTabUseCase = mock()
+ whenever(tabsUseCases.addTab).thenReturn(newTabUseCase)
+ whenever(newTabUseCase(searchUrl, isSearch = true)).thenReturn("2342")
+
+ useCases.newTabSearch(searchTerms, SessionState.Source.Internal.NewTab)
+ store.waitUntilIdle()
+
+ verify(newTabUseCase).invoke(
+ searchUrl,
+ parentId = null,
+ selectTab = true,
+ source = SessionState.Source.Internal.NewTab,
+ isSearch = true,
+ )
+
+ val searchTermsAction = middleware.findFirstAction(ContentAction.UpdateSearchTermsAction::class)
+ assertEquals("2342", searchTermsAction.sessionId)
+ assertEquals(searchTerms, searchTermsAction.searchTerms)
+ }
+
+ @Test
+ fun `GIVEN additional headers and a load url flag WHEN NewTabSearchUseCase creates a new tab THEN addTab is called`() {
+ val source = SessionState.Source.Internal.UserEntered
+ val flags = LoadUrlFlags.select(LoadUrlFlags.ALLOW_JAVASCRIPT_URL)
+ val additionalHeaders = mapOf("X-Extra-Header" to "true")
+ val sessionId = "2342"
+
+ val newTabUseCase: TabsUseCases.AddNewTabUseCase = mock()
+ whenever(tabsUseCases.addTab).thenReturn(newTabUseCase)
+ whenever(
+ newTabUseCase(
+ url = searchUrl,
+ isSearch = true,
+ flags = flags,
+ source = source,
+ additionalHeaders = additionalHeaders,
+ ),
+ ).thenReturn(sessionId)
+
+ useCases.newTabSearch(
+ searchTerms = searchTerms,
+ source = source,
+ flags = flags,
+ additionalHeaders = additionalHeaders,
+ )
+ store.waitUntilIdle()
+
+ verify(newTabUseCase).invoke(
+ url = searchUrl,
+ flags = flags,
+ source = source,
+ isSearch = true,
+ additionalHeaders = additionalHeaders,
+ )
+
+ val searchTermsAction =
+ middleware.findFirstAction(ContentAction.UpdateSearchTermsAction::class)
+ assertEquals(sessionId, searchTermsAction.sessionId)
+ assertEquals(searchTerms, searchTermsAction.searchTerms)
+ }
+
+ @Test
+ fun `DefaultSearchUseCase creates new tab if no session is selected`() {
+ val newTabUseCase: TabsUseCases.AddNewTabUseCase = mock()
+ whenever(tabsUseCases.addTab).thenReturn(newTabUseCase)
+ whenever(newTabUseCase(searchUrl, isSearch = true)).thenReturn("2342")
+
+ useCases.defaultSearch(searchTerms)
+ store.waitUntilIdle()
+
+ verify(newTabUseCase).invoke(
+ searchUrl,
+ parentId = null,
+ selectTab = true,
+ source = SessionState.Source.Internal.NewTab,
+ isSearch = true,
+ )
+
+ val searchTermsAction = middleware.findFirstAction(ContentAction.UpdateSearchTermsAction::class)
+ assertEquals("2342", searchTermsAction.sessionId)
+ assertEquals(searchTerms, searchTermsAction.searchTerms)
+ }
+
+ @Test
+ fun `GIVEN additional headers and a load url flag WHEN DefaultSearchUseCase creates new tab THEN addTab is called`() {
+ val flags = LoadUrlFlags.select(LoadUrlFlags.ALLOW_JAVASCRIPT_URL)
+ val additionalHeaders = mapOf("X-Extra-Header" to "true")
+ val sessionId = "2342"
+
+ val newTabUseCase: TabsUseCases.AddNewTabUseCase = mock()
+ whenever(tabsUseCases.addTab).thenReturn(newTabUseCase)
+ whenever(
+ newTabUseCase(
+ url = searchUrl,
+ flags = flags,
+ isSearch = true,
+ searchEngineName = searchEngineName,
+ additionalHeaders = additionalHeaders,
+ ),
+ ).thenReturn(sessionId)
+
+ useCases.defaultSearch(
+ searchTerms = searchTerms,
+ searchEngine = searchEngine,
+ flags = flags,
+ additionalHeaders = additionalHeaders,
+ )
+ store.waitUntilIdle()
+
+ verify(newTabUseCase).invoke(
+ url = searchUrl,
+ flags = flags,
+ isSearch = true,
+ searchEngineName = searchEngineName,
+ additionalHeaders = additionalHeaders,
+ )
+
+ val searchTermsAction = middleware.findFirstAction(ContentAction.UpdateSearchTermsAction::class)
+ assertEquals(sessionId, searchTermsAction.sessionId)
+ assertEquals(searchTerms, searchTermsAction.searchTerms)
+ }
+
+ @Test
+ fun newPrivateTabSearch() {
+ val newTabUseCase: TabsUseCases.AddNewTabUseCase = mock()
+ whenever(tabsUseCases.addTab).thenReturn(newTabUseCase)
+ whenever(
+ newTabUseCase(
+ searchUrl,
+ source = SessionState.Source.Internal.None,
+ private = true,
+ isSearch = true,
+ ),
+ ).thenReturn("1177")
+
+ useCases.newPrivateTabSearch.invoke(searchTerms)
+ store.waitUntilIdle()
+
+ verify(newTabUseCase).invoke(
+ searchUrl,
+ parentId = null,
+ selectTab = true,
+ private = true,
+ source = SessionState.Source.Internal.None,
+ isSearch = true,
+ )
+
+ val searchTermsAction = middleware.findFirstAction(ContentAction.UpdateSearchTermsAction::class)
+ assertEquals("1177", searchTermsAction.sessionId)
+ assertEquals(searchTerms, searchTermsAction.searchTerms)
+ }
+
+ @Test
+ fun newPrivateTabSearchWithParentSession() {
+ val newTabUseCase: TabsUseCases.AddNewTabUseCase = mock()
+ whenever(tabsUseCases.addTab).thenReturn(newTabUseCase)
+ whenever(
+ newTabUseCase(
+ searchUrl,
+ source = SessionState.Source.Internal.None,
+ parentId = "test-parent",
+ private = true,
+ isSearch = true,
+ ),
+ ).thenReturn("1177")
+
+ useCases.newPrivateTabSearch.invoke(searchTerms, parentSessionId = "test-parent")
+
+ store.waitUntilIdle()
+
+ verify(newTabUseCase).invoke(
+ searchUrl,
+ parentId = "test-parent",
+ selectTab = true,
+ private = true,
+ source = SessionState.Source.Internal.None,
+ isSearch = true,
+ )
+
+ val searchTermsAction = middleware.findFirstAction(ContentAction.UpdateSearchTermsAction::class)
+ assertEquals("1177", searchTermsAction.sessionId)
+ assertEquals(searchTerms, searchTermsAction.searchTerms)
+ }
+
+ @Test
+ fun `Selecting search engine`() {
+ val store = BrowserStore(getBrowserState())
+
+ val useCases = SearchUseCases(store, mock(), mock())
+
+ useCases.selectSearchEngine.invoke(
+ store.findSearchEngineById("engine-d"),
+ )
+
+ store.waitUntilIdle()
+
+ assertEquals("engine-d", store.state.search.userSelectedSearchEngineId)
+ assertNull(store.state.search.userSelectedSearchEngineName)
+
+ useCases.selectSearchEngine.invoke(
+ store.findSearchEngineById("engine-b"),
+ )
+
+ store.waitUntilIdle()
+
+ assertEquals("engine-b", store.state.search.userSelectedSearchEngineId)
+ assertEquals("Engine B", store.state.search.userSelectedSearchEngineName)
+
+ useCases.selectSearchEngine.invoke(
+ store.findSearchEngineById("engine-f"),
+ )
+
+ store.waitUntilIdle()
+
+ assertEquals("engine-f", store.state.search.userSelectedSearchEngineId)
+ assertNull(store.state.search.userSelectedSearchEngineName)
+ }
+
+ @Test
+ fun `addSearchEngine - add bundled engine`() {
+ val store = BrowserStore(getBrowserState())
+
+ val useCases = SearchUseCases(store, mock(), mock())
+
+ assertEquals(7, store.state.search.searchEngines.size)
+ assertEquals(3, store.state.search.availableSearchEngines.size)
+
+ useCases.addSearchEngine.invoke(
+ store.findSearchEngineById("engine-i"),
+ )
+
+ store.waitUntilIdle()
+
+ assertEquals(8, store.state.search.searchEngines.size)
+ assertEquals(2, store.state.search.availableSearchEngines.size)
+
+ assertEquals(4, store.state.search.regionSearchEngines.size)
+ assertEquals(0, store.state.search.hiddenSearchEngines.size)
+
+ assertEquals("engine-i", store.state.search.regionSearchEngines[3].id)
+ assertEquals("Engine I", store.state.search.regionSearchEngines[3].name)
+ }
+
+ @Test
+ fun `addSearchEngine - add additional bundled engine`() {
+ val store = BrowserStore(getBrowserState())
+
+ val useCases = SearchUseCases(store, mock(), mock())
+
+ assertEquals(7, store.state.search.searchEngines.size)
+ assertEquals(3, store.state.search.availableSearchEngines.size)
+
+ useCases.addSearchEngine.invoke(
+ store.findSearchEngineById("engine-h"),
+ )
+
+ store.waitUntilIdle()
+
+ assertEquals(8, store.state.search.searchEngines.size)
+ assertEquals(2, store.state.search.availableSearchEngines.size)
+
+ assertEquals(1, store.state.search.additionalAvailableSearchEngines.size)
+ assertEquals(2, store.state.search.additionalSearchEngines.size)
+
+ assertEquals("engine-h", store.state.search.additionalSearchEngines[1].id)
+ assertEquals("Engine H", store.state.search.additionalSearchEngines[1].name)
+ }
+
+ @Test
+ fun `addSearchEngine - add custom engine`() {
+ val store = BrowserStore(getBrowserState())
+
+ val useCases = SearchUseCases(store, mock(), mock())
+
+ assertEquals(7, store.state.search.searchEngines.size)
+ assertEquals(3, store.state.search.availableSearchEngines.size)
+
+ useCases.addSearchEngine.invoke(
+ createSearchEngine(
+ name = "Engine X",
+ url = "https://www.example.org/?q={searchTerms}",
+ icon = mock(),
+ ),
+ )
+
+ store.waitUntilIdle()
+
+ assertEquals(8, store.state.search.searchEngines.size)
+ assertEquals(3, store.state.search.availableSearchEngines.size)
+
+ assertEquals(3, store.state.search.customSearchEngines.size)
+ assertEquals("Engine X", store.state.search.customSearchEngines[2].name)
+ assertEquals(
+ "https://www.example.org/?q={searchTerms}",
+ store.state.search.customSearchEngines[2].resultUrls[0],
+ )
+ }
+
+ @Test
+ fun `removeSearchEngine - remove bundled engine`() {
+ val store = BrowserStore(getBrowserState())
+
+ val useCases = SearchUseCases(store, mock(), mock())
+
+ assertEquals(7, store.state.search.searchEngines.size)
+ assertEquals(3, store.state.search.availableSearchEngines.size)
+
+ useCases.removeSearchEngine.invoke(
+ store.findSearchEngineById("engine-b"),
+ )
+
+ store.waitUntilIdle()
+
+ assertEquals(6, store.state.search.searchEngines.size)
+ assertEquals(4, store.state.search.availableSearchEngines.size)
+
+ assertEquals(2, store.state.search.regionSearchEngines.size)
+ assertEquals(2, store.state.search.hiddenSearchEngines.size)
+
+ assertEquals("engine-b", store.state.search.hiddenSearchEngines[1].id)
+ assertEquals("Engine B", store.state.search.hiddenSearchEngines[1].name)
+ }
+
+ @Test
+ fun `removeSearchEngine - remove additional bundled engine`() {
+ val store = BrowserStore(getBrowserState())
+
+ val useCases = SearchUseCases(store, mock(), mock())
+
+ assertEquals(7, store.state.search.searchEngines.size)
+ assertEquals(3, store.state.search.availableSearchEngines.size)
+
+ useCases.removeSearchEngine.invoke(
+ store.findSearchEngineById("engine-f"),
+ )
+
+ store.waitUntilIdle()
+
+ assertEquals(6, store.state.search.searchEngines.size)
+ assertEquals(4, store.state.search.availableSearchEngines.size)
+
+ assertEquals(0, store.state.search.additionalSearchEngines.size)
+ assertEquals(3, store.state.search.additionalAvailableSearchEngines.size)
+
+ assertEquals("engine-f", store.state.search.additionalAvailableSearchEngines[2].id)
+ assertEquals("Engine F", store.state.search.additionalAvailableSearchEngines[2].name)
+ }
+
+ @Test
+ fun `removeSearchEngine - remove custom engine`() {
+ val store = BrowserStore(getBrowserState())
+
+ val useCases = SearchUseCases(store, mock(), mock())
+
+ assertEquals(7, store.state.search.searchEngines.size)
+ assertEquals(3, store.state.search.availableSearchEngines.size)
+
+ useCases.removeSearchEngine.invoke(
+ store.findSearchEngineById("engine-d"),
+ )
+
+ store.waitUntilIdle()
+
+ assertEquals(6, store.state.search.searchEngines.size)
+ assertEquals(3, store.state.search.availableSearchEngines.size)
+
+ assertEquals(1, store.state.search.customSearchEngines.size)
+ }
+
+ @Test
+ fun `GIVEN disable search engine use case is invoked WHEN engine gets unselected THEN ID is stored in search state`() {
+ val store = BrowserStore(getBrowserState())
+ val useCases = SearchUseCases(store, mock(), mock())
+
+ assertEquals(0, store.state.search.disabledSearchEngineIds.size)
+
+ useCases.updateDisabledSearchEngineIds.invoke(
+ searchEngineId = "engine-d",
+ isEnabled = false,
+ )
+ store.waitUntilIdle()
+
+ assertEquals(1, store.state.search.disabledSearchEngineIds.size)
+ }
+
+ @Test
+ fun `GIVEN disable search engine use case is invoked WHEN engine gets selected THEN ID is removed from search state`() {
+ val store = BrowserStore(getBrowserState(disabledSearchEngineIds = listOf("engine-d")))
+ val useCases = SearchUseCases(store, mock(), mock())
+
+ assertEquals(1, store.state.search.disabledSearchEngineIds.size)
+
+ useCases.updateDisabledSearchEngineIds.invoke(
+ searchEngineId = "engine-d",
+ isEnabled = true,
+ )
+ store.waitUntilIdle()
+
+ assertEquals(0, store.state.search.disabledSearchEngineIds.size)
+ }
+
+ @Test
+ fun `WHEN restore search engines use case is invoked GIVEN there are hidden engines THEN hidden engines are added back to the bundled engine list`() {
+ val regionSearchEngines = listOf(
+ SearchEngine("bundled-engine-a", "Regional Engine A", mock(), type = SearchEngine.Type.BUNDLED),
+ SearchEngine("bundled-engine-b", "Regional Engine B", mock(), type = SearchEngine.Type.BUNDLED),
+ )
+
+ val hiddenEngine = SearchEngine(
+ "bundled-engine-c",
+ "Regional Engine C",
+ mock(),
+ type = SearchEngine.Type.BUNDLED,
+ )
+
+ val store = BrowserStore(getBrowserState(hiddenSearchEngine = listOf(hiddenEngine), regionSearchEngines = regionSearchEngines))
+ val useCases = SearchUseCases(store, mock(), mock())
+
+ assertEquals(2, store.state.search.regionSearchEngines.size)
+ assertEquals(1, store.state.search.hiddenSearchEngines.size)
+
+ assertEquals("bundled-engine-a", store.state.search.regionSearchEngines[0].id)
+ assertEquals("bundled-engine-b", store.state.search.regionSearchEngines[1].id)
+ assertEquals("bundled-engine-c", store.state.search.hiddenSearchEngines[0].id)
+
+ useCases.restoreHiddenSearchEngines.invoke()
+ store.waitUntilIdle()
+
+ assertEquals(3, store.state.search.regionSearchEngines.size)
+ assertEquals(0, store.state.search.hiddenSearchEngines.size)
+
+ assertEquals("bundled-engine-a", store.state.search.regionSearchEngines[0].id)
+ assertEquals("bundled-engine-b", store.state.search.regionSearchEngines[1].id)
+ assertEquals("bundled-engine-c", store.state.search.regionSearchEngines[2].id)
+ }
+
+ @Test
+ fun `WHEN restore search engines use case is invoked GIVEN there are no hidden engines THEN do nothing`() {
+ val regionSearchEngines = listOf(
+ SearchEngine("bundled-engine-a", "Regional Engine A", mock(), type = SearchEngine.Type.BUNDLED),
+ SearchEngine("bundled-engine-b", "Regional Engine B", mock(), type = SearchEngine.Type.BUNDLED),
+ SearchEngine("bundled-engine-c", "Regional Engine C", mock(), type = SearchEngine.Type.BUNDLED),
+ )
+ val store = BrowserStore(getBrowserState(hiddenSearchEngine = emptyList(), regionSearchEngines = regionSearchEngines))
+ val useCases = SearchUseCases(store, mock(), mock())
+
+ assertEquals(0, store.state.search.hiddenSearchEngines.size)
+ assertEquals(3, store.state.search.regionSearchEngines.size)
+
+ assertEquals("bundled-engine-a", store.state.search.regionSearchEngines[0].id)
+ assertEquals("bundled-engine-b", store.state.search.regionSearchEngines[1].id)
+ assertEquals("bundled-engine-c", store.state.search.regionSearchEngines[2].id)
+
+ useCases.restoreHiddenSearchEngines.invoke()
+ store.waitUntilIdle()
+
+ assertEquals(0, store.state.search.hiddenSearchEngines.size)
+ assertEquals(3, store.state.search.regionSearchEngines.size)
+
+ assertEquals("bundled-engine-a", store.state.search.regionSearchEngines[0].id)
+ assertEquals("bundled-engine-b", store.state.search.regionSearchEngines[1].id)
+ assertEquals("bundled-engine-c", store.state.search.regionSearchEngines[2].id)
+ }
+}
+
+private fun getBrowserState(
+ disabledSearchEngineIds: List<String> = emptyList(),
+ regionSearchEngines: List<SearchEngine> = listOf(
+ SearchEngine("engine-a", "Engine A", mock(), type = SearchEngine.Type.BUNDLED),
+ SearchEngine("engine-b", "Engine B", mock(), type = SearchEngine.Type.BUNDLED),
+ SearchEngine("engine-c", "Engine C", mock(), type = SearchEngine.Type.BUNDLED),
+ ),
+ hiddenSearchEngine: List<SearchEngine> = listOf(
+ SearchEngine(
+ "engine-i",
+ "Engine I",
+ mock(),
+ type = SearchEngine.Type.BUNDLED,
+ ),
+ ),
+) = BrowserState(
+ search = SearchState(
+ region = RegionState("US", "US"),
+ regionSearchEngines = regionSearchEngines,
+ customSearchEngines = listOf(
+ SearchEngine("engine-d", "Engine D", mock(), type = SearchEngine.Type.CUSTOM),
+ SearchEngine("engine-e", "Engine E", mock(), type = SearchEngine.Type.CUSTOM),
+ ),
+ applicationSearchEngines = listOf(
+ SearchEngine("engine-j", "Engine J", mock(), type = SearchEngine.Type.APPLICATION),
+ ),
+ additionalSearchEngines = listOf(
+ SearchEngine("engine-f", "Engine F", mock(), type = SearchEngine.Type.BUNDLED_ADDITIONAL),
+ ),
+ additionalAvailableSearchEngines = listOf(
+ SearchEngine("engine-g", "Engine G", mock(), type = SearchEngine.Type.BUNDLED_ADDITIONAL),
+ SearchEngine("engine-h", "Engine H", mock(), type = SearchEngine.Type.BUNDLED_ADDITIONAL),
+ ),
+ hiddenSearchEngines = hiddenSearchEngine,
+ disabledSearchEngineIds = disabledSearchEngineIds,
+ regionDefaultSearchEngineId = "engine-b",
+ userSelectedSearchEngineId = null,
+ userSelectedSearchEngineName = null,
+ ),
+)
+
+private fun BrowserStore.findSearchEngineById(id: String): SearchEngine {
+ val searchEngine = (state.search.searchEngines + state.search.availableSearchEngines).find {
+ it.id == id
+ }
+ return requireNotNull(searchEngine)
+}
diff --git a/mobile/android/android-components/components/feature/search/src/test/java/mozilla/components/feature/search/ext/BrowserStoreKtTest.kt b/mobile/android/android-components/components/feature/search/src/test/java/mozilla/components/feature/search/ext/BrowserStoreKtTest.kt
new file mode 100644
index 0000000000..c29082e0e1
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/test/java/mozilla/components/feature/search/ext/BrowserStoreKtTest.kt
@@ -0,0 +1,117 @@
+/* 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.feature.search.ext
+
+import mozilla.components.browser.state.action.SearchAction
+import mozilla.components.browser.state.search.SearchEngine
+import mozilla.components.browser.state.state.BrowserState
+import mozilla.components.browser.state.state.SearchState
+import mozilla.components.browser.state.store.BrowserStore
+import mozilla.components.support.test.mock
+import org.junit.Assert.assertEquals
+import org.junit.Assert.assertNotNull
+import org.junit.Assert.assertNull
+import org.junit.Assert.assertTrue
+import org.junit.Test
+import java.util.concurrent.CountDownLatch
+import java.util.concurrent.TimeUnit
+
+class BrowserStoreKtTest {
+ @Test
+ fun `waitForDefaultSearchEngine - with state already loaded`() {
+ val store = BrowserStore(
+ BrowserState(
+ search = SearchState(
+ regionSearchEngines = listOf(
+ SearchEngine(
+ id = "google",
+ name = "Google",
+ icon = mock(),
+ type = SearchEngine.Type.BUNDLED,
+ ),
+ ),
+ userSelectedSearchEngineId = "google",
+ complete = true,
+ ),
+ ),
+ )
+
+ val latch = CountDownLatch(1)
+
+ store.waitForSelectedOrDefaultSearchEngine { searchEngine ->
+ assertNotNull(searchEngine)
+ assertEquals("google", searchEngine!!.id)
+ latch.countDown()
+ }
+
+ assertTrue(latch.await(10, TimeUnit.SECONDS))
+ }
+
+ @Test
+ fun `waitForDefaultSearchEngine - with state dispatched later`() {
+ val store = BrowserStore()
+
+ val latch = CountDownLatch(1)
+
+ store.waitForSelectedOrDefaultSearchEngine { searchEngine ->
+ assertNotNull(searchEngine)
+ assertEquals("google", searchEngine!!.id)
+ latch.countDown()
+ }
+
+ store.dispatch(
+ SearchAction.SetSearchEnginesAction(
+ regionSearchEngines = listOf(
+ SearchEngine(
+ id = "google",
+ name = "Google",
+ icon = mock(),
+ type = SearchEngine.Type.BUNDLED,
+ ),
+ ),
+ userSelectedSearchEngineId = null,
+ userSelectedSearchEngineName = null,
+ regionDefaultSearchEngineId = "google",
+ customSearchEngines = emptyList(),
+ hiddenSearchEngines = emptyList(),
+ disabledSearchEngineIds = emptyList(),
+ additionalAvailableSearchEngines = emptyList(),
+ additionalSearchEngines = emptyList(),
+ regionSearchEnginesOrder = listOf("google"),
+ ),
+ )
+
+ assertTrue(latch.await(10, TimeUnit.SECONDS))
+ }
+
+ @Test
+ fun `waitForDefaultSearchEngine - no default was loaded`() {
+ val store = BrowserStore()
+
+ val latch = CountDownLatch(1)
+
+ store.waitForSelectedOrDefaultSearchEngine { searchEngine ->
+ assertNull(searchEngine)
+ latch.countDown()
+ }
+
+ store.dispatch(
+ SearchAction.SetSearchEnginesAction(
+ regionSearchEngines = listOf(),
+ userSelectedSearchEngineId = null,
+ userSelectedSearchEngineName = null,
+ regionDefaultSearchEngineId = "default",
+ customSearchEngines = emptyList(),
+ hiddenSearchEngines = emptyList(),
+ disabledSearchEngineIds = emptyList(),
+ additionalAvailableSearchEngines = emptyList(),
+ additionalSearchEngines = emptyList(),
+ regionSearchEnginesOrder = listOf("google"),
+ ),
+ )
+
+ assertTrue(latch.await(10, TimeUnit.SECONDS))
+ }
+}
diff --git a/mobile/android/android-components/components/feature/search/src/test/java/mozilla/components/feature/search/ext/SearchEngineKtTest.kt b/mobile/android/android-components/components/feature/search/src/test/java/mozilla/components/feature/search/ext/SearchEngineKtTest.kt
new file mode 100644
index 0000000000..6c117132ff
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/test/java/mozilla/components/feature/search/ext/SearchEngineKtTest.kt
@@ -0,0 +1,196 @@
+/* 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.feature.search.ext
+
+import android.graphics.Bitmap
+import android.net.Uri
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import mozilla.components.browser.state.search.SearchEngine
+import mozilla.components.browser.state.state.SearchState
+import mozilla.components.support.test.mock
+import org.junit.Assert.assertEquals
+import org.junit.Assert.assertNotNull
+import org.junit.Assert.assertNull
+import org.junit.Test
+import org.junit.runner.RunWith
+import java.util.UUID
+
+@RunWith(AndroidJUnit4::class)
+class SearchEngineKtTest {
+
+ @Test
+ fun `WHEN search engine is created THEN the correct properties are set`() {
+ val name = "name"
+ val url = "https://www.example.com/search?q={searchTerms}"
+ val icon: Bitmap = mock()
+ val suggestUrl = "https://www.example.com/search"
+ val isGeneral = true
+ val searchEngine = createSearchEngine(
+ name = name,
+ url = url,
+ icon = icon,
+ suggestUrl = suggestUrl,
+ isGeneral = isGeneral,
+ )
+
+ assertNotNull(searchEngine.id)
+ assertEquals(name, searchEngine.name)
+ assertEquals(icon, searchEngine.icon)
+ assertEquals(SearchEngine.Type.CUSTOM, searchEngine.type)
+ assertEquals(listOf(url), searchEngine.resultUrls)
+ assertEquals(suggestUrl, searchEngine.suggestUrl)
+ assertEquals(isGeneral, searchEngine.isGeneral)
+ }
+
+ @Test
+ fun `Create search URL for startpage`() {
+ val searchEngine = SearchEngine(
+ id = UUID.randomUUID().toString(),
+ name = "Escosia",
+ icon = mock(),
+ type = SearchEngine.Type.CUSTOM,
+ resultUrls = listOf(
+ "https://www.startpage.com/sp/search?q={searchTerms}",
+ ),
+ )
+
+ assertEquals(
+ "https://www.startpage.com/sp/search?q=Hello%20World",
+ searchEngine.buildSearchUrl("Hello World"),
+ )
+ }
+
+ @Test
+ fun `Create search URL for ecosia`() {
+ val searchEngine = createSearchEngine(
+ name = "Ecosia",
+ icon = mock(),
+ url = "https://www.ecosia.org/search?q={searchTerms}",
+ )
+
+ assertEquals(
+ "https://www.ecosia.org/search?q=Hello%20World",
+ searchEngine.buildSearchUrl("Hello World"),
+ )
+ }
+
+ @Test
+ fun `GIVEN ecosia search engine and a set of urls THEN search terms are determined when present`() {
+ val searchEngine = createSearchEngine(
+ name = "Ecosia",
+ icon = mock(),
+ url = "https://www.ecosia.org/search?q={searchTerms}",
+ )
+
+ assertNull(searchEngine.parseSearchTerms(Uri.parse("https://www.ecosia.org/search?q=")))
+ assertNull(searchEngine.parseSearchTerms(Uri.parse("https://www.ecosia.org/search?attr=moz-test")))
+
+ assertEquals(
+ "second test search",
+ searchEngine.parseSearchTerms(Uri.parse("https://www.ecosia.org/search?q=second%20test%20search")),
+ )
+
+ assertEquals(
+ "Another test",
+ searchEngine.parseSearchTerms(Uri.parse("https://www.ecosia.org/search?r=134s7&attr=moz-test&q=Another%20test&d=136697676793")),
+ )
+ }
+
+ @Test
+ fun `GIVEN empty search state THEN search terms are never determined`() {
+ val searchState = SearchState()
+ assertNull(searchState.parseSearchTerms("https://google.com/search/?q=the%20sandbaggers"))
+ }
+
+ @Test
+ fun `GIVEN a search state and a set of urls THEN search terms are determined when present`() {
+ val google = createSearchEngine(
+ name = "Google",
+ icon = mock(),
+ url = "https://google.com/search/?q={searchTerms}",
+ )
+ val ecosia = createSearchEngine(
+ name = "Ecosia",
+ icon = mock(),
+ url = "https://www.ecosia.org/search?q={searchTerms}",
+ )
+ val baidu = createSearchEngine(
+ name = "Baidu",
+ icon = mock(),
+ url = "https://www.baidu.com/s?wd={searchTerms}",
+ )
+ val searchState = SearchState(
+ regionSearchEngines = listOf(google, baidu),
+ additionalSearchEngines = listOf(ecosia),
+ customSearchEngines = listOf(baidu, ecosia),
+ )
+
+ assertNull(searchState.parseSearchTerms("https://www.ecosia.org/search?q="))
+ assertNull(searchState.parseSearchTerms("http://help.baidu.com/"))
+ assertEquals(
+ "神舟十二号载人飞行任务标识发布",
+ searchState.parseSearchTerms("https://www.baidu.com/s?cl=3&tn=baidutop10&fr=top1000&wd=%E7%A5%9E%E8%88%9F%E5%8D%81%E4%BA%8C%E5%8F%B7%E8%BD%BD%E4%BA%BA%E9%A3%9E%E8%A1%8C%E4%BB%BB%E5%8A%A1%E6%A0%87%E8%AF%86%E5%8F%91%E5%B8%83&rsv_idx=2&rsv_dl=fyb_n_homepage&hisfilter=1"),
+ )
+ assertEquals(
+ "the sandbaggers",
+ searchState.parseSearchTerms("https://google.com/search/?q=the%20sandbaggers"),
+ )
+ assertEquals(
+ "фаерфокс",
+ searchState.parseSearchTerms("https://google.com/search/?q=%D1%84%D0%B0%D0%B5%D1%80%D1%84%D0%BE%D0%BA%D1%81"),
+ )
+ assertEquals(
+ "Another test",
+ searchState.parseSearchTerms("https://www.ecosia.org/search?r=134s7&attr=moz-test&q=Another%20test&d=136697676793"),
+ )
+ }
+
+ @Test
+ fun `GIVEN search engine parameter can not be found THEN search terms are never determined`() {
+ val invalidEngine = SearchEngine(
+ id = UUID.randomUUID().toString(),
+ name = "invalid",
+ icon = mock(),
+ type = SearchEngine.Type.CUSTOM,
+ resultUrls = listOf("https://mozilla.org/search/?q={invalid}"),
+ )
+
+ val searchState = SearchState(
+ regionSearchEngines = listOf(invalidEngine),
+ )
+
+ assertNull(searchState.parseSearchTerms("https://mozilla.org/search/?q=test"))
+ }
+
+ @Test
+ fun `GIVEN a search state and a set of input encoding THEN search terms are encoded by input encoding parameter`() {
+ val searchEngine = createSearchEngine(
+ name = "Yahoo! Auctions",
+ icon = mock(),
+ url = "https://auctions.yahoo.co.jp/search/search&p={searchTerms}",
+ inputEncoding = "EUC-JP",
+ )
+
+ assertEquals(
+ "https://auctions.yahoo.co.jp/search/search&p=%A5%D5%A5%A1%A5%A4%A5%E4%A1%BC%A5%D5%A5%A9%A5%C3%A5%AF%A5%B9",
+ searchEngine.buildSearchUrl("ファイヤーフォックス"),
+ )
+ }
+
+ @Test
+ fun `GIVEN invalid input encoding THEN encoding of search terms are determined as UTF-8`() {
+ val searchEngine = createSearchEngine(
+ name = "name",
+ icon = mock(),
+ url = "https://www.example.com/search?q={searchTerms}",
+ inputEncoding = "INVALID-ENOCODING",
+ )
+
+ assertEquals(
+ "https://www.example.com/search?q=%E7%81%AB%E7%8B%90",
+ searchEngine.buildSearchUrl("火狐"),
+ )
+ }
+}
diff --git a/mobile/android/android-components/components/feature/search/src/test/java/mozilla/components/feature/search/middleware/AdsTelemetryMiddlewareTest.kt b/mobile/android/android-components/components/feature/search/src/test/java/mozilla/components/feature/search/middleware/AdsTelemetryMiddlewareTest.kt
new file mode 100644
index 0000000000..b144facd8e
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/test/java/mozilla/components/feature/search/middleware/AdsTelemetryMiddlewareTest.kt
@@ -0,0 +1,126 @@
+/* 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.feature.search.middleware
+
+import mozilla.components.browser.state.action.ContentAction
+import mozilla.components.browser.state.action.TabListAction
+import mozilla.components.browser.state.state.BrowserState
+import mozilla.components.browser.state.state.ContentState
+import mozilla.components.browser.state.state.LoadRequestState
+import mozilla.components.browser.state.state.TabSessionState
+import mozilla.components.browser.state.state.createTab
+import mozilla.components.browser.state.store.BrowserStore
+import mozilla.components.feature.search.telemetry.ads.AdsTelemetry
+import mozilla.components.support.test.ext.joinBlocking
+import mozilla.components.support.test.mock
+import org.junit.Assert.assertEquals
+import org.junit.Assert.assertNotNull
+import org.junit.Assert.assertNull
+import org.junit.Before
+import org.junit.Test
+import org.mockito.Mockito.verify
+
+class AdsTelemetryMiddlewareTest {
+ val sessionId = "session"
+ lateinit var adsMiddleware: AdsTelemetryMiddleware
+ lateinit var browserState: BrowserState
+
+ @Before
+ fun setup() {
+ adsMiddleware = AdsTelemetryMiddleware(mock())
+ browserState = BrowserState(
+ tabs = listOf(TabSessionState(content = ContentState("https://mozilla.org"), id = sessionId)),
+ )
+ }
+
+ @Test
+ fun `GIVEN redirectChain empty WHEN a new URL loads THEN the redirectChain starts from the current tab url`() {
+ val store = BrowserStore(
+ initialState = browserState,
+ middleware = listOf(adsMiddleware),
+ )
+
+ store.dispatch(
+ ContentAction.UpdateLoadRequestAction(
+ sessionId,
+ LoadRequestState(
+ url = "https://mozilla.org/firefox",
+ triggeredByRedirect = false,
+ triggeredByUser = false,
+ ),
+ ),
+ ).joinBlocking()
+
+ assertEquals(1, adsMiddleware.redirectChain.size)
+ assertEquals("https://mozilla.org", adsMiddleware.redirectChain[sessionId]!!.root)
+ }
+
+ @Test
+ fun `GIVEN redirectChain is not empty WHEN a new URL loads THEN that URL is added to the chain`() {
+ adsMiddleware.redirectChain[sessionId] = RedirectChain("https://mozilla.org")
+ val store = BrowserStore(
+ initialState = browserState,
+ middleware = listOf(adsMiddleware),
+ )
+
+ store.dispatch(
+ ContentAction.UpdateLoadRequestAction(
+ sessionId,
+ LoadRequestState(
+ url = "https://mozilla.org/firefox",
+ triggeredByRedirect = false,
+ triggeredByUser = false,
+ ),
+ ),
+ ).joinBlocking()
+
+ assertEquals(1, adsMiddleware.redirectChain.size)
+ assertEquals("https://mozilla.org", adsMiddleware.redirectChain[sessionId]!!.root)
+ assertEquals(1, adsMiddleware.redirectChain.size)
+ assertEquals("https://mozilla.org/firefox", adsMiddleware.redirectChain[sessionId]!!.chain[0])
+ }
+
+ @Test
+ fun `WHEN the session URL is updated THEN check if an ad was clicked`() {
+ val adsTelemetry: AdsTelemetry = mock()
+ val adsMiddleware = AdsTelemetryMiddleware(adsTelemetry)
+ adsMiddleware.redirectChain[sessionId] = RedirectChain("https://mozilla.org")
+ adsMiddleware.redirectChain[sessionId]!!.chain.add("https://mozilla.org/firefox")
+ val store = BrowserStore(
+ initialState = browserState,
+ middleware = listOf(adsMiddleware),
+ )
+
+ store
+ .dispatch(ContentAction.UpdateUrlAction(sessionId, "https://mozilla.org/firefox"))
+ .joinBlocking()
+
+ verify(adsTelemetry).checkIfAddWasClicked(
+ "https://mozilla.org",
+ listOf("https://mozilla.org/firefox"),
+ )
+ }
+
+ @Test
+ fun `GIVEN a location update WHEN ads telemetry is recorded THEN redirect chain is reset`() {
+ val tab = createTab(id = "1", url = "http://mozilla.org")
+ val store = BrowserStore(
+ initialState = browserState,
+ middleware = listOf(adsMiddleware),
+ )
+ store.dispatch(TabListAction.AddTabAction(tab)).joinBlocking()
+ store.dispatch(
+ ContentAction.UpdateLoadRequestAction(
+ tab.id,
+ LoadRequestState("https://mozilla.org", true, true),
+ ),
+ ).joinBlocking()
+
+ assertNotNull(adsMiddleware.redirectChain[tab.id])
+
+ store.dispatch(ContentAction.UpdateUrlAction(tab.id, "https://mozilla.org")).joinBlocking()
+ assertNull(adsMiddleware.redirectChain[tab.id])
+ }
+}
diff --git a/mobile/android/android-components/components/feature/search/src/test/java/mozilla/components/feature/search/middleware/SearchMiddlewareTest.kt b/mobile/android/android-components/components/feature/search/src/test/java/mozilla/components/feature/search/middleware/SearchMiddlewareTest.kt
new file mode 100644
index 0000000000..a93a6e1700
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/test/java/mozilla/components/feature/search/middleware/SearchMiddlewareTest.kt
@@ -0,0 +1,1921 @@
+/* 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.feature.search.middleware
+
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import kotlinx.coroutines.test.TestDispatcher
+import mozilla.components.browser.state.action.SearchAction
+import mozilla.components.browser.state.search.RegionState
+import mozilla.components.browser.state.search.SearchEngine
+import mozilla.components.browser.state.state.availableSearchEngines
+import mozilla.components.browser.state.state.searchEngines
+import mozilla.components.browser.state.state.selectedOrDefaultSearchEngine
+import mozilla.components.browser.state.store.BrowserStore
+import mozilla.components.feature.search.ext.createSearchEngine
+import mozilla.components.feature.search.storage.CustomSearchEngineStorage
+import mozilla.components.feature.search.storage.SearchMetadataStorage
+import mozilla.components.support.test.ext.joinBlocking
+import mozilla.components.support.test.fakes.android.FakeSharedPreferences
+import mozilla.components.support.test.libstate.ext.waitUntilIdle
+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.After
+import org.junit.Assert.assertEquals
+import org.junit.Assert.assertFalse
+import org.junit.Assert.assertNotNull
+import org.junit.Assert.assertNull
+import org.junit.Assert.assertTrue
+import org.junit.Before
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.Mockito.doReturn
+import org.mockito.Mockito.verify
+import org.mockito.Mockito.verifyNoMoreInteractions
+import java.util.Locale
+import java.util.UUID
+
+@RunWith(AndroidJUnit4::class)
+class SearchMiddlewareTest {
+ @get:Rule
+ val coroutinesTestRule = MainCoroutineRule()
+ private val dispatcher = coroutinesTestRule.testDispatcher
+
+ private lateinit var originalLocale: Locale
+
+ @Before
+ fun setUp() {
+ originalLocale = Locale.getDefault()
+ }
+
+ @After
+ fun tearDown() {
+ if (Locale.getDefault() != originalLocale) {
+ Locale.setDefault(originalLocale)
+ }
+ }
+
+ @Test
+ fun `Loads search engines for locale (US)`() {
+ val searchMiddleware = SearchMiddleware(
+ testContext,
+ ioDispatcher = dispatcher,
+ customStorage = CustomSearchEngineStorage(testContext, dispatcher),
+ )
+
+ val store = BrowserStore(
+ middleware = listOf(searchMiddleware),
+ )
+
+ assertTrue(store.state.search.regionSearchEngines.isEmpty())
+
+ store.dispatch(
+ SearchAction.SetRegionAction(
+ RegionState("US", "US"),
+ ),
+ ).joinBlocking()
+
+ wait(store, dispatcher)
+
+ assertTrue(store.state.search.regionSearchEngines.isNotEmpty())
+ assertTrue(store.state.search.additionalAvailableSearchEngines.isEmpty())
+ assertTrue(store.state.search.additionalSearchEngines.isEmpty())
+
+ assertNotNull(store.state.search.regionSearchEngines.find { it.name == "Google" })
+ assertNull(store.state.search.regionSearchEngines.find { it.name == "Yandex" })
+ }
+
+ @Test
+ fun `WHEN distribution doesn't exist THEN Loads default search engines`() {
+ val searchMiddleware = SearchMiddleware(
+ testContext,
+ ioDispatcher = dispatcher,
+ customStorage = CustomSearchEngineStorage(testContext, dispatcher),
+ )
+
+ val store = BrowserStore(
+ middleware = listOf(searchMiddleware),
+ )
+
+ assertTrue(store.state.search.regionSearchEngines.isEmpty())
+
+ store.dispatch(
+ SearchAction.SetRegionAction(
+ RegionState("US", "US"),
+ "test",
+ ),
+ ).joinBlocking()
+
+ wait(store, dispatcher)
+
+ assertTrue(store.state.search.regionSearchEngines.isNotEmpty())
+ assertTrue(store.state.search.additionalAvailableSearchEngines.isEmpty())
+ assertTrue(store.state.search.additionalSearchEngines.isEmpty())
+
+ assertNotNull(store.state.search.regionSearchEngines.find { it.name == "Google" })
+ assertNull(store.state.search.regionSearchEngines.find { it.name == "Yandex" })
+ }
+
+ fun `Loads search engines for locale (An)`() {
+ Locale.setDefault(Locale("an", "AN"))
+ val searchMiddleware = SearchMiddleware(
+ testContext,
+ ioDispatcher = dispatcher,
+ customStorage = CustomSearchEngineStorage(testContext, dispatcher),
+ )
+
+ val store = BrowserStore(
+ middleware = listOf(searchMiddleware),
+ )
+
+ assertTrue(store.state.search.regionSearchEngines.isEmpty())
+
+ store.dispatch(
+ SearchAction.SetRegionAction(
+ RegionState("AN", "AN"),
+ ),
+ ).joinBlocking()
+
+ wait(store, dispatcher)
+
+ assertTrue(store.state.search.regionSearchEngines.isNotEmpty())
+ assertTrue(store.state.search.additionalAvailableSearchEngines.isEmpty())
+ assertTrue(store.state.search.additionalSearchEngines.isEmpty())
+
+ assertEquals(5, store.state.search.regionSearchEngines.size)
+
+ assertEquals("Google", store.state.search.regionSearchEngines[0].name)
+ assertEquals("Bing", store.state.search.regionSearchEngines[1].name)
+ assertEquals("DuckDuckGo", store.state.search.regionSearchEngines[2].name)
+ assertEquals("eBay", store.state.search.regionSearchEngines[3].name)
+ assertEquals("Wikipedia", store.state.search.regionSearchEngines[4].name)
+
+ assertEquals("Google", store.state.search.selectedOrDefaultSearchEngine!!.name)
+ }
+
+ @Test
+ fun `Loads search engines for locale (CA)`() {
+ Locale.setDefault(Locale("CA", "CA"))
+ val searchMiddleware = SearchMiddleware(
+ testContext,
+ ioDispatcher = dispatcher,
+ customStorage = CustomSearchEngineStorage(testContext, dispatcher),
+ )
+
+ val store = BrowserStore(
+ middleware = listOf(searchMiddleware),
+ )
+
+ assertTrue(store.state.search.regionSearchEngines.isEmpty())
+
+ store.dispatch(
+ SearchAction.SetRegionAction(
+ RegionState("CA", "CA"),
+ ),
+ ).joinBlocking()
+
+ wait(store, dispatcher)
+
+ assertTrue(store.state.search.regionSearchEngines.isNotEmpty())
+ assertTrue(store.state.search.additionalAvailableSearchEngines.isEmpty())
+ assertTrue(store.state.search.additionalSearchEngines.isEmpty())
+
+ assertEquals(5, store.state.search.regionSearchEngines.size)
+
+ assertEquals("Google", store.state.search.regionSearchEngines[0].name)
+ assertEquals("Bing", store.state.search.regionSearchEngines[1].name)
+ assertEquals("DuckDuckGo", store.state.search.regionSearchEngines[2].name)
+ assertEquals("eBay", store.state.search.regionSearchEngines[3].name)
+ assertEquals("Viquipèdia (ca)", store.state.search.regionSearchEngines[4].name)
+
+ assertEquals("Google", store.state.search.selectedOrDefaultSearchEngine!!.name)
+ }
+
+ @Test
+ fun `Loads search engines for locale (CY)`() {
+ Locale.setDefault(Locale("cy", "CY"))
+ val searchMiddleware = SearchMiddleware(
+ testContext,
+ ioDispatcher = dispatcher,
+ customStorage = CustomSearchEngineStorage(testContext, dispatcher),
+ )
+
+ val store = BrowserStore(
+ middleware = listOf(searchMiddleware),
+ )
+
+ assertTrue(store.state.search.regionSearchEngines.isEmpty())
+
+ store.dispatch(
+ SearchAction.SetRegionAction(
+ RegionState("CY", "CY"),
+ ),
+ ).joinBlocking()
+
+ wait(store, dispatcher)
+
+ assertTrue(store.state.search.regionSearchEngines.isNotEmpty())
+ assertTrue(store.state.search.additionalAvailableSearchEngines.isEmpty())
+ assertTrue(store.state.search.additionalSearchEngines.isEmpty())
+
+ assertEquals(6, store.state.search.regionSearchEngines.size)
+
+ assertEquals("Google", store.state.search.regionSearchEngines[0].name)
+ assertEquals("Bing", store.state.search.regionSearchEngines[1].name)
+ assertEquals("Amazon.co.uk", store.state.search.regionSearchEngines[2].name)
+ assertEquals("DuckDuckGo", store.state.search.regionSearchEngines[3].name)
+ assertEquals("eBay", store.state.search.regionSearchEngines[4].name)
+ assertEquals("Wicipedia (cy)", store.state.search.regionSearchEngines[5].name)
+
+ assertEquals("Google", store.state.search.selectedOrDefaultSearchEngine!!.name)
+ }
+
+ @Test
+ fun `Loads search engines for locale (fy-NL)`() {
+ Locale.setDefault(Locale("fy", "NL"))
+ val searchMiddleware = SearchMiddleware(
+ testContext,
+ ioDispatcher = dispatcher,
+ customStorage = CustomSearchEngineStorage(testContext, dispatcher),
+ )
+
+ val store = BrowserStore(
+ middleware = listOf(searchMiddleware),
+ )
+
+ assertTrue(store.state.search.regionSearchEngines.isEmpty())
+
+ store.dispatch(
+ SearchAction.SetRegionAction(
+ RegionState("FY", "NL"),
+ ),
+ ).joinBlocking()
+
+ wait(store, dispatcher)
+
+ assertTrue(store.state.search.regionSearchEngines.isNotEmpty())
+ assertTrue(store.state.search.additionalAvailableSearchEngines.isEmpty())
+ assertTrue(store.state.search.additionalSearchEngines.isEmpty())
+
+ assertEquals(5, store.state.search.regionSearchEngines.size)
+
+ assertEquals("Google", store.state.search.regionSearchEngines[0].name)
+ assertEquals("Bing", store.state.search.regionSearchEngines[1].name)
+ assertEquals("DuckDuckGo", store.state.search.regionSearchEngines[2].name)
+ assertEquals("eBay", store.state.search.regionSearchEngines[3].name)
+ assertEquals("Wikipedia (fy)", store.state.search.regionSearchEngines[4].name)
+
+ assertEquals("Google", store.state.search.selectedOrDefaultSearchEngine!!.name)
+ }
+
+ @Test
+ fun `Loads search engines for locale (en-AU)`() {
+ Locale.setDefault(Locale("en", "AU"))
+ val searchMiddleware = SearchMiddleware(
+ testContext,
+ ioDispatcher = dispatcher,
+ customStorage = CustomSearchEngineStorage(testContext, dispatcher),
+ )
+
+ val store = BrowserStore(
+ middleware = listOf(searchMiddleware),
+ )
+
+ assertTrue(store.state.search.regionSearchEngines.isEmpty())
+
+ store.dispatch(
+ SearchAction.SetRegionAction(
+ RegionState("EN", "AU"),
+ ),
+ ).joinBlocking()
+
+ wait(store, dispatcher)
+
+ assertTrue(store.state.search.regionSearchEngines.isNotEmpty())
+ assertTrue(store.state.search.additionalAvailableSearchEngines.isEmpty())
+ assertTrue(store.state.search.additionalSearchEngines.isEmpty())
+
+ assertEquals(6, store.state.search.regionSearchEngines.size)
+
+ assertEquals("Google", store.state.search.regionSearchEngines[0].name)
+ assertEquals("Bing", store.state.search.regionSearchEngines[1].name)
+ assertEquals("Amazon.com.au", store.state.search.regionSearchEngines[2].name)
+ assertEquals("DuckDuckGo", store.state.search.regionSearchEngines[3].name)
+ assertEquals("Wikipedia", store.state.search.regionSearchEngines[4].name)
+ assertEquals("eBay", store.state.search.regionSearchEngines[5].name)
+
+ assertEquals("Google", store.state.search.selectedOrDefaultSearchEngine!!.name)
+ }
+
+ @Test
+ fun `Loads search engines for locale (en-GB)`() {
+ Locale.setDefault(Locale("en", "GB"))
+ val searchMiddleware = SearchMiddleware(
+ testContext,
+ ioDispatcher = dispatcher,
+ customStorage = CustomSearchEngineStorage(testContext, dispatcher),
+ )
+
+ val store = BrowserStore(
+ middleware = listOf(searchMiddleware),
+ )
+
+ assertTrue(store.state.search.regionSearchEngines.isEmpty())
+
+ store.dispatch(
+ SearchAction.SetRegionAction(
+ RegionState("EN", "GB"),
+ ),
+ ).joinBlocking()
+
+ wait(store, dispatcher)
+
+ assertTrue(store.state.search.regionSearchEngines.isNotEmpty())
+ assertTrue(store.state.search.additionalAvailableSearchEngines.isEmpty())
+ assertTrue(store.state.search.additionalSearchEngines.isEmpty())
+
+ assertEquals(7, store.state.search.regionSearchEngines.size)
+
+ assertEquals("Google", store.state.search.regionSearchEngines[0].name)
+ assertEquals("Bing", store.state.search.regionSearchEngines[1].name)
+ assertEquals("Amazon.co.uk", store.state.search.regionSearchEngines[2].name)
+ assertEquals("DuckDuckGo", store.state.search.regionSearchEngines[3].name)
+ assertEquals("Qwant", store.state.search.regionSearchEngines[4].name)
+ assertEquals("Wikipedia", store.state.search.regionSearchEngines[5].name)
+ assertEquals("eBay", store.state.search.regionSearchEngines[6].name)
+
+ assertEquals("Google", store.state.search.selectedOrDefaultSearchEngine!!.name)
+ }
+
+ @Test
+ fun `Loads search engines for locale (en-IE)`() {
+ Locale.setDefault(Locale("en", "IE"))
+ val searchMiddleware = SearchMiddleware(
+ testContext,
+ ioDispatcher = dispatcher,
+ customStorage = CustomSearchEngineStorage(testContext, dispatcher),
+ )
+
+ val store = BrowserStore(
+ middleware = listOf(searchMiddleware),
+ )
+
+ assertTrue(store.state.search.regionSearchEngines.isEmpty())
+
+ store.dispatch(
+ SearchAction.SetRegionAction(
+ RegionState("EN", "IE"),
+ ),
+ ).joinBlocking()
+
+ wait(store, dispatcher)
+
+ assertTrue(store.state.search.regionSearchEngines.isNotEmpty())
+ assertTrue(store.state.search.additionalAvailableSearchEngines.isEmpty())
+ assertTrue(store.state.search.additionalSearchEngines.isEmpty())
+
+ assertEquals(7, store.state.search.regionSearchEngines.size)
+
+ assertEquals("Google", store.state.search.regionSearchEngines[0].name)
+ assertEquals("Bing", store.state.search.regionSearchEngines[1].name)
+ assertEquals("Amazon.co.uk", store.state.search.regionSearchEngines[2].name)
+ assertEquals("DuckDuckGo", store.state.search.regionSearchEngines[3].name)
+ assertEquals("Qwant", store.state.search.regionSearchEngines[4].name)
+ assertEquals("Wikipedia", store.state.search.regionSearchEngines[5].name)
+ assertEquals("eBay", store.state.search.regionSearchEngines[6].name)
+
+ assertEquals("Google", store.state.search.selectedOrDefaultSearchEngine!!.name)
+ }
+
+ @Test
+ fun `Loads search engines for locale (fr-BE)`() {
+ Locale.setDefault(Locale("fr", "BE"))
+ val searchMiddleware = SearchMiddleware(
+ testContext,
+ ioDispatcher = dispatcher,
+ customStorage = CustomSearchEngineStorage(testContext, dispatcher),
+ )
+
+ val store = BrowserStore(
+ middleware = listOf(searchMiddleware),
+ )
+
+ assertTrue(store.state.search.regionSearchEngines.isEmpty())
+
+ store.dispatch(
+ SearchAction.SetRegionAction(
+ RegionState("FR", "BE"),
+ ),
+ ).joinBlocking()
+
+ wait(store, dispatcher)
+
+ assertTrue(store.state.search.regionSearchEngines.isNotEmpty())
+ assertTrue(store.state.search.additionalAvailableSearchEngines.isEmpty())
+ assertTrue(store.state.search.additionalSearchEngines.isEmpty())
+
+ assertEquals(6, store.state.search.regionSearchEngines.size)
+
+ assertEquals("Google", store.state.search.regionSearchEngines[0].name)
+ assertEquals("Bing", store.state.search.regionSearchEngines[1].name)
+ assertEquals("DuckDuckGo", store.state.search.regionSearchEngines[2].name)
+ assertEquals("Qwant", store.state.search.regionSearchEngines[3].name)
+ assertEquals("Wikipédia (fr)", store.state.search.regionSearchEngines[4].name)
+ assertEquals("eBay", store.state.search.regionSearchEngines[5].name)
+
+ assertEquals("Google", store.state.search.selectedOrDefaultSearchEngine!!.name)
+ }
+
+ @Test
+ fun `Loads search engines for locale (fr-CA)`() {
+ Locale.setDefault(Locale("fr", "CA"))
+ val searchMiddleware = SearchMiddleware(
+ testContext,
+ ioDispatcher = dispatcher,
+ customStorage = CustomSearchEngineStorage(testContext, dispatcher),
+ )
+
+ val store = BrowserStore(
+ middleware = listOf(searchMiddleware),
+ )
+
+ assertTrue(store.state.search.regionSearchEngines.isEmpty())
+
+ store.dispatch(
+ SearchAction.SetRegionAction(
+ RegionState("FR", "CA"),
+ ),
+ ).joinBlocking()
+
+ wait(store, dispatcher)
+
+ assertTrue(store.state.search.regionSearchEngines.isNotEmpty())
+ assertTrue(store.state.search.additionalAvailableSearchEngines.isEmpty())
+ assertTrue(store.state.search.additionalSearchEngines.isEmpty())
+
+ assertEquals(6, store.state.search.regionSearchEngines.size)
+
+ assertEquals("Google", store.state.search.regionSearchEngines[0].name)
+ assertEquals("Bing", store.state.search.regionSearchEngines[1].name)
+ assertEquals("Amazon.ca", store.state.search.regionSearchEngines[2].name)
+ assertEquals("DuckDuckGo", store.state.search.regionSearchEngines[3].name)
+ assertEquals("Wikipédia (fr)", store.state.search.regionSearchEngines[4].name)
+ assertEquals("eBay", store.state.search.regionSearchEngines[5].name)
+
+ assertEquals("Google", store.state.search.selectedOrDefaultSearchEngine!!.name)
+ }
+
+ @Test
+ fun `Loads search engines for locale (fr-FR)`() {
+ Locale.setDefault(Locale("fr", "FR"))
+ val searchMiddleware = SearchMiddleware(
+ testContext,
+ ioDispatcher = dispatcher,
+ customStorage = CustomSearchEngineStorage(testContext, dispatcher),
+ )
+
+ val store = BrowserStore(
+ middleware = listOf(searchMiddleware),
+ )
+
+ assertTrue(store.state.search.regionSearchEngines.isEmpty())
+
+ store.dispatch(
+ SearchAction.SetRegionAction(
+ RegionState("FR", "FR"),
+ ),
+ ).joinBlocking()
+
+ wait(store, dispatcher)
+
+ assertTrue(store.state.search.regionSearchEngines.isNotEmpty())
+ assertTrue(store.state.search.additionalAvailableSearchEngines.isEmpty())
+ assertTrue(store.state.search.additionalSearchEngines.isEmpty())
+
+ assertEquals(7, store.state.search.regionSearchEngines.size)
+
+ assertEquals("Google", store.state.search.regionSearchEngines[0].name)
+ assertEquals("Bing", store.state.search.regionSearchEngines[1].name)
+ assertEquals("DuckDuckGo", store.state.search.regionSearchEngines[2].name)
+ assertEquals("Qwant", store.state.search.regionSearchEngines[3].name)
+ assertEquals("Wikipédia (fr)", store.state.search.regionSearchEngines[4].name)
+ assertEquals("Amazon.fr", store.state.search.regionSearchEngines[5].name)
+ assertEquals("eBay", store.state.search.regionSearchEngines[6].name)
+
+ assertEquals("Google", store.state.search.selectedOrDefaultSearchEngine!!.name)
+ }
+
+ @Test
+ fun `Loads search engines for locale (de-AT)`() {
+ Locale.setDefault(Locale("de", "AT"))
+ val searchMiddleware = SearchMiddleware(
+ testContext,
+ ioDispatcher = dispatcher,
+ customStorage = CustomSearchEngineStorage(testContext, dispatcher),
+ )
+
+ val store = BrowserStore(
+ middleware = listOf(searchMiddleware),
+ )
+
+ assertTrue(store.state.search.regionSearchEngines.isEmpty())
+
+ store.dispatch(
+ SearchAction.SetRegionAction(
+ RegionState("DE", "AT"),
+ ),
+ ).joinBlocking()
+
+ wait(store, dispatcher)
+
+ assertTrue(store.state.search.regionSearchEngines.isNotEmpty())
+ assertTrue(store.state.search.additionalAvailableSearchEngines.isEmpty())
+ assertTrue(store.state.search.additionalSearchEngines.isEmpty())
+
+ assertEquals(8, store.state.search.regionSearchEngines.size)
+ assertEquals("Google", store.state.search.regionSearchEngines[0].name)
+ assertEquals("Bing", store.state.search.regionSearchEngines[1].name)
+ assertEquals("Amazon.de", store.state.search.regionSearchEngines[2].name)
+ assertEquals("DuckDuckGo", store.state.search.regionSearchEngines[3].name)
+ assertEquals("Ecosia", store.state.search.regionSearchEngines[4].name)
+ assertEquals("Qwant", store.state.search.regionSearchEngines[5].name)
+ assertEquals("Wikipedia (de)", store.state.search.regionSearchEngines[6].name)
+ assertEquals("eBay", store.state.search.regionSearchEngines[7].name)
+
+ assertEquals("Google", store.state.search.selectedOrDefaultSearchEngine!!.name)
+ }
+
+ @Test
+ fun `Loads search engines for locale (DE)`() {
+ Locale.setDefault(Locale("de", "DE"))
+ val searchMiddleware = SearchMiddleware(
+ testContext,
+ ioDispatcher = dispatcher,
+ customStorage = CustomSearchEngineStorage(testContext, dispatcher),
+ )
+
+ val store = BrowserStore(
+ middleware = listOf(searchMiddleware),
+ )
+
+ assertTrue(store.state.search.regionSearchEngines.isEmpty())
+
+ store.dispatch(
+ SearchAction.SetRegionAction(
+ RegionState("DE", "DE"),
+ ),
+ ).joinBlocking()
+
+ wait(store, dispatcher)
+
+ assertTrue(store.state.search.regionSearchEngines.isNotEmpty())
+ assertTrue(store.state.search.additionalAvailableSearchEngines.isEmpty())
+ assertTrue(store.state.search.additionalSearchEngines.isEmpty())
+
+ assertEquals(8, store.state.search.regionSearchEngines.size)
+ assertEquals("Google", store.state.search.regionSearchEngines[0].name)
+ assertEquals("Bing", store.state.search.regionSearchEngines[1].name)
+ assertEquals("Amazon.de", store.state.search.regionSearchEngines[2].name)
+ assertEquals("DuckDuckGo", store.state.search.regionSearchEngines[3].name)
+ assertEquals("Ecosia", store.state.search.regionSearchEngines[4].name)
+ assertEquals("Qwant", store.state.search.regionSearchEngines[5].name)
+ assertEquals("Wikipedia (de)", store.state.search.regionSearchEngines[6].name)
+ assertEquals("eBay", store.state.search.regionSearchEngines[7].name)
+
+ assertEquals("Google", store.state.search.selectedOrDefaultSearchEngine!!.name)
+ }
+
+ @Test
+ fun `Loads search engines for locale (DSB)`() {
+ Locale.setDefault(Locale("dsb", "DE"))
+ val searchMiddleware = SearchMiddleware(
+ testContext,
+ ioDispatcher = dispatcher,
+ customStorage = CustomSearchEngineStorage(testContext, dispatcher),
+ )
+
+ val store = BrowserStore(
+ middleware = listOf(searchMiddleware),
+ )
+
+ assertTrue(store.state.search.regionSearchEngines.isEmpty())
+
+ store.dispatch(
+ SearchAction.SetRegionAction(
+ RegionState("DSB", "DE"),
+ ),
+ ).joinBlocking()
+
+ wait(store, dispatcher)
+
+ assertTrue(store.state.search.regionSearchEngines.isNotEmpty())
+ assertTrue(store.state.search.additionalAvailableSearchEngines.isEmpty())
+ assertTrue(store.state.search.additionalSearchEngines.isEmpty())
+ assertEquals(6, store.state.search.regionSearchEngines.size)
+ assertEquals("Google", store.state.search.regionSearchEngines[0].name)
+ assertEquals("Bing", store.state.search.regionSearchEngines[1].name)
+ assertEquals("Amazon.de", store.state.search.regionSearchEngines[2].name)
+ assertEquals("DuckDuckGo", store.state.search.regionSearchEngines[3].name)
+ assertEquals("Wikipedija (dsb)", store.state.search.regionSearchEngines[4].name)
+ assertEquals("eBay", store.state.search.regionSearchEngines[5].name)
+
+ assertEquals("Google", store.state.search.selectedOrDefaultSearchEngine!!.name)
+ }
+
+ @Test
+ fun `Loads search engines for locale (HSB)`() {
+ Locale.setDefault(Locale("hsb", "DE"))
+ val searchMiddleware = SearchMiddleware(
+ testContext,
+ ioDispatcher = dispatcher,
+ customStorage = CustomSearchEngineStorage(testContext, dispatcher),
+ )
+
+ val store = BrowserStore(
+ middleware = listOf(searchMiddleware),
+ )
+
+ assertTrue(store.state.search.regionSearchEngines.isEmpty())
+
+ store.dispatch(
+ SearchAction.SetRegionAction(
+ RegionState("HSB", "DE"),
+ ),
+ ).joinBlocking()
+
+ wait(store, dispatcher)
+
+ assertTrue(store.state.search.regionSearchEngines.isNotEmpty())
+ assertTrue(store.state.search.additionalAvailableSearchEngines.isEmpty())
+ assertTrue(store.state.search.additionalSearchEngines.isEmpty())
+ assertEquals(6, store.state.search.regionSearchEngines.size)
+ assertEquals("Google", store.state.search.regionSearchEngines[0].name)
+ assertEquals("Bing", store.state.search.regionSearchEngines[1].name)
+ assertEquals("Amazon.de", store.state.search.regionSearchEngines[2].name)
+ assertEquals("DuckDuckGo", store.state.search.regionSearchEngines[3].name)
+ assertEquals("Wikipedija (hsb)", store.state.search.regionSearchEngines[4].name)
+ assertEquals("eBay", store.state.search.regionSearchEngines[5].name)
+
+ assertEquals("Google", store.state.search.selectedOrDefaultSearchEngine!!.name)
+ }
+
+ @Test
+ fun `Loads search engines for locale (ES)`() {
+ Locale.setDefault(Locale("es", "ES"))
+ val searchMiddleware = SearchMiddleware(
+ testContext,
+ ioDispatcher = dispatcher,
+ customStorage = CustomSearchEngineStorage(testContext, dispatcher),
+ )
+
+ val store = BrowserStore(
+ middleware = listOf(searchMiddleware),
+ )
+
+ assertTrue(store.state.search.regionSearchEngines.isEmpty())
+
+ store.dispatch(
+ SearchAction.SetRegionAction(
+ RegionState("ES", "ES"),
+ ),
+ ).joinBlocking()
+
+ wait(store, dispatcher)
+
+ assertTrue(store.state.search.regionSearchEngines.isNotEmpty())
+ assertTrue(store.state.search.additionalAvailableSearchEngines.isEmpty())
+ assertTrue(store.state.search.additionalSearchEngines.isEmpty())
+
+ assertEquals(6, store.state.search.regionSearchEngines.size)
+
+ assertEquals("Google", store.state.search.regionSearchEngines[0].name)
+ assertEquals("Bing", store.state.search.regionSearchEngines[1].name)
+ assertEquals("DuckDuckGo", store.state.search.regionSearchEngines[2].name)
+ assertEquals("Wikipedia (es)", store.state.search.regionSearchEngines[3].name)
+ assertEquals("Amazon.es", store.state.search.regionSearchEngines[4].name)
+ assertEquals("eBay", store.state.search.regionSearchEngines[5].name)
+
+ assertEquals("Google", store.state.search.selectedOrDefaultSearchEngine!!.name)
+ }
+
+ @Test
+ fun `Loads search engines for locale (IT)`() {
+ Locale.setDefault(Locale("it", "IT"))
+ val searchMiddleware = SearchMiddleware(
+ testContext,
+ ioDispatcher = dispatcher,
+ customStorage = CustomSearchEngineStorage(testContext, dispatcher),
+ )
+
+ val store = BrowserStore(
+ middleware = listOf(searchMiddleware),
+ )
+
+ assertTrue(store.state.search.regionSearchEngines.isEmpty())
+
+ store.dispatch(
+ SearchAction.SetRegionAction(
+ RegionState("it", "IT"),
+ ),
+ ).joinBlocking()
+
+ wait(store, dispatcher)
+
+ assertTrue(store.state.search.regionSearchEngines.isNotEmpty())
+ assertTrue(store.state.search.additionalAvailableSearchEngines.isEmpty())
+ assertTrue(store.state.search.additionalSearchEngines.isEmpty())
+
+ assertEquals(6, store.state.search.regionSearchEngines.size)
+
+ assertEquals("Google", store.state.search.regionSearchEngines[0].name)
+ assertEquals("Bing", store.state.search.regionSearchEngines[1].name)
+ assertEquals("DuckDuckGo", store.state.search.regionSearchEngines[2].name)
+ assertEquals("Wikipedia (it)", store.state.search.regionSearchEngines[3].name)
+ assertEquals("Amazon.it", store.state.search.regionSearchEngines[4].name)
+ assertEquals("eBay", store.state.search.regionSearchEngines[5].name)
+
+ assertEquals("Google", store.state.search.selectedOrDefaultSearchEngine!!.name)
+ }
+
+ @Test
+ fun `Loads search engines for Locale (lij)`() {
+ Locale.setDefault(Locale("lij", "ZE"))
+ val searchMiddleware = SearchMiddleware(
+ testContext,
+ ioDispatcher = dispatcher,
+ customStorage = CustomSearchEngineStorage(testContext, dispatcher),
+ )
+
+ val store = BrowserStore(
+ middleware = listOf(searchMiddleware),
+ )
+
+ assertTrue(store.state.search.regionSearchEngines.isEmpty())
+
+ store.dispatch(
+ SearchAction.SetRegionAction(
+ RegionState("lij", "ZE"),
+ ),
+ ).joinBlocking()
+
+ wait(store, dispatcher)
+
+ assertTrue(store.state.search.regionSearchEngines.isNotEmpty())
+ assertTrue(store.state.search.additionalAvailableSearchEngines.isEmpty())
+ assertTrue(store.state.search.additionalSearchEngines.isEmpty())
+
+ assertEquals(6, store.state.search.regionSearchEngines.size)
+
+ assertEquals("Google", store.state.search.regionSearchEngines[0].name)
+ assertEquals("Bing", store.state.search.regionSearchEngines[1].name)
+ assertEquals("Amazon.it", store.state.search.regionSearchEngines[2].name)
+ assertEquals("DuckDuckGo", store.state.search.regionSearchEngines[3].name)
+ assertEquals("Wikipedia (lij)", store.state.search.regionSearchEngines[4].name)
+ assertEquals("eBay", store.state.search.regionSearchEngines[5].name)
+
+ assertEquals("Google", store.state.search.selectedOrDefaultSearchEngine!!.name)
+ }
+
+ @Test
+ fun `Loads search engines for locale (SE)`() {
+ Locale.setDefault(Locale("sv", "SE"))
+ val searchMiddleware = SearchMiddleware(
+ testContext,
+ ioDispatcher = dispatcher,
+ customStorage = CustomSearchEngineStorage(testContext, dispatcher),
+ )
+
+ val store = BrowserStore(
+ middleware = listOf(searchMiddleware),
+ )
+
+ assertTrue(store.state.search.regionSearchEngines.isEmpty())
+
+ store.dispatch(
+ SearchAction.SetRegionAction(
+ RegionState("sv", "SE"),
+ ),
+ ).joinBlocking()
+
+ wait(store, dispatcher)
+
+ assertTrue(store.state.search.regionSearchEngines.isNotEmpty())
+ assertTrue(store.state.search.additionalAvailableSearchEngines.isEmpty())
+ assertTrue(store.state.search.additionalSearchEngines.isEmpty())
+
+ assertEquals(7, store.state.search.regionSearchEngines.size)
+
+ assertEquals("Google", store.state.search.regionSearchEngines[0].name)
+ assertEquals("Bing", store.state.search.regionSearchEngines[1].name)
+ assertEquals("Prisjakt", store.state.search.regionSearchEngines[2].name)
+ assertEquals("DuckDuckGo", store.state.search.regionSearchEngines[3].name)
+ assertEquals("Wikipedia (sv)", store.state.search.regionSearchEngines[4].name)
+ assertEquals("Amazon.se", store.state.search.regionSearchEngines[5].name)
+ assertEquals("eBay", store.state.search.regionSearchEngines[6].name)
+
+ assertEquals("Google", store.state.search.selectedOrDefaultSearchEngine!!.name)
+ }
+
+ @Test
+ fun `Loads search engines for locale (PL)`() {
+ Locale.setDefault(Locale("pl", "PL"))
+ val searchMiddleware = SearchMiddleware(
+ testContext,
+ ioDispatcher = dispatcher,
+ customStorage = CustomSearchEngineStorage(testContext, dispatcher),
+ )
+
+ val store = BrowserStore(
+ middleware = listOf(searchMiddleware),
+ )
+
+ assertTrue(store.state.search.regionSearchEngines.isEmpty())
+
+ store.dispatch(
+ SearchAction.SetRegionAction(
+ RegionState("pl", "PL"),
+ ),
+ ).joinBlocking()
+
+ wait(store, dispatcher)
+
+ assertTrue(store.state.search.regionSearchEngines.isNotEmpty())
+ assertTrue(store.state.search.additionalAvailableSearchEngines.isEmpty())
+ assertTrue(store.state.search.additionalSearchEngines.isEmpty())
+
+ assertEquals(5, store.state.search.regionSearchEngines.size)
+
+ assertEquals("Google", store.state.search.regionSearchEngines[0].name)
+ assertEquals("Bing", store.state.search.regionSearchEngines[1].name)
+ assertEquals("DuckDuckGo", store.state.search.regionSearchEngines[2].name)
+ assertEquals("Wikipedia (pl)", store.state.search.regionSearchEngines[3].name)
+ assertEquals("eBay", store.state.search.regionSearchEngines[4].name)
+
+ assertEquals("Google", store.state.search.selectedOrDefaultSearchEngine!!.name)
+ }
+
+ @Test
+ fun `Loads search engines for locale (RU)`() {
+ val searchMiddleware = SearchMiddleware(
+ testContext,
+ ioDispatcher = dispatcher,
+ customStorage = CustomSearchEngineStorage(testContext, dispatcher),
+ )
+
+ val store = BrowserStore(
+ middleware = listOf(searchMiddleware),
+ )
+
+ assertTrue(store.state.search.regionSearchEngines.isEmpty())
+
+ store.dispatch(
+ SearchAction.SetRegionAction(
+ RegionState("RU", "RU"),
+ ),
+ ).joinBlocking()
+
+ wait(store, dispatcher)
+
+ assertTrue(store.state.search.regionSearchEngines.isNotEmpty())
+ assertTrue(store.state.search.additionalAvailableSearchEngines.isEmpty())
+ assertTrue(store.state.search.additionalSearchEngines.isEmpty())
+
+ assertNull(store.state.search.regionSearchEngines.find { it.name == "Yandex" })
+ assertNotNull(store.state.search.regionSearchEngines.find { it.name == "Google" })
+ assertNotNull(store.state.search.regionSearchEngines.find { it.name == "DuckDuckGo" })
+ }
+
+ @Test
+ fun `Loads additional search engines`() {
+ val searchMiddleware = SearchMiddleware(
+ testContext,
+ additionalBundledSearchEngineIds = listOf("reddit", "youtube"),
+ ioDispatcher = dispatcher,
+ customStorage = CustomSearchEngineStorage(testContext, dispatcher),
+ )
+
+ val store = BrowserStore(
+ middleware = listOf(searchMiddleware),
+ )
+
+ assertTrue(store.state.search.regionSearchEngines.isEmpty())
+
+ store.dispatch(
+ SearchAction.SetRegionAction(
+ RegionState("US", "US"),
+ ),
+ ).joinBlocking()
+
+ wait(store, dispatcher)
+
+ assertTrue(store.state.search.regionSearchEngines.isNotEmpty())
+ assertTrue(store.state.search.additionalAvailableSearchEngines.isNotEmpty())
+ assertTrue(store.state.search.additionalSearchEngines.isEmpty())
+
+ assertEquals(2, store.state.search.additionalAvailableSearchEngines.size)
+
+ val first = store.state.search.additionalAvailableSearchEngines[0]
+ assertEquals("Reddit", first.name)
+ assertEquals("reddit", first.id)
+
+ val second = store.state.search.additionalAvailableSearchEngines[1]
+ assertEquals("YouTube", second.name)
+ assertEquals("youtube", second.id)
+
+ assertNull(store.state.search.searchEngines.find { searchEngine -> searchEngine.id == "youtube" })
+ assertNull(store.state.search.searchEngines.find { searchEngine -> searchEngine.id == "reddit" })
+
+ assertNotNull(store.state.search.availableSearchEngines.find { searchEngine -> searchEngine.id == "youtube" })
+ assertNotNull(store.state.search.availableSearchEngines.find { searchEngine -> searchEngine.id == "reddit" })
+ }
+
+ @Test
+ fun `Loads additional search engine and honors user choice`() = runTestOnMain {
+ val metadataStorage = SearchMetadataStorage(testContext, preferences = lazy { FakeSharedPreferences() })
+ metadataStorage.setAdditionalSearchEngines(listOf("reddit"))
+
+ val searchMiddleware = SearchMiddleware(
+ testContext,
+ additionalBundledSearchEngineIds = listOf("reddit", "youtube"),
+ metadataStorage = metadataStorage,
+ ioDispatcher = dispatcher,
+ customStorage = CustomSearchEngineStorage(testContext, dispatcher),
+ )
+
+ val store = BrowserStore(
+ middleware = listOf(searchMiddleware),
+ )
+
+ assertTrue(store.state.search.regionSearchEngines.isEmpty())
+
+ store.dispatch(
+ SearchAction.SetRegionAction(
+ RegionState("US", "US"),
+ ),
+ ).joinBlocking()
+
+ wait(store, dispatcher)
+
+ assertTrue(store.state.search.regionSearchEngines.isNotEmpty())
+ assertTrue(store.state.search.additionalAvailableSearchEngines.isNotEmpty())
+ assertTrue(store.state.search.additionalSearchEngines.isNotEmpty())
+
+ assertEquals(1, store.state.search.additionalAvailableSearchEngines.size)
+ assertEquals(1, store.state.search.additionalSearchEngines.size)
+
+ val additional = store.state.search.additionalSearchEngines[0]
+ assertEquals("Reddit", additional.name)
+ assertEquals("reddit", additional.id)
+
+ val available = store.state.search.additionalAvailableSearchEngines[0]
+ assertEquals("YouTube", available.name)
+ assertEquals("youtube", available.id)
+
+ assertNull(store.state.search.searchEngines.find { searchEngine -> searchEngine.id == "youtube" })
+ assertNotNull(store.state.search.searchEngines.find { searchEngine -> searchEngine.id == "reddit" })
+
+ assertNotNull(store.state.search.availableSearchEngines.find { searchEngine -> searchEngine.id == "youtube" })
+ assertNull(store.state.search.availableSearchEngines.find { searchEngine -> searchEngine.id == "reddit" })
+ }
+
+ @Test
+ fun `Loads custom search engines`() = runTestOnMain {
+ val searchEngine = SearchEngine(
+ id = "test-search",
+ name = "Test Engine",
+ icon = mock(),
+ type = SearchEngine.Type.CUSTOM,
+ resultUrls = listOf(),
+ suggestUrl = null,
+ )
+
+ val storage = CustomSearchEngineStorage(testContext, dispatcher)
+ storage.saveSearchEngine(searchEngine)
+
+ val store = BrowserStore(
+ middleware = listOf(
+ SearchMiddleware(
+ testContext,
+ ioDispatcher = dispatcher,
+ customStorage = storage,
+ ),
+ ),
+ )
+
+ store.dispatch(
+ SearchAction.SetRegionAction(RegionState.Default),
+ ).joinBlocking()
+
+ wait(store, dispatcher)
+
+ assertTrue(store.state.search.customSearchEngines.isNotEmpty())
+ assertNull(store.state.search.userSelectedSearchEngineId)
+ }
+
+ @Test
+ fun `Loads default search engine ID`() = runTestOnMain {
+ val storage = SearchMetadataStorage(testContext)
+ storage.setUserSelectedSearchEngine("test-id", null)
+
+ val middleware = SearchMiddleware(
+ testContext,
+ ioDispatcher = dispatcher,
+ metadataStorage = storage,
+ customStorage = CustomSearchEngineStorage(testContext, dispatcher),
+ )
+
+ val store = BrowserStore(
+ middleware = listOf(middleware),
+ )
+
+ store.dispatch(
+ SearchAction.SetRegionAction(RegionState.Default),
+ ).joinBlocking()
+
+ wait(store, dispatcher)
+
+ assertEquals("test-id", store.state.search.userSelectedSearchEngineId)
+ }
+
+ @Test
+ fun `Update default search engine`() {
+ val storage = SearchMetadataStorage(testContext)
+ val id = "test-id-${UUID.randomUUID()}"
+
+ run {
+ val store = BrowserStore(
+ middleware = listOf(
+ SearchMiddleware(
+ testContext,
+ ioDispatcher = dispatcher,
+ metadataStorage = storage,
+ customStorage = CustomSearchEngineStorage(testContext, dispatcher),
+ ),
+ ),
+ )
+
+ store.dispatch(
+ SearchAction.SetRegionAction(RegionState.Default),
+ ).joinBlocking()
+
+ wait(store, dispatcher)
+
+ assertNull(store.state.search.userSelectedSearchEngineId)
+
+ store.dispatch(SearchAction.SelectSearchEngineAction(id, null)).joinBlocking()
+
+ wait(store, dispatcher)
+
+ assertEquals(id, store.state.search.userSelectedSearchEngineId)
+ }
+
+ run {
+ val store = BrowserStore(
+ middleware = listOf(
+ SearchMiddleware(
+ testContext,
+ ioDispatcher = dispatcher,
+ metadataStorage = storage,
+ customStorage = CustomSearchEngineStorage(testContext, dispatcher),
+ ),
+ ),
+ )
+
+ store.dispatch(
+ SearchAction.SetRegionAction(RegionState.Default),
+ ).joinBlocking()
+
+ wait(store, dispatcher)
+
+ assertEquals(id, store.state.search.userSelectedSearchEngineId)
+ }
+ }
+
+ @Test
+ fun `Updates and persists additional search engines`() {
+ val storage = SearchMetadataStorage(testContext, preferences = lazy { FakeSharedPreferences() })
+ val middleware = SearchMiddleware(
+ testContext,
+ ioDispatcher = dispatcher,
+ metadataStorage = storage,
+ customStorage = CustomSearchEngineStorage(testContext, dispatcher),
+ additionalBundledSearchEngineIds = listOf(
+ "reddit",
+ "youtube",
+ ),
+ )
+
+ // First run: Add additional search engine
+ run {
+ val store = BrowserStore(middleware = listOf(middleware))
+
+ store.dispatch(
+ SearchAction.SetRegionAction(RegionState.Default),
+ ).joinBlocking()
+
+ wait(store, dispatcher)
+
+ assertTrue(store.state.search.regionSearchEngines.isNotEmpty())
+ assertTrue(store.state.search.additionalAvailableSearchEngines.isNotEmpty())
+ assertTrue(store.state.search.additionalSearchEngines.isEmpty())
+
+ assertEquals(2, store.state.search.additionalAvailableSearchEngines.size)
+
+ val first = store.state.search.additionalAvailableSearchEngines[0]
+ assertEquals("Reddit", first.name)
+ assertEquals("reddit", first.id)
+
+ val second = store.state.search.additionalAvailableSearchEngines[1]
+ assertEquals("YouTube", second.name)
+ assertEquals("youtube", second.id)
+
+ assertNull(store.state.search.searchEngines.find { searchEngine -> searchEngine.id == "youtube" })
+ assertNull(store.state.search.searchEngines.find { searchEngine -> searchEngine.id == "reddit" })
+
+ assertNotNull(store.state.search.availableSearchEngines.find { searchEngine -> searchEngine.id == "youtube" })
+ assertNotNull(store.state.search.availableSearchEngines.find { searchEngine -> searchEngine.id == "reddit" })
+
+ store.dispatch(
+ SearchAction.AddAdditionalSearchEngineAction("youtube"),
+ ).joinBlocking()
+
+ wait(store, dispatcher)
+
+ assertTrue(store.state.search.regionSearchEngines.isNotEmpty())
+ assertTrue(store.state.search.additionalAvailableSearchEngines.isNotEmpty())
+
+ assertEquals(1, store.state.search.additionalSearchEngines.size)
+ assertEquals(1, store.state.search.additionalAvailableSearchEngines.size)
+
+ assertEquals("Reddit", store.state.search.additionalAvailableSearchEngines[0].name)
+ assertEquals("reddit", store.state.search.additionalAvailableSearchEngines[0].id)
+
+ assertEquals("YouTube", store.state.search.additionalSearchEngines[0].name)
+ assertEquals("youtube", store.state.search.additionalSearchEngines[0].id)
+
+ assertNotNull(store.state.search.searchEngines.find { searchEngine -> searchEngine.id == "youtube" })
+ assertNull(store.state.search.searchEngines.find { searchEngine -> searchEngine.id == "reddit" })
+
+ assertNull(store.state.search.availableSearchEngines.find { searchEngine -> searchEngine.id == "youtube" })
+ assertNotNull(store.state.search.availableSearchEngines.find { searchEngine -> searchEngine.id == "reddit" })
+ }
+
+ // Second run: Restores additional search engine and removes it
+ run {
+ val store = BrowserStore(middleware = listOf(middleware))
+
+ store.dispatch(
+ SearchAction.SetRegionAction(RegionState.Default),
+ ).joinBlocking()
+
+ wait(store, dispatcher)
+
+ assertTrue(store.state.search.regionSearchEngines.isNotEmpty())
+ assertTrue(store.state.search.additionalAvailableSearchEngines.isNotEmpty())
+
+ assertEquals(1, store.state.search.additionalSearchEngines.size)
+ assertEquals(1, store.state.search.additionalAvailableSearchEngines.size)
+
+ assertEquals("Reddit", store.state.search.additionalAvailableSearchEngines[0].name)
+ assertEquals("reddit", store.state.search.additionalAvailableSearchEngines[0].id)
+
+ assertEquals("YouTube", store.state.search.additionalSearchEngines[0].name)
+ assertEquals("youtube", store.state.search.additionalSearchEngines[0].id)
+
+ assertNotNull(store.state.search.searchEngines.find { searchEngine -> searchEngine.id == "youtube" })
+ assertNull(store.state.search.searchEngines.find { searchEngine -> searchEngine.id == "reddit" })
+
+ assertNull(store.state.search.availableSearchEngines.find { searchEngine -> searchEngine.id == "youtube" })
+ assertNotNull(store.state.search.availableSearchEngines.find { searchEngine -> searchEngine.id == "reddit" })
+
+ store.dispatch(
+ SearchAction.RemoveAdditionalSearchEngineAction(
+ "youtube",
+ ),
+ ).joinBlocking()
+
+ wait(store, dispatcher)
+
+ assertTrue(store.state.search.regionSearchEngines.isNotEmpty())
+ assertTrue(store.state.search.additionalAvailableSearchEngines.isNotEmpty())
+ assertTrue(store.state.search.additionalSearchEngines.isEmpty())
+
+ assertEquals(2, store.state.search.additionalAvailableSearchEngines.size)
+
+ val first = store.state.search.additionalAvailableSearchEngines[0]
+ assertEquals("Reddit", first.name)
+ assertEquals("reddit", first.id)
+
+ val second = store.state.search.additionalAvailableSearchEngines[1]
+ assertEquals("YouTube", second.name)
+ assertEquals("youtube", second.id)
+
+ assertNull(store.state.search.searchEngines.find { searchEngine -> searchEngine.id == "youtube" })
+ assertNull(store.state.search.searchEngines.find { searchEngine -> searchEngine.id == "reddit" })
+
+ assertNotNull(store.state.search.availableSearchEngines.find { searchEngine -> searchEngine.id == "youtube" })
+ assertNotNull(store.state.search.availableSearchEngines.find { searchEngine -> searchEngine.id == "reddit" })
+ }
+
+ // Third run: Restores without additional search engine
+ run {
+ val store = BrowserStore(middleware = listOf(middleware))
+
+ store.dispatch(
+ SearchAction.SetRegionAction(RegionState.Default),
+ ).joinBlocking()
+
+ wait(store, dispatcher)
+
+ assertTrue(store.state.search.regionSearchEngines.isNotEmpty())
+ assertTrue(store.state.search.additionalAvailableSearchEngines.isNotEmpty())
+ assertTrue(store.state.search.additionalSearchEngines.isEmpty())
+
+ assertEquals(2, store.state.search.additionalAvailableSearchEngines.size)
+
+ val first = store.state.search.additionalAvailableSearchEngines[0]
+ assertEquals("Reddit", first.name)
+ assertEquals("reddit", first.id)
+
+ val second = store.state.search.additionalAvailableSearchEngines[1]
+ assertEquals("YouTube", second.name)
+ assertEquals("youtube", second.id)
+
+ assertNull(store.state.search.searchEngines.find { searchEngine -> searchEngine.id == "youtube" })
+ assertNull(store.state.search.searchEngines.find { searchEngine -> searchEngine.id == "reddit" })
+
+ assertNotNull(store.state.search.availableSearchEngines.find { searchEngine -> searchEngine.id == "youtube" })
+ assertNotNull(store.state.search.availableSearchEngines.find { searchEngine -> searchEngine.id == "reddit" })
+ }
+ }
+
+ @Test
+ fun `Custom search engines - Create, Update, Delete`() {
+ runTestOnMain {
+ val storage: SearchMiddleware.CustomStorage = mock()
+ doReturn(emptyList<SearchEngine>()).`when`(storage).loadSearchEngineList()
+
+ val store = BrowserStore(
+ middleware = listOf(
+ SearchMiddleware(
+ testContext,
+ ioDispatcher = dispatcher,
+ customStorage = storage,
+ ),
+ ),
+ )
+
+ store.dispatch(
+ SearchAction.SetRegionAction(RegionState.Default),
+ ).joinBlocking()
+
+ wait(store, dispatcher)
+
+ assertTrue(store.state.search.customSearchEngines.isEmpty())
+ verify(storage).loadSearchEngineList()
+ verifyNoMoreInteractions(storage)
+
+ // Add a custom search engine
+
+ val engine1 = SearchEngine("test-id-1", "test engine one", mock(), type = SearchEngine.Type.CUSTOM)
+ store.dispatch(SearchAction.UpdateCustomSearchEngineAction(engine1)).joinBlocking()
+
+ wait(store, dispatcher)
+
+ assertTrue(store.state.search.customSearchEngines.isNotEmpty())
+ assertEquals(1, store.state.search.customSearchEngines.size)
+ verify(storage).saveSearchEngine(engine1)
+ verifyNoMoreInteractions(storage)
+
+ // Add another custom search engine
+
+ val engine2 = SearchEngine("test-id-2", "test engine two", mock(), type = SearchEngine.Type.CUSTOM)
+ store.dispatch(SearchAction.UpdateCustomSearchEngineAction(engine2)).joinBlocking()
+
+ wait(store, dispatcher)
+
+ assertTrue(store.state.search.customSearchEngines.isNotEmpty())
+ assertEquals(2, store.state.search.customSearchEngines.size)
+ verify(storage).saveSearchEngine(engine2)
+ verifyNoMoreInteractions(storage)
+
+ assertEquals("test engine one", store.state.search.customSearchEngines[0].name)
+ assertEquals("test engine two", store.state.search.customSearchEngines[1].name)
+
+ // Update first engine
+
+ val updated = engine1.copy(
+ name = "updated engine",
+ )
+ store.dispatch(SearchAction.UpdateCustomSearchEngineAction(updated)).joinBlocking()
+
+ wait(store, dispatcher)
+
+ assertTrue(store.state.search.customSearchEngines.isNotEmpty())
+ assertEquals(2, store.state.search.customSearchEngines.size)
+ verify(storage).saveSearchEngine(updated)
+ verifyNoMoreInteractions(storage)
+
+ assertEquals("updated engine", store.state.search.customSearchEngines[0].name)
+ assertEquals("test engine two", store.state.search.customSearchEngines[1].name)
+
+ // Remove second engine
+
+ store.dispatch(SearchAction.RemoveCustomSearchEngineAction(engine2.id)).joinBlocking()
+
+ wait(store, dispatcher)
+
+ assertTrue(store.state.search.customSearchEngines.isNotEmpty())
+ assertEquals(1, store.state.search.customSearchEngines.size)
+ verify(storage).removeSearchEngine(engine2.id)
+ verifyNoMoreInteractions(storage)
+
+ assertEquals("updated engine", store.state.search.customSearchEngines[0].name)
+ }
+ }
+
+ @Test
+ fun `GIVEN disabled engines list contains elements WHEN metadata storage is created THEN the engines are disabled`() = runTestOnMain {
+ val additionalBundledSearchEngineIds = setOf("reddit", "youtube")
+ val metadataStorage = SearchMetadataStorage(
+ testContext,
+ additionalBundledSearchEngineIds,
+ lazy { FakeSharedPreferences() },
+ )
+ val disabledSearchEngineIds = metadataStorage.getDisabledSearchEngineIds()
+ assertTrue(disabledSearchEngineIds.contains("reddit"))
+ assertTrue(disabledSearchEngineIds.contains("youtube"))
+ }
+
+ @Test
+ fun `WHEN update disabled engine action is sent THEN search state and storage get updated`() = runTestOnMain {
+ val metadataStorage = SearchMetadataStorage(testContext, preferences = lazy { FakeSharedPreferences() })
+ metadataStorage.setAdditionalSearchEngines(listOf("reddit"))
+
+ val searchMiddleware = SearchMiddleware(
+ testContext,
+ additionalBundledSearchEngineIds = listOf("reddit", "youtube"),
+ metadataStorage = metadataStorage,
+ ioDispatcher = dispatcher,
+ customStorage = CustomSearchEngineStorage(testContext, dispatcher),
+ )
+
+ val store = BrowserStore(
+ middleware = listOf(searchMiddleware),
+ )
+
+ assertFalse(metadataStorage.getDisabledSearchEngineIds().contains("bing"))
+ assertFalse(store.state.search.disabledSearchEngineIds.contains("bing"))
+
+ store.dispatch(
+ SearchAction.UpdateDisabledSearchEngineIdsAction(
+ "bing",
+ false,
+ ),
+ ).joinBlocking()
+
+ wait(store, dispatcher)
+
+ assertTrue(metadataStorage.getDisabledSearchEngineIds().contains("bing"))
+ assertTrue(store.state.search.disabledSearchEngineIds.contains("bing"))
+
+ store.dispatch(
+ SearchAction.UpdateDisabledSearchEngineIdsAction(
+ "bing",
+ true,
+ ),
+ ).joinBlocking()
+
+ wait(store, dispatcher)
+
+ assertFalse(metadataStorage.getDisabledSearchEngineIds().contains("bing"))
+ assertFalse(store.state.search.disabledSearchEngineIds.contains("bing"))
+ }
+
+ @Test
+ fun `WHEN restore hidden search engines action THEN hidden engines are added back to bundled engines list`() = runTestOnMain {
+ val metadataStorage = SearchMetadataStorage(testContext, preferences = lazy { FakeSharedPreferences() })
+ val searchMiddleware = SearchMiddleware(
+ testContext,
+ ioDispatcher = dispatcher,
+ customStorage = CustomSearchEngineStorage(testContext, dispatcher),
+ metadataStorage = metadataStorage,
+ )
+ val store = BrowserStore(middleware = listOf(searchMiddleware))
+
+ store.dispatch(
+ SearchAction.SetRegionAction(
+ RegionState("US", "US"),
+ ),
+ ).joinBlocking()
+ wait(store, dispatcher)
+
+ val google = store.state.search.regionSearchEngines.find { searchEngine -> searchEngine.name == "Google" }
+ assertNotNull(google!!)
+ assertEquals(0, store.state.search.hiddenSearchEngines.size)
+ assertEquals(0, metadataStorage.getHiddenSearchEngines().size)
+
+ store.dispatch(SearchAction.HideSearchEngineAction(google.id)).joinBlocking()
+ wait(store, dispatcher)
+
+ assertNull(store.state.search.regionSearchEngines.find { it.id == google.id })
+
+ assertEquals(1, store.state.search.hiddenSearchEngines.size)
+ assertEquals(1, metadataStorage.getHiddenSearchEngines().size)
+ assertNotNull(store.state.search.hiddenSearchEngines.find { it.id == google.id })
+ assertNotNull(metadataStorage.getHiddenSearchEngines().find { it == google.id })
+
+ store.dispatch(SearchAction.RestoreHiddenSearchEnginesAction).joinBlocking()
+ wait(store, dispatcher)
+
+ assertNotNull(store.state.search.regionSearchEngines.find { it.id == google.id })
+
+ assertEquals(0, store.state.search.hiddenSearchEngines.size)
+ assertEquals(0, metadataStorage.getHiddenSearchEngines().size)
+ assertNull(store.state.search.hiddenSearchEngines.find { it.id == google.id })
+ assertNull(metadataStorage.getHiddenSearchEngines().find { it == google.id })
+ }
+
+ @Test
+ fun `Hiding and showing search engines`() {
+ val searchMiddleware = SearchMiddleware(
+ testContext,
+ ioDispatcher = dispatcher,
+ customStorage = CustomSearchEngineStorage(testContext, dispatcher),
+ metadataStorage = SearchMetadataStorage(testContext),
+ )
+
+ val google = BrowserStore(middleware = listOf(searchMiddleware)).let { store ->
+ store.dispatch(
+ SearchAction.SetRegionAction(
+ RegionState("US", "US"),
+ ),
+ ).joinBlocking()
+
+ wait(store, dispatcher)
+
+ store.state.search.regionSearchEngines.find { searchEngine -> searchEngine.name == "Google" }
+ }
+ assertNotNull(google!!)
+
+ run {
+ val store = BrowserStore(middleware = listOf(searchMiddleware))
+
+ store.dispatch(
+ SearchAction.SetRegionAction(
+ RegionState("US", "US"),
+ ),
+ ).joinBlocking()
+
+ wait(store, dispatcher)
+
+ assertNotNull(store.state.search.regionSearchEngines.find { it.id == google.id })
+ assertEquals(0, store.state.search.hiddenSearchEngines.size)
+
+ store.dispatch(
+ SearchAction.HideSearchEngineAction(google.id),
+ ).joinBlocking()
+
+ wait(store, dispatcher)
+
+ assertNull(store.state.search.regionSearchEngines.find { it.id == google.id })
+ assertEquals(1, store.state.search.hiddenSearchEngines.size)
+ assertNotNull(store.state.search.hiddenSearchEngines.find { it.id == google.id })
+ }
+
+ run {
+ val store = BrowserStore(middleware = listOf(searchMiddleware))
+
+ store.dispatch(
+ SearchAction.SetRegionAction(
+ RegionState("US", "US"),
+ ),
+ ).joinBlocking()
+
+ wait(store, dispatcher)
+
+ assertNull(store.state.search.regionSearchEngines.find { it.id == google.id })
+ assertEquals(1, store.state.search.hiddenSearchEngines.size)
+ assertNotNull(store.state.search.hiddenSearchEngines.find { it.id == google.id })
+
+ store.dispatch(
+ SearchAction.ShowSearchEngineAction(google.id),
+ ).joinBlocking()
+
+ assertNotNull(store.state.search.regionSearchEngines.find { it.id == google.id })
+ assertEquals(0, store.state.search.hiddenSearchEngines.size)
+ }
+
+ run {
+ val store = BrowserStore(middleware = listOf(searchMiddleware))
+
+ store.dispatch(
+ SearchAction.SetRegionAction(
+ RegionState("US", "US"),
+ ),
+ ).joinBlocking()
+
+ wait(store, dispatcher)
+
+ assertNotNull(store.state.search.regionSearchEngines.find { it.id == google.id })
+ assertEquals(0, store.state.search.hiddenSearchEngines.size)
+ }
+ }
+
+ @Test
+ fun `Keeps user choice based on search engine name even if search engine id changes`() {
+ val searchMiddleware = SearchMiddleware(
+ testContext,
+ ioDispatcher = dispatcher,
+ customStorage = CustomSearchEngineStorage(testContext, dispatcher),
+ metadataStorage = SearchMetadataStorage(testContext),
+ )
+
+ run {
+ val store = BrowserStore(middleware = listOf(searchMiddleware))
+
+ store.dispatch(
+ SearchAction.SetRegionAction(
+ RegionState("US", "US"),
+ ),
+ ).joinBlocking()
+
+ wait(store, dispatcher)
+
+ val google = store.state.search.searchEngines.find { it.name == "Google" }
+ assertNotNull(google!!)
+ assertEquals("google-b-1-m", google.id)
+
+ store.dispatch(
+ SearchAction.SelectSearchEngineAction(
+ searchEngineId = "google-b-1-m",
+ searchEngineName = "Google",
+ ),
+ ).joinBlocking()
+
+ wait(store, dispatcher)
+
+ assertEquals("google-b-1-m", store.state.search.userSelectedSearchEngineId)
+ assertEquals("Google", store.state.search.userSelectedSearchEngineName)
+
+ val searchEngine = store.state.search.selectedOrDefaultSearchEngine
+ assertNotNull(searchEngine!!)
+ assertEquals("google-b-1-m", searchEngine.id)
+ assertEquals("Google", searchEngine.name)
+ }
+
+ run {
+ val store = BrowserStore(middleware = listOf(searchMiddleware))
+
+ store.dispatch(
+ SearchAction.SetRegionAction(
+ RegionState("DE", "DE"),
+ ),
+ ).joinBlocking()
+
+ wait(store, dispatcher)
+
+ assertEquals("google-b-1-m", store.state.search.userSelectedSearchEngineId)
+ assertEquals("Google", store.state.search.userSelectedSearchEngineName)
+
+ val searchEngine = store.state.search.selectedOrDefaultSearchEngine
+ assertNotNull(searchEngine!!)
+ assertEquals("google-b-m", searchEngine.id)
+ assertEquals("Google", searchEngine.name)
+ }
+ }
+
+ @Test
+ fun `Adding and restoring custom search engine`() {
+ val searchMiddleware = SearchMiddleware(
+ testContext,
+ ioDispatcher = dispatcher,
+ customStorage = CustomSearchEngineStorage(testContext, dispatcher),
+ metadataStorage = SearchMetadataStorage(testContext),
+ )
+
+ run {
+ val store = BrowserStore(middleware = listOf(searchMiddleware))
+
+ store.dispatch(
+ SearchAction.SetRegionAction(
+ RegionState("US", "US"),
+ ),
+ ).joinBlocking()
+
+ wait(store, dispatcher)
+
+ assertEquals(0, store.state.search.customSearchEngines.size)
+
+ store.dispatch(
+ SearchAction.UpdateCustomSearchEngineAction(
+ SearchEngine(
+ id = UUID.randomUUID().toString(),
+ name = "Example",
+ icon = mock(),
+ type = SearchEngine.Type.CUSTOM,
+ resultUrls = listOf(
+ "https://example.org/?q=%s",
+ ),
+ ),
+ ),
+ ).joinBlocking()
+
+ wait(store, dispatcher)
+
+ assertEquals(1, store.state.search.customSearchEngines.size)
+ }
+
+ run {
+ val store = BrowserStore(middleware = listOf(searchMiddleware))
+
+ store.dispatch(
+ SearchAction.SetRegionAction(
+ RegionState("US", "US"),
+ ),
+ ).joinBlocking()
+
+ wait(store, dispatcher)
+
+ assertEquals(1, store.state.search.customSearchEngines.size)
+ }
+ }
+
+ @Test
+ fun `Migration - custom search engine and default search engine`() {
+ val customStorage = CustomSearchEngineStorage(testContext, dispatcher)
+ val metadataStorage = SearchMetadataStorage(testContext)
+
+ run {
+ val searchMiddleware = SearchMiddleware(
+ testContext,
+ ioDispatcher = dispatcher,
+ customStorage = customStorage,
+ metadataStorage = metadataStorage,
+ migration = object : SearchMiddleware.Migration {
+ override fun getValuesToMigrate() = SearchMiddleware.Migration.MigrationValues(
+ customSearchEngines = listOf(
+ createSearchEngine(
+ name = "Example",
+ url = "https://example.org/?q={searchTerms}",
+ icon = mock(),
+ ),
+ ),
+ defaultSearchEngineName = "Example",
+ )
+ },
+ )
+
+ val store = BrowserStore(middleware = listOf(searchMiddleware))
+
+ store.dispatch(
+ SearchAction.SetRegionAction(
+ RegionState("US", "US"),
+ ),
+ ).joinBlocking()
+
+ wait(store, dispatcher)
+
+ assertEquals(1, store.state.search.customSearchEngines.size)
+
+ val selectedSearchEngine = store.state.search.selectedOrDefaultSearchEngine
+ assertNotNull(selectedSearchEngine!!)
+
+ assertEquals("Example", selectedSearchEngine.name)
+ assertEquals("https://example.org/?q={searchTerms}", selectedSearchEngine.resultUrls[0])
+ }
+
+ run {
+ val searchMiddleware = SearchMiddleware(
+ testContext,
+ ioDispatcher = dispatcher,
+ customStorage = customStorage,
+ metadataStorage = metadataStorage,
+ )
+
+ val store = BrowserStore(middleware = listOf(searchMiddleware))
+
+ store.dispatch(
+ SearchAction.SetRegionAction(
+ RegionState("US", "US"),
+ ),
+ ).joinBlocking()
+
+ wait(store, dispatcher)
+
+ assertEquals(1, store.state.search.customSearchEngines.size)
+
+ val selectedSearchEngine = store.state.search.selectedOrDefaultSearchEngine
+ assertNotNull(selectedSearchEngine!!)
+
+ assertEquals("Example", selectedSearchEngine.name)
+ assertEquals("https://example.org/?q={searchTerms}", selectedSearchEngine.resultUrls[0])
+ }
+ }
+
+ @Test
+ fun `Migration - default search engine`() {
+ val customStorage = CustomSearchEngineStorage(testContext, dispatcher)
+ val metadataStorage = SearchMetadataStorage(testContext)
+
+ run {
+ val searchMiddleware = SearchMiddleware(
+ testContext,
+ ioDispatcher = dispatcher,
+ customStorage = customStorage,
+ metadataStorage = metadataStorage,
+ migration = object : SearchMiddleware.Migration {
+ override fun getValuesToMigrate() = SearchMiddleware.Migration.MigrationValues(
+ customSearchEngines = listOf(),
+ defaultSearchEngineName = "Amazon.com",
+ )
+ },
+ )
+
+ val store = BrowserStore(middleware = listOf(searchMiddleware))
+
+ store.dispatch(
+ SearchAction.SetRegionAction(
+ RegionState("US", "US"),
+ ),
+ ).joinBlocking()
+
+ wait(store, dispatcher)
+
+ val selectedSearchEngine = store.state.search.selectedOrDefaultSearchEngine
+ assertNotNull(selectedSearchEngine!!)
+
+ assertEquals("Amazon.com", selectedSearchEngine.name)
+ assertTrue(selectedSearchEngine.resultUrls[0].startsWith("https://www.amazon.com/"))
+ }
+
+ run {
+ val searchMiddleware = SearchMiddleware(
+ testContext,
+ ioDispatcher = dispatcher,
+ customStorage = customStorage,
+ metadataStorage = metadataStorage,
+ )
+
+ val store = BrowserStore(middleware = listOf(searchMiddleware))
+
+ store.dispatch(
+ SearchAction.SetRegionAction(
+ RegionState("US", "US"),
+ ),
+ ).joinBlocking()
+
+ wait(store, dispatcher)
+
+ val selectedSearchEngine = store.state.search.selectedOrDefaultSearchEngine
+ assertNotNull(selectedSearchEngine!!)
+
+ assertEquals("Amazon.com", selectedSearchEngine.name)
+ assertTrue(selectedSearchEngine.resultUrls[0].startsWith("https://www.amazon.com/"))
+ }
+ }
+
+ @Test
+ fun `Reorders list of region search engines after adding previously removed search engines`() {
+ val searchMiddleware = SearchMiddleware(
+ testContext,
+ ioDispatcher = dispatcher,
+ customStorage = CustomSearchEngineStorage(testContext, dispatcher),
+ )
+
+ val store = BrowserStore(
+ middleware = listOf(searchMiddleware),
+ )
+
+ assertTrue(store.state.search.regionSearchEngines.isEmpty())
+
+ store.dispatch(
+ SearchAction.SetRegionAction(
+ RegionState("US", "US"),
+ ),
+ ).joinBlocking()
+
+ wait(store, dispatcher)
+
+ // ///////////////////////////////////////////////////////////////////////////////////////////
+ // Verify initial state
+ // ///////////////////////////////////////////////////////////////////////////////////////////
+
+ assertEquals(6, store.state.search.regionSearchEngines.size)
+
+ assertEquals("Google", store.state.search.regionSearchEngines[0].name)
+ assertEquals("Bing", store.state.search.regionSearchEngines[1].name)
+ assertEquals("Amazon.com", store.state.search.regionSearchEngines[2].name)
+ assertEquals("DuckDuckGo", store.state.search.regionSearchEngines[3].name)
+ assertEquals("eBay", store.state.search.regionSearchEngines[4].name)
+ assertEquals("Wikipedia", store.state.search.regionSearchEngines[5].name)
+
+ assertEquals("Google", store.state.search.selectedOrDefaultSearchEngine!!.name)
+
+ store.dispatch(
+ SearchAction.HideSearchEngineAction(
+ "google-b-1-m",
+ ),
+ ).joinBlocking()
+
+ store.dispatch(
+ SearchAction.HideSearchEngineAction(
+ "ddg",
+ ),
+ ).joinBlocking()
+
+ // ///////////////////////////////////////////////////////////////////////////////////////////
+ // Verify after hiding search engines
+ // ///////////////////////////////////////////////////////////////////////////////////////////
+
+ assertEquals(4, store.state.search.regionSearchEngines.size)
+
+ assertEquals("Bing", store.state.search.regionSearchEngines[0].name)
+ assertEquals("Amazon.com", store.state.search.regionSearchEngines[1].name)
+ assertEquals("eBay", store.state.search.regionSearchEngines[2].name)
+ assertEquals("Wikipedia", store.state.search.regionSearchEngines[3].name)
+
+ assertEquals("Bing", store.state.search.selectedOrDefaultSearchEngine!!.name)
+
+ println(store.state.search.regionSearchEngines)
+
+ store.dispatch(
+ SearchAction.ShowSearchEngineAction("google-b-1-m"),
+ ).joinBlocking()
+
+ store.dispatch(
+ SearchAction.ShowSearchEngineAction("ddg"),
+ ).joinBlocking()
+
+ // ///////////////////////////////////////////////////////////////////////////////////////////
+ // Verify state after adding search engines back
+ // ///////////////////////////////////////////////////////////////////////////////////////////
+
+ assertEquals(6, store.state.search.regionSearchEngines.size)
+
+ assertEquals("Google", store.state.search.regionSearchEngines[0].name)
+ assertEquals("Bing", store.state.search.regionSearchEngines[1].name)
+ assertEquals("Amazon.com", store.state.search.regionSearchEngines[2].name)
+ assertEquals("DuckDuckGo", store.state.search.regionSearchEngines[3].name)
+ assertEquals("eBay", store.state.search.regionSearchEngines[4].name)
+ assertEquals("Wikipedia", store.state.search.regionSearchEngines[5].name)
+
+ assertEquals("Google", store.state.search.selectedOrDefaultSearchEngine!!.name)
+ }
+
+ @Test
+ fun `Loads search engines for locale (JA)`() {
+ Locale.setDefault(Locale("ja", "JA"))
+ val searchMiddleware = SearchMiddleware(
+ testContext,
+ ioDispatcher = dispatcher,
+ customStorage = CustomSearchEngineStorage(testContext, dispatcher),
+ )
+
+ val store = BrowserStore(
+ middleware = listOf(searchMiddleware),
+ )
+
+ assertTrue(store.state.search.regionSearchEngines.isEmpty())
+
+ store.dispatch(
+ SearchAction.SetRegionAction(
+ RegionState("JA", "JA"),
+ ),
+ ).joinBlocking()
+
+ wait(store, dispatcher)
+
+ assertTrue(store.state.search.regionSearchEngines.isNotEmpty())
+ assertTrue(store.state.search.additionalAvailableSearchEngines.isEmpty())
+ assertTrue(store.state.search.additionalSearchEngines.isEmpty())
+
+ assertEquals(8, store.state.search.regionSearchEngines.size)
+
+ assertEquals("Google", store.state.search.regionSearchEngines[0].name)
+ assertEquals("Bing", store.state.search.regionSearchEngines[1].name)
+ assertEquals("Amazon.co.jp", store.state.search.regionSearchEngines[2].name)
+ assertEquals("DuckDuckGo", store.state.search.regionSearchEngines[3].name)
+ assertEquals("楽天市場", store.state.search.regionSearchEngines[4].name)
+ assertEquals("Wikipedia (ja)", store.state.search.regionSearchEngines[5].name)
+ assertEquals("Yahoo! JAPAN", store.state.search.regionSearchEngines[6].name)
+ assertEquals("Yahoo!オークション", store.state.search.regionSearchEngines[7].name)
+
+ assertEquals("Google", store.state.search.selectedOrDefaultSearchEngine!!.name)
+ }
+}
+
+private fun wait(store: BrowserStore, dispatcher: TestDispatcher) {
+ // First we wait for the InitAction that may still need to be processed.
+ store.waitUntilIdle()
+
+ // Now we wait for the Middleware that may need to asynchronously process an action the test dispatched
+ dispatcher.scheduler.advanceUntilIdle()
+
+ // Since the Middleware may have dispatched an action, we now wait for the store again.
+ store.waitUntilIdle()
+}
diff --git a/mobile/android/android-components/components/feature/search/src/test/java/mozilla/components/feature/search/region/RegionManagerTest.kt b/mobile/android/android-components/components/feature/search/src/test/java/mozilla/components/feature/search/region/RegionManagerTest.kt
new file mode 100644
index 0000000000..1103680e3e
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/test/java/mozilla/components/feature/search/region/RegionManagerTest.kt
@@ -0,0 +1,146 @@
+/* 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.feature.search.region
+
+import kotlinx.coroutines.test.runTest
+import mozilla.components.service.location.LocationService
+import mozilla.components.support.test.fakes.FakeClock
+import mozilla.components.support.test.fakes.android.FakeContext
+import mozilla.components.support.test.fakes.android.FakeSharedPreferences
+import org.junit.Assert.assertEquals
+import org.junit.Assert.assertNotNull
+import org.junit.Assert.assertNull
+import org.junit.Test
+
+class RegionManagerTest {
+ @Test
+ fun `Initial state`() {
+ val regionManager = RegionManager(
+ context = FakeContext(),
+ locationService = FakeLocationService(),
+ currentTime = FakeClock()::time,
+ preferences = lazy { FakeSharedPreferences() },
+ )
+
+ assertNull(regionManager.region())
+ }
+
+ @Test
+ fun `First update`() = runTest {
+ val locationService = FakeLocationService(
+ region = LocationService.Region("DE", "Germany"),
+ )
+
+ val regionManager = RegionManager(
+ context = FakeContext(),
+ locationService = locationService,
+ currentTime = FakeClock()::time,
+ preferences = lazy { FakeSharedPreferences() },
+ )
+
+ val updatedRegion = regionManager.update()
+ assertNotNull(updatedRegion!!)
+ assertEquals("DE", updatedRegion.current)
+ assertEquals("DE", updatedRegion.home)
+ }
+
+ @Test
+ fun `Updating to new home region`() = runTest {
+ val clock = FakeClock()
+
+ val locationService = FakeLocationService(
+ region = LocationService.Region("DE", "Germany"),
+ )
+
+ val regionManager = RegionManager(
+ context = FakeContext(),
+ locationService = locationService,
+ currentTime = clock::time,
+ preferences = lazy { FakeSharedPreferences() },
+ )
+
+ regionManager.update()
+
+ locationService.region = LocationService.Region("FR", "France")
+
+ // Should not be updated since the "home" region didn't change
+ assertNull(regionManager.update())
+ assertEquals("DE", regionManager.region()?.home)
+ assertEquals("FR", regionManager.region()?.current)
+
+ // Let's jump one week into the future!
+ clock.advanceBy(60L * 60L * 24L * 7L * 1000L)
+
+ // Still not updated because we switch after two weeks
+ assertNull(regionManager.update())
+ assertEquals("DE", regionManager.region()?.home)
+ assertEquals("FR", regionManager.region()?.current)
+
+ // Let's move the clock 8 more days into the future
+ clock.advanceBy(60L * 60L * 24L * 8L * 1000L)
+
+ val updatedRegion = (regionManager.update())
+ assertNotNull(updatedRegion!!)
+ assertEquals("FR", updatedRegion.home)
+ assertEquals("FR", updatedRegion.current)
+ assertEquals("FR", regionManager.region()?.home)
+ assertEquals("FR", regionManager.region()?.current)
+ }
+
+ @Test
+ fun `Switching back to home region after staying in different region shortly`() = runTest {
+ val clock = FakeClock()
+
+ val locationService = FakeLocationService(
+ region = LocationService.Region("DE", "Germany"),
+ )
+
+ val regionManager = RegionManager(
+ context = FakeContext(),
+ locationService = locationService,
+ currentTime = clock::time,
+ preferences = lazy { FakeSharedPreferences() },
+ )
+
+ regionManager.update()
+
+ // Let's jump one week into the future!
+ clock.advanceBy(60L * 60L * 24L * 7L * 1000L)
+
+ locationService.region = LocationService.Region("FR", "France")
+
+ // Should not be updated since the "home" region didn't change
+ assertNull(regionManager.update())
+ assertEquals("DE", regionManager.region()?.home)
+ assertEquals("FR", regionManager.region()?.current)
+
+ // Next day, we are back in the home region
+ clock.advanceBy(60L * 60L * 24L * 1000L)
+
+ locationService.region = LocationService.Region("DE", "Germany")
+ assertNull(regionManager.update())
+ assertEquals("DE", regionManager.region()?.home)
+ assertEquals("DE", regionManager.region()?.current)
+
+ // Another week forward, we are back in France
+ clock.advanceBy(60L * 60L * 24L * 7L * 1000L)
+
+ locationService.region = LocationService.Region("FR", "France")
+
+ // The "home" region should not have changed since we haven't been in the other region the
+ // whole time.
+ assertNull(regionManager.update())
+ assertEquals("DE", regionManager.region()?.home)
+ assertEquals("FR", regionManager.region()?.current)
+ }
+}
+
+class FakeLocationService(
+ var region: LocationService.Region? = null,
+ private val hasRegionCached: Boolean = false,
+) : LocationService {
+ override suspend fun fetchRegion(readFromCache: Boolean): LocationService.Region? = region
+ override fun hasRegionCached(): Boolean = hasRegionCached
+}
diff --git a/mobile/android/android-components/components/feature/search/src/test/java/mozilla/components/feature/search/region/RegionMiddlewareTest.kt b/mobile/android/android-components/components/feature/search/src/test/java/mozilla/components/feature/search/region/RegionMiddlewareTest.kt
new file mode 100644
index 0000000000..b05dc5e7c9
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/test/java/mozilla/components/feature/search/region/RegionMiddlewareTest.kt
@@ -0,0 +1,153 @@
+/* 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.feature.search.region
+
+import mozilla.components.browser.state.action.InitAction
+import mozilla.components.browser.state.action.SearchAction.RefreshSearchEnginesAction
+import mozilla.components.browser.state.search.RegionState
+import mozilla.components.browser.state.store.BrowserStore
+import mozilla.components.service.location.LocationService
+import mozilla.components.support.test.ext.joinBlocking
+import mozilla.components.support.test.fakes.FakeClock
+import mozilla.components.support.test.fakes.android.FakeContext
+import mozilla.components.support.test.fakes.android.FakeSharedPreferences
+import mozilla.components.support.test.libstate.ext.waitUntilIdle
+import mozilla.components.support.test.rule.MainCoroutineRule
+import mozilla.components.support.test.rule.runTestOnMain
+import org.junit.Assert.assertEquals
+import org.junit.Assert.assertNotEquals
+import org.junit.Before
+import org.junit.Rule
+import org.junit.Test
+
+class RegionMiddlewareTest {
+
+ @get:Rule
+ val coroutinesTestRule = MainCoroutineRule()
+ private val dispatcher = coroutinesTestRule.testDispatcher
+
+ private lateinit var locationService: FakeLocationService
+ private lateinit var clock: FakeClock
+ private lateinit var regionManager: RegionManager
+
+ @Before
+ fun setUp() {
+ clock = FakeClock()
+ locationService = FakeLocationService()
+ regionManager = RegionManager(
+ context = FakeContext(),
+ locationService = locationService,
+ currentTime = clock::time,
+ preferences = lazy { FakeSharedPreferences() },
+ )
+ }
+
+ @Test
+ fun `Updates region on init`() {
+ val middleware = RegionMiddleware(FakeContext(), locationService, dispatcher)
+ middleware.regionManager = regionManager
+
+ locationService.region = LocationService.Region("FR", "France")
+
+ val store = BrowserStore(
+ middleware = listOf(middleware),
+ )
+
+ store.waitUntilIdle()
+ middleware.updateJob?.joinBlocking()
+ store.waitUntilIdle()
+
+ assertNotEquals(RegionState.Default, store.state.search.region)
+ assertEquals("FR", store.state.search.region!!.home)
+ assertEquals("FR", store.state.search.region!!.current)
+ }
+
+ @Test
+ fun `Uses default region if could never get updated`() {
+ val middleware = RegionMiddleware(FakeContext(), locationService, dispatcher)
+ middleware.regionManager = regionManager
+
+ val store = BrowserStore(
+ middleware = listOf(middleware),
+ )
+
+ store.dispatch(InitAction).joinBlocking()
+
+ dispatcher.scheduler.advanceUntilIdle()
+ store.waitUntilIdle()
+
+ assertEquals(RegionState.Default, store.state.search.region)
+ assertEquals("XX", store.state.search.region!!.home)
+ assertEquals("XX", store.state.search.region!!.current)
+ }
+
+ @Test
+ fun `Dispatches cached home region and update later`() = runTestOnMain {
+ val middleware = RegionMiddleware(FakeContext(), locationService, dispatcher)
+ middleware.regionManager = regionManager
+
+ locationService.region = LocationService.Region("FR", "France")
+ regionManager.update()
+
+ val store = BrowserStore(
+ middleware = listOf(middleware),
+ )
+
+ store.dispatch(InitAction).joinBlocking()
+ middleware.updateJob?.joinBlocking()
+ store.waitUntilIdle()
+
+ assertEquals("FR", store.state.search.region!!.home)
+ assertEquals("FR", store.state.search.region!!.current)
+
+ locationService.region = LocationService.Region("DE", "Germany")
+ regionManager.update()
+
+ store.dispatch(InitAction).joinBlocking()
+ middleware.updateJob?.joinBlocking()
+ store.waitUntilIdle()
+
+ assertEquals("FR", store.state.search.region!!.home)
+ assertEquals("DE", store.state.search.region!!.current)
+
+ clock.advanceBy(1000L * 60L * 60L * 24L * 21L)
+
+ store.dispatch(InitAction).joinBlocking()
+ middleware.updateJob?.joinBlocking()
+ store.waitUntilIdle()
+
+ assertEquals("DE", store.state.search.region!!.home)
+ assertEquals("DE", store.state.search.region!!.current)
+ }
+
+ @Test
+ fun `GIVEN a locale is already selected WHEN the locale changes THEN update region on RefreshSearchEngines`() = runTestOnMain {
+ val middleware = RegionMiddleware(FakeContext(), locationService, dispatcher)
+ middleware.regionManager = regionManager
+
+ locationService.region = LocationService.Region("FR", "France")
+
+ val store = BrowserStore(
+ middleware = listOf(middleware),
+ )
+
+ store.dispatch(InitAction).joinBlocking()
+ middleware.updateJob?.joinBlocking()
+ store.waitUntilIdle()
+
+ assertEquals("FR", store.state.search.region!!.home)
+ assertEquals("FR", store.state.search.region!!.current)
+
+ locationService.region = LocationService.Region("DE", "Germany")
+ regionManager.update()
+
+ store.dispatch(RefreshSearchEnginesAction).joinBlocking()
+ middleware.updateJob?.joinBlocking()
+ store.waitUntilIdle()
+
+ assertEquals("FR", store.state.search.region!!.home)
+ assertEquals("DE", store.state.search.region!!.current)
+ }
+}
diff --git a/mobile/android/android-components/components/feature/search/src/test/java/mozilla/components/feature/search/storage/BundledSearchEnginesStorageTest.kt b/mobile/android/android-components/components/feature/search/src/test/java/mozilla/components/feature/search/storage/BundledSearchEnginesStorageTest.kt
new file mode 100644
index 0000000000..bfd6691432
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/test/java/mozilla/components/feature/search/storage/BundledSearchEnginesStorageTest.kt
@@ -0,0 +1,196 @@
+/* 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.feature.search.storage
+
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import kotlinx.coroutines.test.runTest
+import mozilla.components.browser.state.search.RegionState
+import mozilla.components.browser.state.search.SearchEngine
+import mozilla.components.support.test.robolectric.testContext
+import org.junit.Assert.assertEquals
+import org.junit.Assert.assertFalse
+import org.junit.Assert.assertNotNull
+import org.junit.Assert.assertTrue
+import org.junit.Test
+import org.junit.runner.RunWith
+import java.util.Locale
+
+@RunWith(AndroidJUnit4::class)
+class BundledSearchEnginesStorageTest {
+ @Test
+ fun `Load search engines for en-US from assets`() = runTest {
+ val storage = BundledSearchEnginesStorage(testContext)
+
+ val engines = storage.load(RegionState("US", "US"), Locale("en", "US"))
+ val searchEngines = engines.list
+
+ assertEquals(6, searchEngines.size)
+ }
+
+ @Test
+ fun `Load search engines for all known locales without region`() = runTest {
+ val storage = BundledSearchEnginesStorage(testContext)
+ val locales = Locale.getAvailableLocales()
+ assertTrue(locales.isNotEmpty())
+
+ for (locale in locales) {
+ val engines = storage.load(RegionState.Default, locale)
+ assertTrue(engines.list.isNotEmpty())
+ assertFalse(engines.defaultSearchEngineId.isEmpty())
+ }
+ }
+
+ @Test
+ fun `Load search engines for de-DE with global US region override`() = runTest {
+ // Without region
+ run {
+ val storage = BundledSearchEnginesStorage(testContext)
+ val engines = storage.load(RegionState.Default, Locale("de", "DE"))
+ val searchEngines = engines.list
+
+ assertEquals(8, searchEngines.size)
+ assertContainsSearchEngine("google-b-m", searchEngines)
+ assertContainsNotSearchEngine("google-2018", searchEngines)
+ }
+ // With region
+ run {
+ val storage = BundledSearchEnginesStorage(testContext)
+ val engines = storage.load(RegionState("US", "US"), Locale("de", "DE"))
+ val searchEngines = engines.list
+
+ assertEquals(8, searchEngines.size)
+ assertContainsSearchEngine("google-b-1-m", searchEngines)
+ assertContainsNotSearchEngine("google", searchEngines)
+ }
+ }
+
+ @Test
+ fun `Load search engines for en-US with local RU region override`() = runTest {
+ // Without region
+ run {
+ val storage = BundledSearchEnginesStorage(testContext)
+ val engines = storage.load(RegionState.Default, Locale("en", "US"))
+ val searchEngines = engines.list
+
+ println("searchEngines = $searchEngines")
+ assertEquals(6, searchEngines.size)
+ assertContainsNotSearchEngine("yandex-en", searchEngines)
+ }
+ // With region
+ run {
+ val storage = BundledSearchEnginesStorage(testContext)
+ val engines = storage.load(RegionState("RU", "RU"), Locale("en", "US"))
+ val searchEngines = engines.list
+
+ println("searchEngines = $searchEngines")
+ assertEquals(5, searchEngines.size)
+ assertContainsSearchEngine("google-com-nocodes", searchEngines)
+ assertContainsNotSearchEngine("yandex-en", searchEngines)
+ }
+ }
+
+ @Test
+ fun `Load search engines for zh-CN_CN locale with searchDefault override`() = runTest {
+ val storage = BundledSearchEnginesStorage(testContext)
+ val engines = storage.load(RegionState("CN", "CN"), Locale("zh", "CN"))
+ val searchEngines = engines.list
+
+ // visibleDefaultEngines: ["google-b-m", "bing", "baidu", "ddg", "wikipedia-zh-CN"]
+ // searchOrder (default): ["Google", "Bing"]
+
+ assertEquals(
+ listOf("google-b-m", "bing", "baidu", "ddg", "wikipedia-zh-CN"),
+ searchEngines.map { it.id },
+ )
+
+ // searchDefault: "百度"
+ val default = searchEngines.find { it.id == engines.defaultSearchEngineId }
+ assertNotNull(default)
+ assertEquals("baidu", default!!.id)
+ }
+
+ @Test
+ fun `Load search engines for ru_RU locale with engines not in searchOrder`() = runTest {
+ val storage = BundledSearchEnginesStorage(testContext)
+ val engines = storage.load(RegionState("RU", "RU"), Locale("ru", "RU"))
+ val searchEngines = engines.list
+
+ assertEquals(
+ listOf("google-com-nocodes", "ddg", "wikipedia-ru"),
+ searchEngines.map { it.id },
+ )
+
+ // searchDefault: "Google"
+ val default = searchEngines.find { it.id == engines.defaultSearchEngineId }
+ assertNotNull(default)
+ assertEquals("google-com-nocodes", default!!.id)
+ }
+
+ @Test
+ fun `Load search engines for trs locale with non-google initial engines and no default`() = runTest {
+ val storage = BundledSearchEnginesStorage(testContext)
+ val engines = storage.load(RegionState.Default, Locale("trs", ""))
+ val searchEngines = engines.list
+
+ // visibleDefaultEngines: ["google-b-m", "bing", "amazondotcom", "ddg", "wikipedia-es"]
+ // searchOrder (default): ["Google", "Bing"]
+
+ assertEquals(
+ listOf("google-b-m", "bing", "amazondotcom", "ddg", "wikipedia-es"),
+ searchEngines.map { it.id },
+ )
+
+ // searchDefault (default): "Google"
+ val default = searchEngines.find { it.id == engines.defaultSearchEngineId }
+ assertNotNull(default)
+ assertEquals("google-b-m", default!!.id)
+ }
+
+ @Test
+ fun `Load search engines for locale not in configuration`() = runTest {
+ val storage = BundledSearchEnginesStorage(testContext)
+ val engines = storage.load(RegionState.Default, Locale("xx", "XX"))
+ val searchEngines = engines.list
+
+ assertEquals(5, searchEngines.size)
+ }
+
+ private fun assertContainsSearchEngine(identifier: String, searchEngines: List<SearchEngine>) {
+ searchEngines.forEach {
+ if (identifier == it.id) {
+ return
+ }
+ }
+ throw AssertionError("Search engine $identifier not in list")
+ }
+
+ private fun assertContainsNotSearchEngine(identifier: String, searchEngines: List<SearchEngine>) {
+ searchEngines.forEach {
+ if (identifier == it.id) {
+ throw AssertionError("Search engine $identifier in list")
+ }
+ }
+ }
+
+ @Test
+ fun `Verify values of Google search engine`() = runTest {
+ val storage = BundledSearchEnginesStorage(testContext)
+
+ val engines = storage.load(RegionState("US", "US"), Locale("en", "US"))
+ val searchEngines = engines.list
+
+ assertEquals(6, searchEngines.size)
+
+ val google = searchEngines.find { it.name == "Google" }
+ assertNotNull(google!!)
+
+ assertEquals("google-b-1-m", google.id)
+ assertEquals("Google", google.name)
+ assertEquals(SearchEngine.Type.BUNDLED, google.type)
+ assertNotNull(google.icon)
+ assertEquals("https://www.google.com/complete/search?client=firefox&q={searchTerms}", google.suggestUrl)
+ assertTrue(google.resultUrls.isNotEmpty())
+ }
+}
diff --git a/mobile/android/android-components/components/feature/search/src/test/java/mozilla/components/feature/search/storage/CustomSearchEngineStorageTest.kt b/mobile/android/android-components/components/feature/search/src/test/java/mozilla/components/feature/search/storage/CustomSearchEngineStorageTest.kt
new file mode 100644
index 0000000000..2da25c0b5d
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/test/java/mozilla/components/feature/search/storage/CustomSearchEngineStorageTest.kt
@@ -0,0 +1,105 @@
+/* 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.feature.search.storage
+
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import kotlinx.coroutines.test.runTest
+import mozilla.components.browser.state.search.SearchEngine
+import mozilla.components.support.test.mock
+import mozilla.components.support.test.robolectric.testContext
+import org.junit.Assert.assertEquals
+import org.junit.Assert.assertTrue
+import org.junit.Ignore
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@RunWith(AndroidJUnit4::class)
+class CustomSearchEngineStorageTest {
+ @Test
+ fun `saveSearchEngine successfully saves`() = runTest {
+ val searchEngine = SearchEngine(
+ id = "id1",
+ name = "example",
+ icon = mock(),
+ type = SearchEngine.Type.CUSTOM,
+ resultUrls = listOf("https://www.example.com/search"),
+ )
+
+ val storage = CustomSearchEngineStorage(testContext, coroutineContext)
+ assertTrue(storage.saveSearchEngine(searchEngine))
+ assertTrue(storage.getSearchFile(searchEngine.id).baseFile.exists())
+ }
+
+ @Test
+ fun `loadSearchEngine successfully loads after saving`() = runTest {
+ val searchEngine = SearchEngine(
+ id = "id1",
+ name = "example",
+ icon = mock(),
+ type = SearchEngine.Type.CUSTOM,
+ resultUrls = listOf("https://www.example.com/search"),
+ )
+
+ val storage = CustomSearchEngineStorage(testContext, coroutineContext)
+ assertTrue(storage.saveSearchEngine(searchEngine))
+
+ val storedSearchEngine = storage.loadSearchEngine(searchEngine.id)
+ assertEquals(searchEngine.id, storedSearchEngine.id)
+ assertEquals(searchEngine.name, storedSearchEngine.name)
+ assertEquals(searchEngine.type, storedSearchEngine.type)
+ assertEquals(searchEngine.resultUrls, storedSearchEngine.resultUrls)
+ }
+
+ @Test
+ @Ignore("https://github.com/mozilla-mobile/android-components/issues/8124")
+ fun `loadSearchEngineList successfully loads after saving`() = runTest {
+ val searchEngine = SearchEngine(
+ id = "id1",
+ name = "example",
+ icon = mock(),
+ type = SearchEngine.Type.CUSTOM,
+ resultUrls = listOf("https://www.example.com/search"),
+ )
+ val searchEngineTwo = SearchEngine(
+ id = "id2",
+ name = "searchTwo",
+ icon = mock(),
+ type = SearchEngine.Type.CUSTOM,
+ resultUrls = listOf("https://www.searchtwo.com/search"),
+ )
+
+ val storage = CustomSearchEngineStorage(testContext, coroutineContext)
+ assertTrue(storage.saveSearchEngine(searchEngine))
+ assertTrue(storage.saveSearchEngine(searchEngineTwo))
+
+ val storedSearchEngines = storage.loadSearchEngineList()
+ assertEquals(2, storedSearchEngines.size)
+ assertEquals(searchEngine.id, storedSearchEngines[0].id)
+ assertEquals(searchEngine.name, storedSearchEngines[0].name)
+ assertEquals(searchEngine.type, storedSearchEngines[0].type)
+ assertEquals(searchEngine.resultUrls, storedSearchEngines[0].resultUrls)
+ assertEquals(searchEngineTwo.id, storedSearchEngines[1].id)
+ assertEquals(searchEngineTwo.name, storedSearchEngines[1].name)
+ assertEquals(searchEngineTwo.type, storedSearchEngines[1].type)
+ assertEquals(searchEngineTwo.resultUrls, storedSearchEngines[1].resultUrls)
+ }
+
+ @Test
+ fun `removeSearchEngine successfully deletes`() = runTest {
+ val searchEngine = SearchEngine(
+ id = "id1",
+ name = "example",
+ icon = mock(),
+ type = SearchEngine.Type.CUSTOM,
+ resultUrls = listOf("https://www.example.com/search"),
+ )
+
+ val storage = CustomSearchEngineStorage(testContext, coroutineContext)
+ assertTrue(storage.saveSearchEngine(searchEngine))
+
+ storage.removeSearchEngine(searchEngine.id)
+ assertTrue(storage.loadSearchEngineList().isEmpty())
+ }
+}
diff --git a/mobile/android/android-components/components/feature/search/src/test/java/mozilla/components/feature/search/storage/ParseSearchPluginsTest.kt b/mobile/android/android-components/components/feature/search/src/test/java/mozilla/components/feature/search/storage/ParseSearchPluginsTest.kt
new file mode 100644
index 0000000000..662fbd76b6
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/test/java/mozilla/components/feature/search/storage/ParseSearchPluginsTest.kt
@@ -0,0 +1,106 @@
+/* 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.feature.search.storage
+
+import android.text.TextUtils
+import mozilla.components.browser.state.search.SearchEngine
+import mozilla.components.feature.search.middleware.SearchExtraParams
+import org.junit.Assert.assertEquals
+import org.junit.Assert.assertFalse
+import org.junit.Assert.assertNotNull
+import org.junit.Assert.assertTrue
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.robolectric.ParameterizedRobolectricTestRunner
+import java.io.File
+import java.io.FileInputStream
+
+@RunWith(ParameterizedRobolectricTestRunner::class)
+class ParseSearchPluginsTest(private val searchEngineIdentifier: String) {
+
+ @Test
+ @Throws(Exception::class)
+ fun parserNoSearchExtraParams() {
+ val stream = FileInputStream(File(basePath, searchEngineIdentifier))
+ val searchEngine = SearchEngineReader(type = SearchEngine.Type.BUNDLED)
+ .loadStream(searchEngineIdentifier, stream)
+
+ assertEquals(searchEngineIdentifier, searchEngine.id)
+
+ assertNotNull(searchEngine.name)
+ assertFalse(TextUtils.isEmpty(searchEngine.name))
+
+ assertNotNull(searchEngine.icon)
+
+ val searchUrl = searchEngine.resultUrls
+ assertTrue(searchUrl.isNotEmpty())
+
+ stream.close()
+ }
+
+ @Test
+ @Throws(Exception::class)
+ fun parserWithSearchExtraParams() {
+ val stream = FileInputStream(File(basePath, searchEngineIdentifier))
+ val searchEngineName = "test"
+ val featureEnablerName = "t"
+ val featureEnablerParam = "enabled"
+ val channelIdName = "p"
+ val channelIdParam = "12345"
+ val searchExtraParams = SearchExtraParams(
+ searchEngineName = searchEngineName,
+ featureEnablerName = featureEnablerName,
+ featureEnablerParam = featureEnablerParam,
+ channelIdName = channelIdName,
+ channelIdParam = channelIdParam,
+ )
+ val searchEngine =
+ SearchEngineReader(
+ type = SearchEngine.Type.BUNDLED,
+ searchExtraParams = searchExtraParams,
+ ).loadStream(
+ identifier = searchEngineIdentifier,
+ stream = stream,
+ )
+
+ assertEquals(searchEngineIdentifier, searchEngine.id)
+
+ assertNotNull(searchEngine.name)
+ assertFalse(TextUtils.isEmpty(searchEngine.name))
+
+ assertNotNull(searchEngine.icon)
+
+ val searchUrl = searchEngine.resultUrls
+ assertTrue(searchUrl.isNotEmpty())
+
+ if (searchEngine.name.startsWith(searchEngineName)) {
+ for (url in searchUrl) {
+ assertTrue(url.contains("=$featureEnablerParam"))
+ assertTrue(url.endsWith("=$channelIdParam"))
+ }
+ } else {
+ for (url in searchUrl) {
+ assertFalse(url.endsWith("=$channelIdParam"))
+ assertFalse(url.contains("=$featureEnablerParam"))
+ }
+ }
+
+ stream.close()
+ }
+
+ companion object {
+ @JvmStatic
+ @ParameterizedRobolectricTestRunner.Parameters(name = "{0}")
+ fun searchPlugins(): Collection<Array<Any>> = basePath.list().orEmpty()
+ .mapNotNull { it as Any }
+ .map { arrayOf(it) }
+ .apply { if (isEmpty()) { throw IllegalStateException("No search plugins found.") } }
+
+ private val basePath: File
+ get() = ParseSearchPluginsTest::class.java.classLoader!!
+ .getResource("searchplugins").file
+ .let { File(it) }
+ }
+}
diff --git a/mobile/android/android-components/components/feature/search/src/test/java/mozilla/components/feature/search/storage/SearchEngineReaderTest.kt b/mobile/android/android-components/components/feature/search/src/test/java/mozilla/components/feature/search/storage/SearchEngineReaderTest.kt
new file mode 100644
index 0000000000..e1bdea0901
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/test/java/mozilla/components/feature/search/storage/SearchEngineReaderTest.kt
@@ -0,0 +1,84 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+package mozilla.components.feature.search.storage
+
+import android.util.AtomicFile
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import mozilla.components.browser.state.search.SearchEngine
+import mozilla.components.support.test.mock
+import mozilla.components.support.test.robolectric.testContext
+import org.junit.Assert.assertEquals
+import org.junit.Assert.assertTrue
+import org.junit.Test
+import org.junit.runner.RunWith
+import java.io.File
+import java.io.IOException
+
+@RunWith(AndroidJUnit4::class)
+class SearchEngineReaderTest {
+ @Test
+ fun `SearchEngineReader can read from a file`() {
+ val searchEngine = SearchEngine(
+ id = "id1",
+ name = "example",
+ icon = mock(),
+ inputEncoding = "ISO-8859-1",
+ type = SearchEngine.Type.CUSTOM,
+ resultUrls = listOf("https://www.example.com/search"),
+ )
+ val readSearchEngine = saveAndLoadSearchEngine(searchEngine)
+
+ assertEquals(searchEngine.id, readSearchEngine.id)
+ assertEquals(searchEngine.name, readSearchEngine.name)
+ assertEquals(searchEngine.inputEncoding, readSearchEngine.inputEncoding)
+ assertEquals(searchEngine.type, readSearchEngine.type)
+ assertEquals(searchEngine.resultUrls, readSearchEngine.resultUrls)
+ assertTrue(readSearchEngine.isGeneral)
+ }
+
+ @Test(expected = IOException::class)
+ fun `Parsing not existing file will throw exception`() {
+ val searchEngine = SearchEngine(
+ id = "id1",
+ name = "example",
+ icon = mock(),
+ type = SearchEngine.Type.CUSTOM,
+ resultUrls = listOf("https://www.example.com/search"),
+ )
+ val reader = SearchEngineReader(type = SearchEngine.Type.CUSTOM)
+ val invalidFile = AtomicFile(File("", ""))
+ reader.loadFile(searchEngine.id, invalidFile)
+ }
+
+ @Test
+ fun `WHEN SearchEngineReader is loading bundled search engines from a file THEN the correct SearchEngine properties are parsed`() {
+ for (id in GENERAL_SEARCH_ENGINE_IDS + setOf("mozilla", "wikipedia")) {
+ val searchEngine = SearchEngine(
+ id = id,
+ name = "example",
+ icon = mock(),
+ type = SearchEngine.Type.BUNDLED,
+ resultUrls = listOf("https://www.example.com/search"),
+ )
+ val readSearchEngine = saveAndLoadSearchEngine(searchEngine)
+
+ assertEquals(searchEngine.id, readSearchEngine.id)
+ assertEquals(searchEngine.name, readSearchEngine.name)
+ assertEquals(searchEngine.type, readSearchEngine.type)
+ assertEquals(searchEngine.resultUrls, readSearchEngine.resultUrls)
+ assertEquals(id in GENERAL_SEARCH_ENGINE_IDS, readSearchEngine.isGeneral)
+ }
+ }
+ private fun saveAndLoadSearchEngine(searchEngine: SearchEngine): SearchEngine {
+ val storage = CustomSearchEngineStorage(testContext)
+ val writer = SearchEngineWriter()
+ val reader = SearchEngineReader(type = searchEngine.type)
+ val file = storage.getSearchFile(searchEngine.id)
+
+ writer.saveSearchEngineXML(searchEngine, file)
+
+ return reader.loadFile(searchEngine.id, file)
+ }
+}
diff --git a/mobile/android/android-components/components/feature/search/src/test/java/mozilla/components/feature/search/storage/SearchEngineWriterTest.kt b/mobile/android/android-components/components/feature/search/src/test/java/mozilla/components/feature/search/storage/SearchEngineWriterTest.kt
new file mode 100644
index 0000000000..487231f6f9
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/test/java/mozilla/components/feature/search/storage/SearchEngineWriterTest.kt
@@ -0,0 +1,212 @@
+/* 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.feature.search.storage
+
+import android.util.AtomicFile
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import mozilla.components.browser.state.search.SearchEngine
+import mozilla.components.support.test.any
+import mozilla.components.support.test.mock
+import mozilla.components.support.test.robolectric.testContext
+import mozilla.components.support.test.whenever
+import org.junit.Assert.assertFalse
+import org.junit.Assert.assertNotNull
+import org.junit.Assert.assertTrue
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.Mockito.spy
+import org.w3c.dom.DOMException
+import org.w3c.dom.DOMException.INVALID_CHARACTER_ERR
+import org.w3c.dom.Document
+import java.io.File
+import java.io.StringWriter
+import javax.xml.parsers.DocumentBuilderFactory
+import javax.xml.transform.OutputKeys
+import javax.xml.transform.TransformerConfigurationException
+import javax.xml.transform.TransformerException
+import javax.xml.transform.TransformerFactory
+import javax.xml.transform.dom.DOMSource
+import javax.xml.transform.stream.StreamResult
+
+@RunWith(AndroidJUnit4::class)
+class SearchEngineWriterTest {
+ @Test
+ fun `buildSearchEngineXML builds search engine xml correctly`() {
+ val writer = SearchEngineWriter()
+ val searchEngine = SearchEngine(
+ id = "id1",
+ name = "example",
+ icon = mock(),
+ type = SearchEngine.Type.CUSTOM,
+ inputEncoding = "UTF-8",
+ resultUrls = listOf("https://www.example.com/search?q={searchTerms}'"),
+ )
+
+ val document = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument()
+ writer.buildSearchEngineXML(searchEngine, document)
+ val searchXML = document.xmlToString()
+ assertTrue(searchXML!!.contains(searchEngine.name))
+ assertTrue(searchXML.contains(IMAGE_URI_PREFIX))
+ assertTrue(searchXML.contains(URL_TYPE_SEARCH_HTML))
+ assertTrue(searchXML.contains("https://www.example.com/search?q={searchTerms}"))
+ assertTrue(searchXML.contains("UTF-8"))
+ assertFalse(searchXML.contains(URL_TYPE_SUGGEST_JSON))
+ }
+
+ @Test
+ fun `buildSearchEngineXML builds multiple resultUrls correctly`() {
+ val writer = SearchEngineWriter()
+ val searchEngine = SearchEngine(
+ id = "id1",
+ name = "example",
+ icon = mock(),
+ type = SearchEngine.Type.CUSTOM,
+ resultUrls = listOf(
+ "https://www.example.com/search?q=%s",
+ "https://www.example.com/search1?q=%s",
+ "https://www.example.com/search2?q=%s",
+ ),
+ )
+
+ val document = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument()
+ writer.buildSearchEngineXML(searchEngine, document)
+ val searchXML = document.xmlToString()
+ assertTrue(searchXML!!.contains(searchEngine.name))
+ assertTrue(searchXML.contains(IMAGE_URI_PREFIX))
+ assertTrue(searchXML.contains(URL_TYPE_SEARCH_HTML))
+ searchEngine.resultUrls.forEach {
+ val url = it.replace("%s", "{searchTerms}")
+ searchXML.contains(url)
+ }
+ assertFalse(searchXML.contains(URL_TYPE_SUGGEST_JSON))
+ }
+
+ @Test
+ fun `buildSearchEngineXML builds suggestUrl correctly`() {
+ val writer = SearchEngineWriter()
+ val searchEngine = SearchEngine(
+ id = "id1",
+ name = "example",
+ icon = mock(),
+ type = SearchEngine.Type.CUSTOM,
+ suggestUrl = "https://www.example.com/search-suggestion?q=%s",
+ )
+
+ val document = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument()
+ writer.buildSearchEngineXML(searchEngine, document)
+ val searchXML = document.xmlToString()
+ assertTrue(searchXML!!.contains(searchEngine.name))
+ assertTrue(searchXML.contains(IMAGE_URI_PREFIX))
+ assertFalse(searchXML.contains(URL_TYPE_SEARCH_HTML))
+ assertTrue(searchXML.contains(URL_TYPE_SUGGEST_JSON))
+ assertTrue(searchXML.contains("https://www.example.com/search-suggestion?q={searchTerms}"))
+ }
+
+ @Test
+ fun `buildSearchEngineXML successfully for search engines with XML escaped characters`() {
+ val writer = SearchEngineWriter()
+ val invalidSearchEngineNameAmp = SearchEngine(
+ id = "id1",
+ name = "&&&example&&&",
+ icon = mock(),
+ type = SearchEngine.Type.CUSTOM,
+ suggestUrl = "https://www.example.com/search-suggestion?q=%s",
+ )
+ val invalidResultUrlLessSign = SearchEngine(
+ id = "id1",
+ name = "example",
+ icon = mock(),
+ type = SearchEngine.Type.CUSTOM,
+ resultUrls = listOf("https://www.example.com/search?<q=%s"),
+ )
+ val invalidResultUrlGreaterSign = SearchEngine(
+ id = "id1",
+ name = "example",
+ icon = mock(),
+ type = SearchEngine.Type.CUSTOM,
+ resultUrls = listOf("https://www.example.com/search?>q=%s"),
+ )
+ val invalidSuggestionUrlApo = SearchEngine(
+ id = "id1",
+ name = "example",
+ icon = mock(),
+ type = SearchEngine.Type.CUSTOM,
+ suggestUrl = "https://www.example.com/search-'suggestion'?q=%s",
+ )
+
+ assertNotNull(
+ writer.buildSearchEngineXML(
+ invalidSearchEngineNameAmp,
+ DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument(),
+ ),
+ )
+ assertNotNull(
+ writer.buildSearchEngineXML(
+ invalidResultUrlLessSign,
+ DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument(),
+ ),
+ )
+ assertNotNull(
+ writer.buildSearchEngineXML(
+ invalidResultUrlGreaterSign,
+ DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument(),
+ ),
+ )
+ assertNotNull(
+ writer.buildSearchEngineXML(
+ invalidSuggestionUrlApo,
+ DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument(),
+ ),
+ )
+ }
+
+ @Test
+ fun `saveSearchEngineXML returns false when failed to write to a bad file data`() {
+ val writer = spy(SearchEngineWriter())
+ val searchEngine = SearchEngine(
+ id = "id1",
+ name = "example",
+ icon = mock(),
+ type = SearchEngine.Type.CUSTOM,
+ resultUrls = listOf("https://www.example.com/search?q=%s'"),
+ )
+
+ val badFile = AtomicFile(File("", ""))
+ assertFalse(writer.saveSearchEngineXML(searchEngine, badFile))
+ }
+
+ @Test
+ fun `saveSearchEngineXML returns false when there's DOMException while generating XML doc`() {
+ val storage = CustomSearchEngineStorage(testContext)
+ val writer = spy(SearchEngineWriter())
+ val searchEngine = SearchEngine(
+ id = "id1",
+ name = "example",
+ icon = mock(),
+ type = SearchEngine.Type.CUSTOM,
+ resultUrls = listOf("https://www.example.com/search?q=%s'"),
+ )
+
+ val file = storage.getSearchFile(searchEngine.id)
+ val mockDoc: Document = mock()
+ whenever(mockDoc.createElement(any())).thenThrow(DOMException(INVALID_CHARACTER_ERR, ""))
+ assertFalse(writer.saveSearchEngineXML(searchEngine, file, mockDoc))
+ }
+}
+
+private fun Document.xmlToString(): String? {
+ val writer = StringWriter()
+ try {
+ val tf = TransformerFactory.newInstance().newTransformer()
+ tf.setOutputProperty(OutputKeys.ENCODING, "UTF-8")
+ tf.transform(DOMSource(this), StreamResult(writer))
+ } catch (e: TransformerConfigurationException) {
+ return null
+ } catch (e: TransformerException) {
+ return null
+ }
+
+ return writer.toString()
+}
diff --git a/mobile/android/android-components/components/feature/search/src/test/java/mozilla/components/feature/search/suggestions/ParserTest.kt b/mobile/android/android-components/components/feature/search/src/test/java/mozilla/components/feature/search/suggestions/ParserTest.kt
new file mode 100644
index 0000000000..6d69abd67b
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/test/java/mozilla/components/feature/search/suggestions/ParserTest.kt
@@ -0,0 +1,149 @@
+/* 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.feature.search.suggestions
+
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import org.junit.Assert.assertEquals
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@RunWith(AndroidJUnit4::class)
+class ParserTest {
+
+ @Test
+ fun `can parse a response from Google`() {
+ val json = "[\"firefox\",[\"firefox\",\"firefox for mac\",\"firefox quantum\",\"firefox update\",\"firefox esr\",\"firefox focus\",\"firefox addons\",\"firefox extensions\",\"firefox nightly\",\"firefox clear cache\"]]"
+
+ val results = defaultResponseParser(json)
+ val expectedResults = listOf("firefox", "firefox for mac", "firefox quantum", "firefox update", "firefox esr", "firefox focus", "firefox addons", "firefox extensions", "firefox nightly", "firefox clear cache")
+ assertEquals(expectedResults, results)
+ }
+
+ @Test
+ fun `can parse a response from Amazon`() {
+ val json = "[\"firefox\",[\"firefox for fire tv\",\"firefox movie\",\"firefox app\",\"firefox books\",\"firefox glider\",\"firefox stick\",\"firefox for firestick\",\"firefox\",\"firefox books series\",\"firefox browser\"],[{\"nodes\":[{\"name\":\"Apps & Games\",\"alias\":\"mobile-apps\"}]},{},{},{},{},{},{},{},{},{}],[],\"344I6KZL0KU9N\"]"
+
+ val results = defaultResponseParser(json)
+ val expectedResults = listOf("firefox for fire tv", "firefox movie", "firefox app", "firefox books", "firefox glider", "firefox stick", "firefox for firestick", "firefox", "firefox books series", "firefox browser")
+ assertEquals(expectedResults, results)
+ }
+
+ @Test
+ fun `can parse a response from Azerdict`() {
+ val json = "{\"query\":\"code\",\"suggestions\":[\"code\",\"codec\",\"codex\",\"codeine\",\"code of laws\"]}"
+
+ val results = azerdictResponseParser(json)
+ val expectedResults = listOf("code", "codec", "codex", "codeine", "code of laws")
+ assertEquals(expectedResults, results)
+ }
+
+ @Test
+ fun `can parse a response from Baidu`() {
+ val json = "[\"firefox\",[\"firefox rocket\",\"firefox手机浏览器\",\"firefox是什么意思\",\"firefox focus\",\"firefox风哥\",\"firefox官网\",\"firefox吧\",\"firefox os\",\"firefox国际版\",\"firefox android\"]]"
+
+ val results = defaultResponseParser(json)
+ val expectedResults = listOf("firefox rocket", "firefox手机浏览器", "firefox是什么意思", "firefox focus", "firefox风哥", "firefox官网", "firefox吧", "firefox os", "firefox国际版", "firefox android")
+ assertEquals(expectedResults, results)
+ }
+
+ @Test
+ fun `can parse a response from Bing`() {
+ val json = "[\"firefox\",[\"firefox\",\"firefox download\",\"firefox for windows 10\",\"firefox browser\",\"firefox quantum\",\"firefox esr\",\"firefox 64-bit\",\"firefox mozilla\",\"firefox nightly\",\"firefox update\",\"firefox install\",\"firefox focus\",\"firefox beta\",\"firefox developer edition\",\"firefox portable\",\"firefox add-ons\"]]"
+
+ val results = defaultResponseParser(json)
+ val expectedResults = listOf("firefox", "firefox download", "firefox for windows 10", "firefox browser", "firefox quantum", "firefox esr", "firefox 64-bit", "firefox mozilla", "firefox nightly", "firefox update", "firefox install", "firefox focus", "firefox beta", "firefox developer edition", "firefox portable", "firefox add-ons")
+ assertEquals(expectedResults, results)
+ }
+
+ @Test
+ fun `can parse a response from Coccoc`() {
+ val json = "[\"firefox\",[\"firefox\",\"firefox tiếng việt\",\"firefox download\",\"firefox quantum\",\"firefox 51\",\"firefox 42\",\"firefox english\",\"firefox portable\",\"firefox 49\",\"firefox viet nam\"],[\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\"],[\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\"],{\"google:suggesttype\":[\"QUERY\",\"QUERY\",\"QUERY\",\"QUERY\",\"QUERY\",\"QUERY\",\"QUERY\",\"QUERY\",\"QUERY\",\"QUERY\"]}]"
+
+ val results = defaultResponseParser(json)
+ val expectedResults = listOf("firefox", "firefox tiếng việt", "firefox download", "firefox quantum", "firefox 51", "firefox 42", "firefox english", "firefox portable", "firefox 49", "firefox viet nam")
+ assertEquals(expectedResults, results)
+ }
+
+ @Test
+ fun `can parse a response from Daum`() {
+ val json = "{\"q\":\"firefox\",\"rq\":\"firefox\",\"items\":[\"firefox\",\"firefox download\",\"firefox focus\",\"mozilla firefox\",\"firefox adobe flash\",\"firefox 삭제\",\"firefox 한글판\",\"firefox 즐겨찾기 가져오기\",\"firefox quantum\",\"firefox 57\",\"mozila firefox\",\"mozilla firefox download\",\"mozilla firefox 삭제\",\"Hacking Firefox\",\"Programming Firefox\"],\"r_items\":[]}"
+
+ val results = daumResponseParser(json)
+ val expectedResults = listOf("firefox", "firefox download", "firefox focus", "mozilla firefox", "firefox adobe flash", "firefox 삭제", "firefox 한글판", "firefox 즐겨찾기 가져오기", "firefox quantum", "firefox 57", "mozila firefox", "mozilla firefox download", "mozilla firefox 삭제", "Hacking Firefox", "Programming Firefox")
+ assertEquals(expectedResults, results)
+ }
+
+ @Test
+ fun `can parse a response from Duck Duck Go`() {
+ val json = "[\"firefox\",[\"firefox\",\"firefox browser\",\"firefox.com\",\"firefox update\",\"firefox for mac\",\"firefox quantum\",\"firefox extensions\",\"firefox esr\",\"firefox clear cache\",\"firefox themes\"]]"
+
+ val results = defaultResponseParser(json)
+ val expectedResults = listOf("firefox", "firefox browser", "firefox.com", "firefox update", "firefox for mac", "firefox quantum", "firefox extensions", "firefox esr", "firefox clear cache", "firefox themes")
+ assertEquals(expectedResults, results)
+ }
+
+ @Test
+ fun `can parse a response from Naver`() {
+ val json = "[\"firefox\",[\"firefox\",\"Mozilla Firefox\",\"firefox add-on to detect vulnerable websites\",\"firefox ak\",\"firefox as gaeilge\",\"firefox developer edition\",\"firefox down\",\"firefox for dummies\",\"firefox for mac\",\"firefox for mobile\"],[],[\"http://search.naver.com/search.naver?where=nexearch&sm=osp_sug&ie=utf8&query=firefox\",\"http://search.naver.com/search.naver?where=nexearch&sm=osp_sug&ie=utf8&query=Mozilla+Firefox\",\"http://search.naver.com/search.naver?where=nexearch&sm=osp_sug&ie=utf8&query=firefox+add-on+to+detect+vulnerable+websites\",\"http://search.naver.com/search.naver?where=nexearch&sm=osp_sug&ie=utf8&query=firefox+ak\",\"http://search.naver.com/search.naver?where=nexearch&sm=osp_sug&ie=utf8&query=firefox+as+gaeilge\",\"http://search.naver.com/search.naver?where=nexearch&sm=osp_sug&ie=utf8&query=firefox+developer+edition\",\"http://search.naver.com/search.naver?where=nexearch&sm=osp_sug&ie=utf8&query=firefox+down\",\"http://search.naver.com/search.naver?where=nexearch&sm=osp_sug&ie=utf8&query=firefox+for+dummies\",\"http://search.naver.com/search.naver?where=nexearch&sm=osp_sug&ie=utf8&query=firefox+for+mac\",\"http://search.naver.com/search.naver?where=nexearch&sm=osp_sug&ie=utf8&query=firefox+for+mobile\"]]"
+
+ val results = defaultResponseParser(json)
+ val expectedResults = listOf("firefox", "Mozilla Firefox", "firefox add-on to detect vulnerable websites", "firefox ak", "firefox as gaeilge", "firefox developer edition", "firefox down", "firefox for dummies", "firefox for mac", "firefox for mobile")
+ assertEquals(expectedResults, results)
+ }
+
+ @Test
+ fun `can parse a response from Prisjakt`() {
+ val json = "[\"firefox\",[\"Firefox\",\"Firefox\",\"Mountain Equipment Firefox Pants (Herr)\",\"Mountain Equipment Firefox (Herr)\",\"Firefox (DE)\"],[\"L\\u00e4gsta pris: 149:-\",\"L\\u00e4gsta pris: 205:-\",\"L\\u00e4gsta pris: 1 559:-\",\"L\\u00e4gsta pris: 2 773:-\",\"L\\u00e4gsta pris: 198:-\"],[\"https:\\/\\/www.prisjakt.nu\\/produkt.php?p=886794\",\"https:\\/\\/www.prisjakt.nu\\/produkt.php?p=53272\",\"https:\\/\\/www.prisjakt.nu\\/produkt.php?p=3548472\",\"https:\\/\\/www.prisjakt.nu\\/produkt.php?p=1822581\",\"https:\\/\\/www.prisjakt.nu\\/produkt.php?p=3408551\"]]"
+
+ val results = defaultResponseParser(json)
+ val expectedResults = listOf("Firefox", "Firefox", "Mountain Equipment Firefox Pants (Herr)", "Mountain Equipment Firefox (Herr)", "Firefox (DE)")
+ assertEquals(expectedResults, results)
+ }
+
+ @Test
+ fun `can parse a response from Qwant`() {
+ val json = "{\"status\":\"success\",\"data\":{\"items\":[{\"value\":\"firefox (video game)\",\"suggestType\":3},{\"value\":\"firefox addons\",\"suggestType\":12},{\"value\":\"firefox\",\"suggestType\":2},{\"value\":\"firefox quantum\",\"suggestType\":12},{\"value\":\"firefox focus\",\"suggestType\":12}],\"special\":[],\"availableQwick\":[]}}"
+
+ val results = qwantResponseParser(json)
+ val expectedResults = listOf("firefox (video game)", "firefox addons", "firefox", "firefox quantum", "firefox focus")
+ assertEquals(expectedResults, results)
+ }
+
+ @Test
+ fun `can parse a response from Seznam`() {
+ val json = "[\"firefox\", [\"firefox\", \"firefox ak keep it up\", \"firefox ak city to city\", \"firefox ak all those people\", \"firefox ak who can act\", \"firefox ak color the trees\", \"firefox ak habibi\", \"firefox ak zodiac\", \"firefox ak the draft\", \"mozilla firefox\"], [], []]"
+
+ val results = defaultResponseParser(json)
+ val expectedResults = listOf("firefox", "firefox ak keep it up", "firefox ak city to city", "firefox ak all those people", "firefox ak who can act", "firefox ak color the trees", "firefox ak habibi", "firefox ak zodiac", "firefox ak the draft", "mozilla firefox")
+ assertEquals(expectedResults, results)
+ }
+
+ @Test
+ fun `can parse a response from Wikipedia`() {
+ val json = "[\"code\",[\"Code\",\"Code Geass\",\"Codeine\",\"Codename: Kids Next Door\",\"Code page\",\"Codex Sinaiticus\",\"Code talker\",\"Code Black (TV series)\",\"Codependency\",\"Codex Vaticanus\"],[\"In communications and information processing, code is a system of rules to convert information\\u2014such as a letter, word, sound, image, or gesture\\u2014into another form or representation, sometimes shortened or secret, for communication through a communication channel or storage in a storage medium.\",\"Code Geass: Lelouch of the Rebellion (\\u30b3\\u30fc\\u30c9\\u30ae\\u30a2\\u30b9 \\u53cd\\u9006\\u306e\\u30eb\\u30eb\\u30fc\\u30b7\\u30e5, K\\u014ddo Giasu: Hangyaku no Rur\\u016bshu), often referred to as simply Code Geass, is a Japanese anime series created by Sunrise, directed by Gor\\u014d Taniguchi, and written by Ichir\\u014d \\u014ckouchi, with original character designs by manga authors Clamp.\",\"Codeine is an opiate used to treat pain, as a cough medicine, and for diarrhea. It is typically used to treat mild to moderate degrees of pain.\",\"Codename: Kids Next Door, commonly abbreviated to Kids Next Door or KND, is an American animated television series created by Tom Warburton for Cartoon Network, and the 13th of the network's Cartoon Cartoons.\",\"In computing, a code page is a table of values that describes the character set used for encoding a particular set of characters, usually combined with a number of control characters.\",\"Codex Sinaiticus (Greek: \\u03a3\\u03b9\\u03bd\\u03b1\\u03ca\\u03c4\\u03b9\\u03ba\\u03cc\\u03c2 \\u039a\\u03ce\\u03b4\\u03b9\\u03ba\\u03b1\\u03c2, Hebrew: \\u05e7\\u05d5\\u05d3\\u05e7\\u05e1 \\u05e1\\u05d9\\u05e0\\u05d0\\u05d9\\u05d8\\u05d9\\u05e7\\u05d5\\u05e1\\u200e; Shelfmarks and references: London, Brit.\",\"Code talkers are people in the 20th century who used obscure languages as a means of secret communication during wartime.\",\"Code Black is an American medical drama television series created by Michael Seitzman which premiered on CBS on September 30, 2015. It takes place in an overcrowded and understaffed emergency room in Los Angeles, California, and is based on a documentary by Ryan McGarry.\",\"Codependency is a controversial concept for a dysfunctional helping relationship where one person supports or enables another person's addiction, poor mental health, immaturity, irresponsibility, or under-achievement.\",\"The Codex Vaticanus (The Vatican, Bibl. Vat., Vat. gr. 1209; no. B or 03 Gregory-Aland, \\u03b4 1 von Soden) is regarded as the oldest extant manuscript of the Greek Bible (Old and New Testament), one of the four great uncial codices.\"],[\"https://en.wikipedia.org/wiki/Code\",\"https://en.wikipedia.org/wiki/Code_Geass\",\"https://en.wikipedia.org/wiki/Codeine\",\"https://en.wikipedia.org/wiki/Codename:_Kids_Next_Door\",\"https://en.wikipedia.org/wiki/Code_page\",\"https://en.wikipedia.org/wiki/Codex_Sinaiticus\",\"https://en.wikipedia.org/wiki/Code_talker\",\"https://en.wikipedia.org/wiki/Code_Black_(TV_series)\",\"https://en.wikipedia.org/wiki/Codependency\",\"https://en.wikipedia.org/wiki/Codex_Vaticanus\"]]"
+
+ val results = defaultResponseParser(json)
+ val expectedResults = listOf("Code", "Code Geass", "Codeine", "Codename: Kids Next Door", "Code page", "Codex Sinaiticus", "Code talker", "Code Black (TV series)", "Codependency", "Codex Vaticanus")
+ assertEquals(expectedResults, results)
+ }
+
+ @Test
+ fun `can parse a response from Yahoo`() {
+ val json = "[\"firefox\",[\"firefox\",\"firefox browser\",\"firefox.com\",\"firefox update\"],[],[]]"
+
+ val results = defaultResponseParser(json)
+ val expectedResults = listOf("firefox", "firefox browser", "firefox.com", "firefox update")
+ assertEquals(expectedResults, results)
+ }
+
+ @Test
+ fun `can parse a response from Yandex`() {
+ val json = "[\"firefox\",[\"firefox\",\"firefox download\",\"firefox browser\",\"firefox update\",\"firefox.com\"]]"
+
+ val results = defaultResponseParser(json)
+ val expectedResults = listOf("firefox", "firefox download", "firefox browser", "firefox update", "firefox.com")
+ assertEquals(expectedResults, results)
+ }
+}
diff --git a/mobile/android/android-components/components/feature/search/src/test/java/mozilla/components/feature/search/suggestions/SearchSuggestionClientTest.kt b/mobile/android/android-components/components/feature/search/src/test/java/mozilla/components/feature/search/suggestions/SearchSuggestionClientTest.kt
new file mode 100644
index 0000000000..3ffd14698a
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/test/java/mozilla/components/feature/search/suggestions/SearchSuggestionClientTest.kt
@@ -0,0 +1,110 @@
+/* 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.feature.search.suggestions
+
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import kotlinx.coroutines.test.runTest
+import mozilla.components.browser.state.state.BrowserState
+import mozilla.components.browser.state.state.SearchState
+import mozilla.components.browser.state.store.BrowserStore
+import mozilla.components.feature.search.ext.createSearchEngine
+import mozilla.components.support.test.mock
+import mozilla.components.support.test.robolectric.testContext
+import org.junit.Assert.assertEquals
+import org.junit.Test
+import org.junit.runner.RunWith
+import java.io.IOException
+
+@RunWith(AndroidJUnit4::class)
+class SearchSuggestionClientTest {
+ companion object {
+ val GOOGLE_MOCK_RESPONSE: SearchSuggestionFetcher = { "[\"firefox\",[\"firefox\",\"firefox for mac\",\"firefox quantum\",\"firefox update\",\"firefox esr\",\"firefox focus\",\"firefox addons\",\"firefox extensions\",\"firefox nightly\",\"firefox clear cache\"]]" }
+ val QWANT_MOCK_RESPONSE: SearchSuggestionFetcher = { "{\"status\":\"success\",\"data\":{\"items\":[{\"value\":\"firefox (video game)\",\"suggestType\":3},{\"value\":\"firefox addons\",\"suggestType\":12},{\"value\":\"firefox\",\"suggestType\":2},{\"value\":\"firefox quantum\",\"suggestType\":12},{\"value\":\"firefox focus\",\"suggestType\":12}],\"special\":[],\"availableQwick\":[]}}" }
+ val SERVER_ERROR_RESPONSE: SearchSuggestionFetcher = { "Server error. Try again later" }
+ }
+
+ private val searchEngine = createSearchEngine(
+ name = "Test",
+ url = "https://localhost?q={searchTerms}",
+ suggestUrl = "https://localhost/suggestions?q={searchTerms}",
+ icon = mock(),
+ )
+
+ @Test
+ fun `Get a list of results based on the Google search engine`() = runTest {
+ val client = SearchSuggestionClient(searchEngine, GOOGLE_MOCK_RESPONSE)
+ val expectedResults = listOf("firefox", "firefox for mac", "firefox quantum", "firefox update", "firefox esr", "firefox focus", "firefox addons", "firefox extensions", "firefox nightly", "firefox clear cache")
+
+ val results = client.getSuggestions("firefox")
+
+ assertEquals(expectedResults, results)
+ }
+
+ @Test
+ fun `Get a list of results based on a non google search engine`() = runTest {
+ val qwant = createSearchEngine(
+ name = "Qwant",
+ url = "https://localhost?q={searchTerms}",
+ suggestUrl = "https://localhost/suggestions?q={searchTerms}",
+ icon = mock(),
+ )
+ val client = SearchSuggestionClient(qwant, QWANT_MOCK_RESPONSE)
+ val expectedResults = listOf("firefox (video game)", "firefox addons", "firefox", "firefox quantum", "firefox focus")
+
+ val results = client.getSuggestions("firefox")
+
+ assertEquals(expectedResults, results)
+ }
+
+ @Test(expected = SearchSuggestionClient.ResponseParserException::class)
+ fun `Check that a bad response will throw a parser exception`() = runTest {
+ val client = SearchSuggestionClient(searchEngine, SERVER_ERROR_RESPONSE)
+
+ client.getSuggestions("firefox")
+ }
+
+ @Test(expected = SearchSuggestionClient.FetchException::class)
+ fun `Check that an exception in the suggestionFetcher will re-throw an IOException`() = runTest {
+ val client = SearchSuggestionClient(searchEngine) { throw IOException() }
+
+ client.getSuggestions("firefox")
+ }
+
+ @Test
+ fun `Check that a search engine without a suggestURI will return an empty suggestion list`() = runTest {
+ val searchEngine = createSearchEngine(
+ name = "Test",
+ url = "https://localhost?q={searchTerms}",
+ icon = mock(),
+ )
+ val client = SearchSuggestionClient(searchEngine) { "no-op" }
+
+ val results = client.getSuggestions("firefox")
+
+ assertEquals(emptyList<String>(), results)
+ }
+
+ @Test
+ fun `Default search engine is used if search engine manager provided`() = runTest {
+ val store = BrowserStore(
+ BrowserState(
+ search = SearchState(
+ regionSearchEngines = listOf(searchEngine),
+ ),
+ ),
+ )
+
+ val client = SearchSuggestionClient(
+ testContext,
+ store,
+ GOOGLE_MOCK_RESPONSE,
+ )
+ val expectedResults = listOf("firefox", "firefox for mac", "firefox quantum", "firefox update", "firefox esr", "firefox focus", "firefox addons", "firefox extensions", "firefox nightly", "firefox clear cache")
+
+ val results = client.getSuggestions("firefox")
+
+ assertEquals(expectedResults, results)
+ }
+}
diff --git a/mobile/android/android-components/components/feature/search/src/test/java/mozilla/components/feature/search/telemetry/BaseSearchTelemetryTest.kt b/mobile/android/android-components/components/feature/search/src/test/java/mozilla/components/feature/search/telemetry/BaseSearchTelemetryTest.kt
new file mode 100644
index 0000000000..90024bbb56
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/test/java/mozilla/components/feature/search/telemetry/BaseSearchTelemetryTest.kt
@@ -0,0 +1,187 @@
+/* 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.feature.search.telemetry
+
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import kotlinx.coroutines.runBlocking
+import mozilla.components.browser.state.store.BrowserStore
+import mozilla.components.concept.engine.Engine
+import mozilla.components.support.test.any
+import mozilla.components.support.test.eq
+import mozilla.components.support.test.mock
+import org.json.JSONObject
+import org.junit.Assert.assertEquals
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.Mock
+import org.mockito.Mockito.doAnswer
+import org.mockito.Mockito.doReturn
+import org.mockito.Mockito.spy
+import org.mockito.Mockito.verify
+import org.mockito.Mockito.`when`
+import java.io.File
+
+@RunWith(AndroidJUnit4::class)
+class BaseSearchTelemetryTest {
+
+ private lateinit var baseTelemetry: BaseSearchTelemetry
+ private lateinit var handler: BaseSearchTelemetry.SearchTelemetryMessageHandler
+
+ @Mock
+ private lateinit var mockRepo: SerpTelemetryRepository
+
+ private val mockReadJson: () -> JSONObject = mock()
+ private val mockRootStorageDirectory: File = mock()
+
+ private fun createMockProviderList(): List<SearchProviderModel> = listOf(
+ SearchProviderModel(
+ schema = 1698656464939,
+ taggedCodes = listOf("monline_7_dg"),
+ telemetryId = "baidu",
+ organicCodes = emptyList(),
+ codeParamName = "tn",
+ queryParamNames = listOf("wd"),
+ searchPageRegexp = "^https://(?:m|www)\\\\.baidu\\\\.com/(?:s|baidu)",
+ followOnParamNames = listOf("oq"),
+ extraAdServersRegexps = listOf("^https?://www\\\\.baidu\\\\.com/baidu\\\\.php?"),
+ expectedOrganicCodes = emptyList(),
+ ),
+ )
+
+ private val rawJson = """
+ {
+ "data": [
+ {
+ "schema": 1698656464939,
+ "taggedCodes": [
+ "monline_7_dg"
+ ],
+ "telemetryId": "baidu",
+ "organicCodes": [],
+ "codeParamName": "tn",
+ "queryParamNames": [
+ "wd"
+ ],
+ "searchPageRegexp": "^https://(?:m|www)\\.baidu\\.com/(?:s|baidu)",
+ "followOnParamNames": [
+ "oq"
+ ],
+ "extraAdServersRegexps": [
+ "^https?://www\\.baidu\\.com/baidu\\.php?"
+ ],
+ "id": "19c434a3-d173-4871-9743-290ac92a3f6a",
+ "last_modified": 1698666532326
+ }],
+ "timestamp": 16
+}
+ """.trimIndent()
+
+ @Before
+ fun setup() {
+ baseTelemetry = spy(
+ object : BaseSearchTelemetry() {
+ override suspend fun install(
+ engine: Engine,
+ store: BrowserStore,
+ providerList: List<SearchProviderModel>,
+ ) {
+ // mock, do nothing
+ }
+
+ override fun processMessage(message: JSONObject) {
+ // mock, do nothing
+ }
+ },
+ )
+ handler = baseTelemetry.SearchTelemetryMessageHandler()
+ mockRepo = spy(SerpTelemetryRepository(mockRootStorageDirectory, mockReadJson, "test"))
+ }
+
+ @Test
+ fun `GIVEN an engine WHEN installWebExtension is called THEN the provided extension is installed in engine`() {
+ val engine: Engine = mock()
+ val store: BrowserStore = mock()
+ val id = "id"
+ val resourceUrl = "resourceUrl"
+ val messageId = "messageId"
+ val extensionInfo = ExtensionInfo(id, resourceUrl, messageId)
+
+ baseTelemetry.installWebExtension(engine, store, extensionInfo)
+
+ verify(engine).installBuiltInWebExtension(
+ id = eq(id),
+ url = eq(resourceUrl),
+ onSuccess = any(),
+ onError = any(),
+ )
+ }
+
+ @Test
+ fun `GIVEN a search provider does not exist for the url WHEN getProviderForUrl is called THEN return null`() {
+ val url = "https://www.mozilla.com/search?q=firefox"
+ baseTelemetry.providerList = createMockProviderList()
+
+ assertEquals(null, baseTelemetry.getProviderForUrl(url))
+ }
+
+ @Test(expected = IllegalStateException::class)
+ fun `GIVEN an extension message WHEN that cannot be processed THEN throw IllegalStateException`() {
+ val message = "message"
+
+ handler.onMessage(message, mock())
+ }
+
+ @Test
+ fun `GIVEN an extension message WHEN received THEN pass it to processMessage`() {
+ val message = JSONObject()
+
+ handler.onMessage(message, mock())
+
+ verify(baseTelemetry).processMessage(message)
+ }
+
+ @Test
+ fun `GIVEN empty cacheResponse WHEN initializeProviderList is called THEN update providerList`(): Unit =
+ runBlocking {
+ val localResponse = JSONObject(rawJson)
+ val cacheResponse: Pair<ULong, List<SearchProviderModel>> = Pair(0u, emptyList())
+
+ `when`(mockRepo.loadProvidersFromCache()).thenReturn(cacheResponse)
+ doAnswer {
+ localResponse
+ }.`when`(mockReadJson)()
+
+ `when`(mockRepo.parseLocalPreinstalledData(localResponse)).thenReturn(createMockProviderList())
+ doReturn(Unit).`when`(mockRepo).fetchRemoteResponse(any())
+
+ baseTelemetry.setProviderList(mockRepo.updateProviderList())
+
+ assertEquals(baseTelemetry.providerList.toString(), createMockProviderList().toString())
+ }
+
+ @Test
+ fun `GIVEN non-empty cacheResponse WHEN initializeProviderList is called THEN update providerList`(): Unit =
+ runBlocking {
+ val localResponse = JSONObject(rawJson)
+ val cacheResponse: Pair<ULong, List<SearchProviderModel>> = Pair(123u, createMockProviderList())
+
+ `when`(mockRepo.loadProvidersFromCache()).thenReturn(cacheResponse)
+ doAnswer {
+ localResponse
+ }.`when`(mockReadJson)()
+ doReturn(Unit).`when`(mockRepo).fetchRemoteResponse(any())
+
+ baseTelemetry.setProviderList(mockRepo.updateProviderList())
+
+ assertEquals(baseTelemetry.providerList.toString(), createMockProviderList().toString())
+ }
+
+ fun getProviderForUrl(url: String): SearchProviderModel? {
+ return createMockProviderList().find { provider ->
+ provider.searchPageRegexp.pattern.toRegex().containsMatchIn(url)
+ }
+ }
+}
diff --git a/mobile/android/android-components/components/feature/search/src/test/java/mozilla/components/feature/search/telemetry/SearchProviderModelTest.kt b/mobile/android/android-components/components/feature/search/src/test/java/mozilla/components/feature/search/telemetry/SearchProviderModelTest.kt
new file mode 100644
index 0000000000..89e4620101
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/test/java/mozilla/components/feature/search/telemetry/SearchProviderModelTest.kt
@@ -0,0 +1,40 @@
+/* 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.feature.search.telemetry
+
+import org.junit.Assert
+import org.junit.Test
+
+class SearchProviderModelTest {
+ private val testSearchProvider =
+ SearchProviderModel(
+ schema = 1671479978127,
+ taggedCodes = listOf("mzl", "813cf1dd", "16eeffc4"),
+ telemetryId = "test",
+ organicCodes = listOf(),
+ codeParamName = "tt",
+ queryParamNames = listOf("q"),
+ searchPageRegexp = "^https://www\\.ecosia\\.org/",
+ expectedOrganicCodes = listOf(),
+ extraAdServersRegexps = listOf(
+ "^https:\\/\\/www\\.bing\\.com\\/acli?c?k",
+ "^https:\\/\\/www\\.bing\\.com\\/fd\\/ls\\/GLinkPingPost\\.aspx.*acli?c?k",
+ ),
+ )
+
+ @Test
+ fun `test search provider contains ads`() {
+ val ad = "https://www.bing.com/aclick"
+ val nonAd = "https://www.bing.com/notanad"
+ Assert.assertTrue(testSearchProvider.containsAdLinks(listOf(ad, nonAd)))
+ }
+
+ @Test
+ fun `test search provider does not contain ads`() {
+ val nonAd1 = "https://www.yahoo.com/notanad"
+ val nonAd2 = "https://www.google.com/"
+ Assert.assertFalse(testSearchProvider.containsAdLinks(listOf(nonAd1, nonAd2)))
+ }
+}
diff --git a/mobile/android/android-components/components/feature/search/src/test/java/mozilla/components/feature/search/telemetry/SerpTelemetryRepositoryTest.kt b/mobile/android/android-components/components/feature/search/src/test/java/mozilla/components/feature/search/telemetry/SerpTelemetryRepositoryTest.kt
new file mode 100644
index 0000000000..50ae3c6aee
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/test/java/mozilla/components/feature/search/telemetry/SerpTelemetryRepositoryTest.kt
@@ -0,0 +1,92 @@
+/* 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.feature.search.telemetry
+
+import kotlinx.coroutines.runBlocking
+import mozilla.appservices.remotesettings.RemoteSettingsRecord
+import mozilla.appservices.remotesettings.RemoteSettingsResponse
+import mozilla.components.support.remotesettings.RemoteSettingsClient
+import mozilla.components.support.remotesettings.RemoteSettingsResult
+import mozilla.components.support.test.mock
+import org.json.JSONObject
+import org.junit.Assert.assertEquals
+import org.junit.Assert.assertTrue
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.Mock
+import org.mockito.Mockito.`when`
+import org.mockito.MockitoAnnotations
+import org.robolectric.RobolectricTestRunner
+
+@RunWith(RobolectricTestRunner::class)
+class SerpTelemetryRepositoryTest {
+ @Mock
+ private lateinit var mockRemoteSettingsClient: RemoteSettingsClient
+
+ private lateinit var serpTelemetryRepository: SerpTelemetryRepository
+
+ @Before
+ fun setup() {
+ MockitoAnnotations.openMocks(this)
+ serpTelemetryRepository = SerpTelemetryRepository(
+ rootStorageDirectory = mock(),
+ readJson = mock(),
+ collectionName = "",
+ serverUrl = "https://test.server",
+ bucketName = "",
+ )
+
+ serpTelemetryRepository.remoteSettingsClient = mockRemoteSettingsClient
+ }
+
+ @Test
+ fun `GIVEN non-empty response WHEN writeToCache is called THEN the result is a success`() = runBlocking {
+ val records = listOf(
+ RemoteSettingsRecord("1", 123u, false, null, JSONObject()),
+ RemoteSettingsRecord("2", 456u, true, null, JSONObject()),
+ )
+ val response = RemoteSettingsResponse(records, 125614567U)
+
+ `when`(mockRemoteSettingsClient.write(response))
+ .thenReturn(RemoteSettingsResult.Success(response))
+
+ val result = serpTelemetryRepository.writeToCache(response)
+
+ assertTrue(result is RemoteSettingsResult.Success)
+ assertEquals(response, (result as RemoteSettingsResult.Success).response)
+ }
+
+ @Test
+ fun `GIVEN non-empty response WHEN fetchRemoteResponse is called THEN the result is equal to the response`() = runBlocking {
+ val records = listOf(
+ RemoteSettingsRecord("1", 123u, false, null, JSONObject()),
+ RemoteSettingsRecord("2", 456u, true, null, JSONObject()),
+ )
+ val response = RemoteSettingsResponse(records, 125614567U)
+ `when`(mockRemoteSettingsClient.fetch())
+ .thenReturn(RemoteSettingsResult.Success(response))
+
+ val result = serpTelemetryRepository.fetchRemoteResponse()
+
+ assertEquals(response, result)
+ }
+
+ @Test
+ fun `GIVEN non-empty response WHEN loadProvidersFromCache is called THEN the result is equal to the response`() = runBlocking {
+ val records = listOf(
+ RemoteSettingsRecord("1", 123u, false, null, JSONObject()),
+ RemoteSettingsRecord("2", 456u, true, null, JSONObject()),
+ )
+ val response = RemoteSettingsResponse(records, 125614567U)
+ `when`(mockRemoteSettingsClient.read())
+ .thenReturn(RemoteSettingsResult.Success(response))
+
+ val result = serpTelemetryRepository.loadProvidersFromCache()
+
+ assertEquals(response.lastModified, result.first)
+ assertEquals(response.records.mapNotNull { it.fields.toSearchProviderModel() }, result.second)
+ }
+}
diff --git a/mobile/android/android-components/components/feature/search/src/test/java/mozilla/components/feature/search/telemetry/ads/AdsTelemetryTest.kt b/mobile/android/android-components/components/feature/search/src/test/java/mozilla/components/feature/search/telemetry/ads/AdsTelemetryTest.kt
new file mode 100644
index 0000000000..d804ad98fa
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/test/java/mozilla/components/feature/search/telemetry/ads/AdsTelemetryTest.kt
@@ -0,0 +1,271 @@
+/* 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.feature.search.telemetry.ads
+
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import kotlinx.coroutines.runBlocking
+import mozilla.components.browser.state.store.BrowserStore
+import mozilla.components.concept.engine.Engine
+import mozilla.components.feature.search.telemetry.ExtensionInfo
+import mozilla.components.feature.search.telemetry.SearchProviderCookie
+import mozilla.components.feature.search.telemetry.SearchProviderModel
+import mozilla.components.feature.search.telemetry.ads.AdsTelemetry.Companion.ADS_EXTENSION_ID
+import mozilla.components.feature.search.telemetry.ads.AdsTelemetry.Companion.ADS_EXTENSION_RESOURCE_URL
+import mozilla.components.feature.search.telemetry.ads.AdsTelemetry.Companion.ADS_MESSAGE_COOKIES_KEY
+import mozilla.components.feature.search.telemetry.ads.AdsTelemetry.Companion.ADS_MESSAGE_DOCUMENT_URLS_KEY
+import mozilla.components.feature.search.telemetry.ads.AdsTelemetry.Companion.ADS_MESSAGE_ID
+import mozilla.components.feature.search.telemetry.ads.AdsTelemetry.Companion.ADS_MESSAGE_SESSION_URL_KEY
+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.FactProcessor
+import mozilla.components.support.base.facts.Facts
+import mozilla.components.support.test.any
+import mozilla.components.support.test.argumentCaptor
+import mozilla.components.support.test.eq
+import mozilla.components.support.test.mock
+import org.json.JSONArray
+import org.json.JSONObject
+import org.junit.Assert.assertEquals
+import org.junit.Assert.assertTrue
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.Mockito.doNothing
+import org.mockito.Mockito.spy
+import org.mockito.Mockito.verify
+
+@RunWith(AndroidJUnit4::class)
+class AdsTelemetryTest {
+ private lateinit var telemetry: AdsTelemetry
+
+ fun createMockProviderList(): List<SearchProviderModel> = listOf(
+ SearchProviderModel(
+ schema = 1671479978127,
+ taggedCodes = listOf("monline_7_dg", "monline_4_dg", "monline_3_dg", "monline_dg"),
+ telemetryId = "baidu",
+ organicCodes = emptyList(),
+ codeParamName = "tn",
+ followOnParamNames = listOf("oq"),
+ queryParamNames = listOf("wd", "word"),
+ searchPageRegexp = "^https://(?:m|www)\\.baidu\\.com/(?:s|baidu)",
+ extraAdServersRegexps = listOf("^https?://www\\.baidu\\.com/baidu\\.php?"),
+ expectedOrganicCodes = emptyList(),
+ ),
+ SearchProviderModel(
+ schema = 1671479978127,
+ taggedCodes = listOf("firefox-b-m", "fpas", "lm"),
+ telemetryId = "duckduckgo",
+ organicCodes = emptyList(),
+ codeParamName = "t",
+ queryParamNames = listOf("q"),
+ searchPageRegexp = "^https:\\/\\/duckduckgo\\.com\\/",
+ extraAdServersRegexps = listOf("^https://duckduckgo.com/y\\.js?.*ad_provider\\="),
+ expectedOrganicCodes = emptyList(),
+ ),
+ SearchProviderModel(
+ schema = 1671479978127,
+ taggedCodes = listOf("firefox-b-m", "fpas", "def"),
+ telemetryId = "google",
+ organicCodes = emptyList(),
+ codeParamName = "client",
+ followOnParamNames = listOf("oq", "ved", "ei"),
+ queryParamNames = listOf("q"),
+ searchPageRegexp = "^https://www\\.google\\.(?:.+)/search",
+ extraAdServersRegexps = listOf("^https?://www\\.google(?:adservices)?\\.com/(?:pagead/)?aclk"),
+ expectedOrganicCodes = emptyList(),
+ ),
+ SearchProviderModel(
+ schema = 1671479978127,
+ taggedCodes = listOf("MOZMBA", "MOZL", "def"),
+ telemetryId = "bing",
+ organicCodes = emptyList(),
+ codeParamName = "pc",
+ queryParamNames = listOf("q"),
+ searchPageRegexp = "^https://www\\.bing\\.com/search",
+ extraAdServersRegexps = listOf("^https://www\\.bing\\.com/acli?c?k"),
+ followOnCookies = listOf(
+ SearchProviderCookie(
+ extraCodeParamName = "form",
+ extraCodePrefixes = listOf("QBRE"),
+ host = "www.bing.com",
+ name = "SRCHS",
+ codeParamName = "PC",
+ ),
+ ),
+ expectedOrganicCodes = emptyList(),
+ ),
+ )
+
+ @Before
+ fun setUp() {
+ telemetry = spy(AdsTelemetry())
+ }
+
+ @Test
+ fun `WHEN installWebExtension is called THEN install a properly configured extension`() {
+ val engine: Engine = mock()
+ val store: BrowserStore = mock()
+ val extensionCaptor = argumentCaptor<ExtensionInfo>()
+
+ runBlocking {
+ doNothing().`when`(telemetry).setProviderList(any())
+ telemetry.install(engine, store, mock())
+ }
+
+ verify(telemetry).installWebExtension(eq(engine), eq(store), extensionCaptor.capture())
+ assertEquals(ADS_EXTENSION_ID, extensionCaptor.value.id)
+ assertEquals(ADS_EXTENSION_RESOURCE_URL, extensionCaptor.value.resourceUrl)
+ assertEquals(ADS_MESSAGE_ID, extensionCaptor.value.messageId)
+ }
+
+ @Test
+ fun `WHEN checkIfAddWasClicked is called with a null session URL THEN don't emit a Fact`() {
+ val facts = mutableListOf<Fact>()
+ Facts.registerProcessor(
+ object : FactProcessor {
+ override fun process(fact: Fact) {
+ facts.add(fact)
+ }
+ },
+ )
+
+ telemetry.checkIfAddWasClicked(null, listOf())
+
+ assertTrue(facts.isEmpty())
+ }
+
+ @Test
+ fun `GIVEN no ads in the redirect path WHEN checkIfAddWasClicked is called THEN don't emit a Fact`() {
+ val sessionUrl = "https://www.google.com/search?q=aaa"
+ val facts = mutableListOf<Fact>()
+ Facts.registerProcessor(
+ object : FactProcessor {
+ override fun process(fact: Fact) {
+ facts.add(fact)
+ }
+ },
+ )
+
+ telemetry.checkIfAddWasClicked(sessionUrl, listOf("https://www.aaa.com"))
+
+ assertTrue(facts.isEmpty())
+ }
+
+ @Test
+ fun `GIVEN ads are in the redirect path WHEN checkIfAddWasClicked is called THEN emit an appropriate SERP_ADD_CLICKED Fact`() {
+ val sessionUrl = "https://www.google.com/search?q=aaa"
+ telemetry.providerList = createMockProviderList()
+ val facts = mutableListOf<Fact>()
+ Facts.registerProcessor(
+ object : FactProcessor {
+ override fun process(fact: Fact) {
+ facts.add(fact)
+ }
+ },
+ )
+
+ telemetry.checkIfAddWasClicked(
+ sessionUrl,
+ listOf("https://www.google.com/aclk", "https://www.aaa.com"),
+ )
+
+ assertEquals(1, facts.size)
+ assertEquals(Component.FEATURE_SEARCH, facts[0].component)
+ assertEquals(Action.INTERACTION, facts[0].action)
+ assertEquals(AdsTelemetry.SERP_ADD_CLICKED, facts[0].item)
+ assertEquals("google.in-content.organic.none", facts[0].value)
+ }
+
+ @Test
+ fun `GIVEN a message containing ad links from the extension WHEN processMessage is called THEN track a SERP_SHOWN_WITH_ADDS Fact`() {
+ val first = "https://www.google.com/aclk"
+ val second = "https://www.google.com/aaa"
+ val urls = JSONArray()
+ urls.put(first)
+ urls.put(second)
+ val cookies = JSONArray()
+ val message = JSONObject()
+ message.put(ADS_MESSAGE_DOCUMENT_URLS_KEY, urls)
+ message.put(ADS_MESSAGE_SESSION_URL_KEY, "https://www.google.com/search?q=aaa")
+ message.put(ADS_MESSAGE_COOKIES_KEY, cookies)
+ telemetry.providerList = createMockProviderList()
+ val facts = mutableListOf<Fact>()
+ Facts.registerProcessor(
+ object : FactProcessor {
+ override fun process(fact: Fact) {
+ facts.add(fact)
+ }
+ },
+ )
+
+ telemetry.processMessage(message)
+
+ assertEquals(1, facts.size)
+ assertEquals(Component.FEATURE_SEARCH, facts[0].component)
+ assertEquals(Action.INTERACTION, facts[0].action)
+ assertEquals(AdsTelemetry.SERP_SHOWN_WITH_ADDS, facts[0].item)
+ assertEquals("google.in-content.organic.none", facts[0].value)
+ }
+
+ @Test
+ fun `GIVEN a message not containing ad links from the extension WHEN processMessage is called THEN don't emit any Fact`() {
+ val first = "https://www.google.com/aaaaaa"
+ val second = "https://www.google.com/aaa"
+ val urls = JSONArray()
+ urls.put(first)
+ urls.put(second)
+ val cookies = JSONArray()
+ val message = JSONObject()
+ message.put(ADS_MESSAGE_DOCUMENT_URLS_KEY, urls)
+ message.put(ADS_MESSAGE_SESSION_URL_KEY, "https://www.google.com/search?q=aaa")
+ message.put(ADS_MESSAGE_COOKIES_KEY, cookies)
+ val facts = mutableListOf<Fact>()
+ Facts.registerProcessor(
+ object : FactProcessor {
+ override fun process(fact: Fact) {
+ facts.add(fact)
+ }
+ },
+ )
+
+ telemetry.processMessage(message)
+
+ assertTrue(facts.isEmpty())
+ }
+
+ @Test
+ fun `GIVEN a Bing sap-follow-on with cookies WHEN checkIfAddWasClicked is called THEN emit an appropriate SERP_ADD_CLICKED Fact`() {
+ val url = "https://www.bing.com/search?q=aaa&form=QBRERANDOM"
+ telemetry.providerList = createMockProviderList()
+ telemetry.cachedCookies = createCookieList()
+ val facts = mutableListOf<Fact>()
+ Facts.registerProcessor(
+ object : FactProcessor {
+ override fun process(fact: Fact) {
+ facts.add(fact)
+ }
+ },
+ )
+
+ telemetry.checkIfAddWasClicked(url, listOf("https://www.bing.com/aclik", "https://www.aaa.com"))
+
+ assertEquals(1, facts.size)
+ assertEquals(Component.FEATURE_SEARCH, facts[0].component)
+ assertEquals(Action.INTERACTION, facts[0].action)
+ assertEquals(AdsTelemetry.SERP_ADD_CLICKED, facts[0].item)
+ assertEquals("bing.in-content.sap-follow-on.mozl", facts[0].value)
+ }
+
+ private fun createCookieList(): List<JSONObject> {
+ val first = JSONObject()
+ first.put("name", "SRCHS")
+ first.put("value", "PC=MOZL")
+ val second = JSONObject()
+ second.put("name", "RANDOM")
+ second.put("value", "RANDOM")
+ return listOf(first, second)
+ }
+}
diff --git a/mobile/android/android-components/components/feature/search/src/test/java/mozilla/components/feature/search/telemetry/incontent/InContentTelemetryTest.kt b/mobile/android/android-components/components/feature/search/src/test/java/mozilla/components/feature/search/telemetry/incontent/InContentTelemetryTest.kt
new file mode 100644
index 0000000000..2de381f11d
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/test/java/mozilla/components/feature/search/telemetry/incontent/InContentTelemetryTest.kt
@@ -0,0 +1,467 @@
+/* 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.feature.search.telemetry.incontent
+
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import kotlinx.coroutines.runBlocking
+import mozilla.components.browser.state.store.BrowserStore
+import mozilla.components.concept.engine.Engine
+import mozilla.components.feature.search.telemetry.ExtensionInfo
+import mozilla.components.feature.search.telemetry.SearchProviderCookie
+import mozilla.components.feature.search.telemetry.SearchProviderModel
+import mozilla.components.feature.search.telemetry.incontent.InContentTelemetry.Companion.SEARCH_EXTENSION_ID
+import mozilla.components.feature.search.telemetry.incontent.InContentTelemetry.Companion.SEARCH_EXTENSION_RESOURCE_URL
+import mozilla.components.feature.search.telemetry.incontent.InContentTelemetry.Companion.SEARCH_MESSAGE_ID
+import mozilla.components.feature.search.telemetry.incontent.InContentTelemetry.Companion.SEARCH_MESSAGE_LIST_KEY
+import mozilla.components.feature.search.telemetry.incontent.InContentTelemetry.Companion.SEARCH_MESSAGE_SESSION_URL_KEY
+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.FactProcessor
+import mozilla.components.support.base.facts.Facts
+import mozilla.components.support.test.any
+import mozilla.components.support.test.argumentCaptor
+import mozilla.components.support.test.eq
+import mozilla.components.support.test.mock
+import org.json.JSONArray
+import org.json.JSONObject
+import org.junit.Assert.assertEquals
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.Mockito.doNothing
+import org.mockito.Mockito.spy
+import org.mockito.Mockito.verify
+
+@RunWith(AndroidJUnit4::class)
+class InContentTelemetryTest {
+ private lateinit var telemetry: InContentTelemetry
+
+ fun createMockProviderList(): List<SearchProviderModel> = listOf(
+ SearchProviderModel(
+ schema = 1671479978127,
+ taggedCodes = listOf("monline_7_dg", "monline_4_dg", "monline_3_dg", "monline_dg"),
+ telemetryId = "baidu",
+ organicCodes = emptyList(),
+ codeParamName = "tn",
+ followOnParamNames = listOf("oq"),
+ queryParamNames = listOf("wd", "word"),
+ searchPageRegexp = "^https://(?:m|www)\\.baidu\\.com/(?:s|baidu)",
+ extraAdServersRegexps = listOf("^https?://www\\.baidu\\.com/baidu\\.php?"),
+ expectedOrganicCodes = emptyList(),
+ ),
+ SearchProviderModel(
+ schema = 1671479978127,
+ taggedCodes = listOf("firefox-b-m", "fpas", "lm"),
+ telemetryId = "example",
+ organicCodes = listOf("foo"),
+ codeParamName = "pc",
+ queryParamNames = listOf("q"),
+ searchPageRegexp = "^https:\\/\\/example\\.com\\/",
+ extraAdServersRegexps = listOf("^https://example.com/y\\\\.js?.*ad_provider\\\\="),
+ expectedOrganicCodes = emptyList(),
+ ),
+ SearchProviderModel(
+ schema = 1671479978127,
+ taggedCodes = listOf("firefox-b-m", "fpas", "lm"),
+ telemetryId = "duckduckgo",
+ organicCodes = emptyList(),
+ codeParamName = "t",
+ queryParamNames = listOf("q"),
+ searchPageRegexp = "^https:\\/\\/duckduckgo\\.com\\/",
+ extraAdServersRegexps = listOf("^https://duckduckgo.com/y\\\\.js?.*ad_provider\\\\="),
+ expectedOrganicCodes = listOf("ha"),
+ ),
+ SearchProviderModel(
+ schema = 1671479978127,
+ taggedCodes = listOf("firefox-b-m", "fpas", "def"),
+ telemetryId = "google",
+ organicCodes = emptyList(),
+ codeParamName = "client",
+ followOnParamNames = listOf("oq", "ved", "ei"),
+ queryParamNames = listOf("q"),
+ searchPageRegexp = "^https://www\\.google\\.(?:.+)/search",
+ extraAdServersRegexps = listOf("^https?://www\\\\.google(?:adservices)?\\\\.com/(?:pagead/)?aclk"),
+ expectedOrganicCodes = emptyList(),
+ ),
+ SearchProviderModel(
+ schema = 1671479978127,
+ taggedCodes = listOf("MOZ2", "MOZL", "def"),
+ telemetryId = "bing",
+ organicCodes = emptyList(),
+ codeParamName = "pc",
+ queryParamNames = listOf("q"),
+ searchPageRegexp = "^https://www\\.bing\\.com/search",
+ extraAdServersRegexps = listOf("^https://www\\\\.bing\\\\.com/acli?c?k"),
+ followOnCookies = listOf(
+ SearchProviderCookie(
+ extraCodeParamName = "form",
+ extraCodePrefixes = listOf("QBRE"),
+ host = "name",
+ name = "SRCHS",
+ codeParamName = "PC",
+ ),
+ ),
+ expectedOrganicCodes = emptyList(),
+ ),
+ )
+
+ @Before
+ fun setup() {
+ telemetry = spy(InContentTelemetry())
+ }
+
+ @Test
+ fun `WHEN installWebExtension is called THEN install a properly configured extension`() {
+ val engine: Engine = mock()
+ val store: BrowserStore = mock()
+ val extensionCaptor = argumentCaptor<ExtensionInfo>()
+
+ runBlocking {
+ doNothing().`when`(telemetry).setProviderList(any())
+ telemetry.install(engine, store, mock())
+ }
+
+ verify(telemetry).installWebExtension(eq(engine), eq(store), extensionCaptor.capture())
+ assertEquals(SEARCH_EXTENSION_ID, extensionCaptor.value.id)
+ assertEquals(SEARCH_EXTENSION_RESOURCE_URL, extensionCaptor.value.resourceUrl)
+ assertEquals(SEARCH_MESSAGE_ID, extensionCaptor.value.messageId)
+ }
+
+ @Test
+ fun `GIVEN a message from the extension WHEN processMessage is called THEN track the search`() {
+ val first = JSONObject()
+ val second = JSONObject()
+ val array = JSONArray()
+ array.put(first)
+ array.put(second)
+ val message = JSONObject()
+ val url = "https://www.google.com/search?q=aaa"
+ message.put(SEARCH_MESSAGE_LIST_KEY, array)
+ message.put(SEARCH_MESSAGE_SESSION_URL_KEY, url)
+
+ telemetry.processMessage(message)
+
+ verify(telemetry).trackPartnerUrlTypeMetric(url, listOf(first, second))
+ }
+
+ @Test
+ fun `GIVEN a Example search WHEN trackPartnerUrlTypeMetric is called THEN emit an appropriate IN_CONTENT_SEARCH fact`() {
+ val url = "https://example.com/?q=aaa&pc=foo"
+ telemetry.providerList = createMockProviderList()
+ val facts = mutableListOf<Fact>()
+ Facts.registerProcessor(
+ object : FactProcessor {
+ override fun process(fact: Fact) {
+ facts.add(fact)
+ }
+ },
+ )
+
+ telemetry.trackPartnerUrlTypeMetric(url, listOf())
+
+ assertEquals(1, facts.size)
+ assertEquals(Component.FEATURE_SEARCH, facts[0].component)
+ assertEquals(Action.INTERACTION, facts[0].action)
+ assertEquals(InContentTelemetry.IN_CONTENT_SEARCH, facts[0].item)
+ assertEquals("example.in-content.organic.foo", facts[0].value)
+ }
+
+ @Test
+ fun `GIVEN a Google search WHEN trackPartnerUrlTypeMetric is called THEN emit an appropriate IN_CONTENT_SEARCH fact`() {
+ val url = "https://www.google.com/search?q=aaa&client=firefox-b-m"
+ telemetry.providerList = createMockProviderList()
+
+ val facts = mutableListOf<Fact>()
+ Facts.registerProcessor(
+ object : FactProcessor {
+ override fun process(fact: Fact) {
+ facts.add(fact)
+ }
+ },
+ )
+ telemetry.trackPartnerUrlTypeMetric(url, listOf())
+
+ assertEquals(1, facts.size)
+ assertEquals(Component.FEATURE_SEARCH, facts[0].component)
+ assertEquals(Action.INTERACTION, facts[0].action)
+ assertEquals(InContentTelemetry.IN_CONTENT_SEARCH, facts[0].item)
+ assertEquals("google.in-content.sap.firefox-b-m", facts[0].value)
+ }
+
+ @Test
+ fun `GIVEN a DuckDuckGo search WHEN trackPartnerUrlTypeMetric is called THEN emit an appropriate IN_CONTENT_SEARCH fact`() {
+ val url = "https://duckduckgo.com/?q=aaa&t=fpas"
+ telemetry.providerList = createMockProviderList()
+ val facts = mutableListOf<Fact>()
+ Facts.registerProcessor(
+ object : FactProcessor {
+ override fun process(fact: Fact) {
+ facts.add(fact)
+ }
+ },
+ )
+
+ telemetry.trackPartnerUrlTypeMetric(url, listOf())
+
+ assertEquals(1, facts.size)
+ assertEquals(Component.FEATURE_SEARCH, facts[0].component)
+ assertEquals(Action.INTERACTION, facts[0].action)
+ assertEquals(InContentTelemetry.IN_CONTENT_SEARCH, facts[0].item)
+ assertEquals("duckduckgo.in-content.sap.fpas", facts[0].value)
+ }
+
+ @Test
+ fun `GIVEN an invalid Bing search WHEN trackPartnerUrlTypeMetric is called THEN emit an appropriate IN_CONTENT_SEARCH fact`() {
+ val url = "https://www.bing.com/search?q=aaa&pc=MOZMBA"
+ telemetry.providerList = createMockProviderList()
+ val facts = mutableListOf<Fact>()
+ Facts.registerProcessor(
+ object : FactProcessor {
+ override fun process(fact: Fact) {
+ facts.add(fact)
+ }
+ },
+ )
+
+ telemetry.trackPartnerUrlTypeMetric(url, listOf())
+
+ assertEquals(1, facts.size)
+ assertEquals(Component.FEATURE_SEARCH, facts[0].component)
+ assertEquals(Action.INTERACTION, facts[0].action)
+ assertEquals(InContentTelemetry.IN_CONTENT_SEARCH, facts[0].item)
+ assertEquals("bing.in-content.organic.other", facts[0].value)
+ }
+
+ @Test
+ fun `GIVEN a Google sap-follow-on WHEN trackPartnerUrlTypeMetric is called THEN emit an appropriate IN_CONTENT_SEARCH fact`() {
+ val url = "https://www.google.com/search?q=aaa&client=firefox-b-m&oq=random"
+ telemetry.providerList = createMockProviderList()
+ val facts = mutableListOf<Fact>()
+ Facts.registerProcessor(
+ object : FactProcessor {
+ override fun process(fact: Fact) {
+ facts.add(fact)
+ }
+ },
+ )
+
+ telemetry.trackPartnerUrlTypeMetric(url, listOf())
+
+ assertEquals(1, facts.size)
+ assertEquals(Component.FEATURE_SEARCH, facts[0].component)
+ assertEquals(Action.INTERACTION, facts[0].action)
+ assertEquals(InContentTelemetry.IN_CONTENT_SEARCH, facts[0].item)
+ assertEquals("google.in-content.sap-follow-on.firefox-b-m", facts[0].value)
+ }
+
+ @Test
+ fun `GIVEN an invalid Google sap-follow-on WHEN trackPartnerUrlTypeMetric is called THEN emit an appropriate IN_CONTENT_SEARCH fact`() {
+ val url = "https://www.google.com/search?q=aaa&client=firefox-b-mTesting&oq=random"
+ telemetry.providerList = createMockProviderList()
+ val facts = mutableListOf<Fact>()
+ Facts.registerProcessor(
+ object : FactProcessor {
+ override fun process(fact: Fact) {
+ facts.add(fact)
+ }
+ },
+ )
+
+ telemetry.trackPartnerUrlTypeMetric(url, listOf())
+
+ assertEquals(1, facts.size)
+ assertEquals(Component.FEATURE_SEARCH, facts[0].component)
+ assertEquals(Action.INTERACTION, facts[0].action)
+ assertEquals(InContentTelemetry.IN_CONTENT_SEARCH, facts[0].item)
+ assertEquals("google.in-content.organic.other", facts[0].value)
+ }
+
+ @Test
+ fun `GIVEN a Google sap-follow-on from topSite WHEN trackPartnerUrlTypeMetric is called THEN emit an appropriate IN_CONTENT_SEARCH fact`() {
+ val url = "https://www.google.com/search?q=aaa&client=firefox-b-m&channel=ts&oq=random"
+ telemetry.providerList = createMockProviderList()
+ val facts = mutableListOf<Fact>()
+ Facts.registerProcessor(
+ object : FactProcessor {
+ override fun process(fact: Fact) {
+ facts.add(fact)
+ }
+ },
+ )
+
+ telemetry.trackPartnerUrlTypeMetric(url, listOf())
+
+ assertEquals(1, facts.size)
+ assertEquals(Component.FEATURE_SEARCH, facts[0].component)
+ assertEquals(Action.INTERACTION, facts[0].action)
+ assertEquals(InContentTelemetry.IN_CONTENT_SEARCH, facts[0].item)
+ assertEquals("google.in-content.sap-follow-on.firefox-b-m.ts", facts[0].value)
+ }
+
+ @Test
+ fun `GIVEN an invalid Google channel from topSite WHEN trackPartnerUrlTypeMetric is called THEN emit an appropriate IN_CONTENT_SEARCH fact`() {
+ val url = "https://www.google.com/search?q=aaa&client=firefox-b-m&channel=tsTest&oq=random"
+ telemetry.providerList = createMockProviderList()
+ val facts = mutableListOf<Fact>()
+ Facts.registerProcessor(
+ object : FactProcessor {
+ override fun process(fact: Fact) {
+ facts.add(fact)
+ }
+ },
+ )
+
+ telemetry.trackPartnerUrlTypeMetric(url, listOf())
+
+ assertEquals(1, facts.size)
+ assertEquals(Component.FEATURE_SEARCH, facts[0].component)
+ assertEquals(Action.INTERACTION, facts[0].action)
+ assertEquals(InContentTelemetry.IN_CONTENT_SEARCH, facts[0].item)
+ assertEquals("google.in-content.sap-follow-on.firefox-b-m", facts[0].value)
+ }
+
+ @Test
+ fun `GIVEN a Bing sap-follow-on with cookies WHEN trackPartnerUrlTypeMetric is called THEN emit an appropriate IN_CONTENT_SEARCH fact`() {
+ val url = "https://www.bing.com/search?q=aaa&form=QBRERANDOM"
+ telemetry.providerList = createMockProviderList()
+ val facts = mutableListOf<Fact>()
+ Facts.registerProcessor(
+ object : FactProcessor {
+ override fun process(fact: Fact) {
+ facts.add(fact)
+ }
+ },
+ )
+
+ telemetry.trackPartnerUrlTypeMetric(url, createCookieList())
+
+ assertEquals(1, facts.size)
+ assertEquals(Component.FEATURE_SEARCH, facts[0].component)
+ assertEquals(Action.INTERACTION, facts[0].action)
+ assertEquals(InContentTelemetry.IN_CONTENT_SEARCH, facts[0].item)
+ assertEquals("bing.in-content.sap-follow-on.mozl", facts[0].value)
+ }
+
+ @Test
+ fun `GIVEN a Google organic search WHEN trackPartnerUrlTypeMetric is called THEN emit an appropriate IN_CONTENT_SEARCH fact`() {
+ val url = "https://www.google.com/search?q=aaa"
+ telemetry.providerList = createMockProviderList()
+ val facts = mutableListOf<Fact>()
+ Facts.registerProcessor(
+ object : FactProcessor {
+ override fun process(fact: Fact) {
+ facts.add(fact)
+ }
+ },
+ )
+
+ telemetry.trackPartnerUrlTypeMetric(url, listOf())
+
+ assertEquals(1, facts.size)
+ assertEquals(Component.FEATURE_SEARCH, facts[0].component)
+ assertEquals(Action.INTERACTION, facts[0].action)
+ assertEquals(InContentTelemetry.IN_CONTENT_SEARCH, facts[0].item)
+ assertEquals("google.in-content.organic.none", facts[0].value)
+ }
+
+ @Test
+ fun `GIVEN a DuckDuckGo organic search WHEN trackPartnerUrlTypeMetric is called THEN emit an appropriate IN_CONTENT_SEARCH fact`() {
+ val url = "https://duckduckgo.com/?q=aaa"
+ telemetry.providerList = createMockProviderList()
+ val facts = mutableListOf<Fact>()
+ Facts.registerProcessor(
+ object : FactProcessor {
+ override fun process(fact: Fact) {
+ facts.add(fact)
+ }
+ },
+ )
+
+ telemetry.trackPartnerUrlTypeMetric(url, listOf())
+
+ assertEquals(1, facts.size)
+ assertEquals(Component.FEATURE_SEARCH, facts[0].component)
+ assertEquals(Action.INTERACTION, facts[0].action)
+ assertEquals(InContentTelemetry.IN_CONTENT_SEARCH, facts[0].item)
+ assertEquals("duckduckgo.in-content.organic.none", facts[0].value)
+ }
+
+ @Test
+ fun `GIVEN a DuckDuckGo organic search with expected organic code WHEN trackPartnerUrlTypeMetric is called THEN emit an appropriate IN_CONTENT_SEARCH fact`() {
+ val url = "https://duckduckgo.com/?t=ha&q=aaa"
+ val facts = mutableListOf<Fact>()
+ telemetry.providerList = createMockProviderList()
+ Facts.registerProcessor(
+ object : FactProcessor {
+ override fun process(fact: Fact) {
+ facts.add(fact)
+ }
+ },
+ )
+
+ telemetry.trackPartnerUrlTypeMetric(url, listOf())
+
+ assertEquals(1, facts.size)
+ assertEquals(Component.FEATURE_SEARCH, facts[0].component)
+ assertEquals(Action.INTERACTION, facts[0].action)
+ assertEquals(InContentTelemetry.IN_CONTENT_SEARCH, facts[0].item)
+ assertEquals("duckduckgo.in-content.organic.none", facts[0].value)
+ }
+
+ @Test
+ fun `GIVEN a Bing organic search WHEN trackPartnerUrlTypeMetric is called THEN emit an appropriate IN_CONTENT_SEARCH fact`() {
+ val url = "https://www.bing.com/search?q=aaa"
+ telemetry.providerList = createMockProviderList()
+ val facts = mutableListOf<Fact>()
+ Facts.registerProcessor(
+ object : FactProcessor {
+ override fun process(fact: Fact) {
+ facts.add(fact)
+ }
+ },
+ )
+
+ telemetry.trackPartnerUrlTypeMetric(url, listOf())
+
+ assertEquals(1, facts.size)
+ assertEquals(Component.FEATURE_SEARCH, facts[0].component)
+ assertEquals(Action.INTERACTION, facts[0].action)
+ assertEquals(InContentTelemetry.IN_CONTENT_SEARCH, facts[0].item)
+ assertEquals("bing.in-content.organic.none", facts[0].value)
+ }
+
+ @Test
+ fun `GIVEN a Baidu organic search WHEN trackPartnerUrlTypeMetric is called THEN emit an appropriate IN_CONTENT_SEARCH fact`() {
+ val url = "https://m.baidu.com/s?word=aaa"
+ telemetry.providerList = createMockProviderList()
+ val facts = mutableListOf<Fact>()
+ Facts.registerProcessor(
+ object : FactProcessor {
+ override fun process(fact: Fact) {
+ facts.add(fact)
+ }
+ },
+ )
+
+ telemetry.trackPartnerUrlTypeMetric(url, listOf())
+
+ assertEquals(1, facts.size)
+ assertEquals(Component.FEATURE_SEARCH, facts[0].component)
+ assertEquals(Action.INTERACTION, facts[0].action)
+ assertEquals(InContentTelemetry.IN_CONTENT_SEARCH, facts[0].item)
+ assertEquals("baidu.in-content.organic.none", facts[0].value)
+ }
+
+ private fun createCookieList(): List<JSONObject> {
+ val first = JSONObject()
+ first.put("name", "SRCHS")
+ first.put("value", "PC=MOZL")
+ val second = JSONObject()
+ second.put("name", "RANDOM")
+ second.put("value", "RANDOM")
+ return listOf(first, second)
+ }
+}
diff --git a/mobile/android/android-components/components/feature/search/src/test/java/mozilla/components/feature/search/widget/AppSearchWidgetProviderTest.kt b/mobile/android/android-components/components/feature/search/src/test/java/mozilla/components/feature/search/widget/AppSearchWidgetProviderTest.kt
new file mode 100644
index 0000000000..b0b74bec65
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/test/java/mozilla/components/feature/search/widget/AppSearchWidgetProviderTest.kt
@@ -0,0 +1,159 @@
+/* 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.feature.search.widget
+
+import android.content.Context
+import mozilla.components.feature.search.R
+import mozilla.components.feature.search.widget.AppSearchWidgetProvider.Companion.getLayout
+import mozilla.components.support.test.mock
+import org.junit.Assert.assertEquals
+import org.junit.Assert.assertNull
+import org.junit.Test
+import org.mockito.Mockito.doReturn
+
+class AppSearchWidgetProviderTest {
+
+ private val testContext: Context = mock()
+
+ @Test
+ fun testGetLayoutSize() {
+ val sizes = mapOf(
+ 0 to SearchWidgetProviderSize.EXTRA_SMALL_V1,
+ 10 to SearchWidgetProviderSize.EXTRA_SMALL_V1,
+ 63 to SearchWidgetProviderSize.EXTRA_SMALL_V1,
+ 64 to SearchWidgetProviderSize.EXTRA_SMALL_V2,
+ 99 to SearchWidgetProviderSize.EXTRA_SMALL_V2,
+ 100 to SearchWidgetProviderSize.SMALL,
+ 191 to SearchWidgetProviderSize.SMALL,
+ 192 to SearchWidgetProviderSize.MEDIUM,
+ 255 to SearchWidgetProviderSize.MEDIUM,
+ 256 to SearchWidgetProviderSize.LARGE,
+ 1000 to SearchWidgetProviderSize.LARGE,
+ )
+
+ for ((dp, layoutSize) in sizes) {
+ assertEquals(layoutSize, AppSearchWidgetProvider.getLayoutSize(dp))
+ }
+ }
+
+ @Test
+ fun testGetLargeLayout() {
+ assertEquals(
+ R.layout.mozac_search_widget_large,
+ getLayout(SearchWidgetProviderSize.LARGE, showMic = false),
+ )
+ assertEquals(
+ R.layout.mozac_search_widget_large,
+ getLayout(SearchWidgetProviderSize.LARGE, showMic = true),
+ )
+ }
+
+ @Test
+ fun testGetMediumLayout() {
+ assertEquals(
+ R.layout.mozac_search_widget_medium,
+ getLayout(SearchWidgetProviderSize.MEDIUM, showMic = false),
+ )
+ assertEquals(
+ R.layout.mozac_search_widget_medium,
+ getLayout(SearchWidgetProviderSize.MEDIUM, showMic = true),
+ )
+ }
+
+ @Test
+ fun testGetSmallLayout() {
+ assertEquals(
+ R.layout.mozac_search_widget_small_no_mic,
+ getLayout(SearchWidgetProviderSize.SMALL, showMic = false),
+ )
+ assertEquals(
+ R.layout.mozac_search_widget_small,
+ getLayout(SearchWidgetProviderSize.SMALL, showMic = true),
+ )
+ }
+
+ @Test
+ fun testGetExtraSmall2Layout() {
+ assertEquals(
+ R.layout.mozac_search_widget_extra_small_v2,
+ getLayout(
+ SearchWidgetProviderSize.EXTRA_SMALL_V2,
+ showMic = false,
+ ),
+ )
+ assertEquals(
+ R.layout.mozac_search_widget_extra_small_v2,
+ getLayout(
+ SearchWidgetProviderSize.EXTRA_SMALL_V2,
+ showMic = true,
+ ),
+ )
+ }
+
+ @Test
+ fun testGetExtraSmall1Layout() {
+ assertEquals(
+ R.layout.mozac_search_widget_extra_small_v1,
+ getLayout(
+ SearchWidgetProviderSize.EXTRA_SMALL_V1,
+ showMic = false,
+ ),
+ )
+ assertEquals(
+ R.layout.mozac_search_widget_extra_small_v1,
+ getLayout(
+ SearchWidgetProviderSize.EXTRA_SMALL_V1,
+ showMic = true,
+ ),
+ )
+ }
+
+ @Test
+ fun testGetText() {
+ assertEquals(
+ testContext.getString(R.string.search_widget_text_long),
+ AppSearchWidgetProvider.getText(
+ SearchWidgetProviderSize.LARGE,
+ testContext,
+ ),
+ )
+ assertEquals(
+ testContext.getString(R.string.search_widget_text_short),
+ AppSearchWidgetProvider.getText(
+ SearchWidgetProviderSize.MEDIUM,
+ testContext,
+ ),
+ )
+ assertNull(
+ AppSearchWidgetProvider.getText(
+ SearchWidgetProviderSize.SMALL,
+ testContext,
+ ),
+ )
+ assertNull(
+ AppSearchWidgetProvider.getText(
+ SearchWidgetProviderSize.EXTRA_SMALL_V1,
+ testContext,
+ ),
+ )
+ assertNull(
+ AppSearchWidgetProvider.getText(
+ SearchWidgetProviderSize.EXTRA_SMALL_V2,
+ testContext,
+ ),
+ )
+ }
+
+ @Test
+ fun `GIVEN voice search is disabled WHEN createVoiceSearchIntent is called THEN it returns null`() {
+ val appSearchWidgetProvider: AppSearchWidgetProvider =
+ mock()
+ doReturn(false).`when`(appSearchWidgetProvider).shouldShowVoiceSearch(testContext)
+
+ val result = appSearchWidgetProvider.createVoiceSearchIntent(testContext)
+
+ assertNull(result)
+ }
+}
diff --git a/mobile/android/android-components/components/feature/search/src/test/java/mozilla/components/feature/search/widget/BaseVoiceSearchActivityExtendedForTests.kt b/mobile/android/android-components/components/feature/search/src/test/java/mozilla/components/feature/search/widget/BaseVoiceSearchActivityExtendedForTests.kt
new file mode 100644
index 0000000000..5777364226
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/test/java/mozilla/components/feature/search/widget/BaseVoiceSearchActivityExtendedForTests.kt
@@ -0,0 +1,24 @@
+/* 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.feature.search.widget
+
+import androidx.core.view.MenuProvider
+import java.util.Locale
+
+class BaseVoiceSearchActivityExtendedForTests : BaseVoiceSearchActivity() {
+
+ override fun getCurrentLocale(): Locale {
+ return Locale.getDefault()
+ }
+
+ override fun onSpeechRecognitionStarted() {
+ }
+
+ override fun onSpeechRecognitionEnded(spokenText: String) {
+ }
+
+ override fun addMenuProvider(provider: MenuProvider) {
+ }
+}
diff --git a/mobile/android/android-components/components/feature/search/src/test/java/mozilla/components/feature/search/widget/BaseVoiceSearchActivityTest.kt b/mobile/android/android-components/components/feature/search/src/test/java/mozilla/components/feature/search/widget/BaseVoiceSearchActivityTest.kt
new file mode 100644
index 0000000000..bf865e3313
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/test/java/mozilla/components/feature/search/widget/BaseVoiceSearchActivityTest.kt
@@ -0,0 +1,134 @@
+/* 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.feature.search.widget
+
+import android.app.Activity
+import android.app.Activity.RESULT_OK
+import android.content.ComponentName
+import android.content.Intent
+import android.content.IntentFilter
+import android.os.Bundle
+import android.speech.RecognizerIntent.ACTION_RECOGNIZE_SPEECH
+import android.speech.RecognizerIntent.EXTRA_RESULTS
+import androidx.activity.result.ActivityResult
+import mozilla.components.feature.search.widget.BaseVoiceSearchActivity.Companion.PREVIOUS_INTENT
+import mozilla.components.feature.search.widget.BaseVoiceSearchActivity.Companion.SPEECH_PROCESSING
+import mozilla.components.support.test.robolectric.testContext
+import mozilla.components.support.utils.ext.getParcelableCompat
+import org.junit.Assert.assertEquals
+import org.junit.Assert.assertFalse
+import org.junit.Assert.assertNull
+import org.junit.Assert.assertTrue
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.robolectric.Robolectric
+import org.robolectric.RobolectricTestRunner
+import org.robolectric.Shadows.shadowOf
+import org.robolectric.android.controller.ActivityController
+import org.robolectric.shadows.ShadowActivity
+
+@RunWith(RobolectricTestRunner::class)
+class BaseVoiceSearchActivityTest {
+
+ private lateinit var controller: ActivityController<BaseVoiceSearchActivityExtendedForTests>
+ private lateinit var activity: BaseVoiceSearchActivityExtendedForTests
+ private lateinit var shadow: ShadowActivity
+
+ @Before
+ fun setup() {
+ val intent = Intent()
+ intent.putExtra(SPEECH_PROCESSING, true)
+
+ controller = Robolectric.buildActivity(BaseVoiceSearchActivityExtendedForTests::class.java, intent)
+ activity = controller.get()
+ shadow = shadowOf(activity)
+ }
+
+ private fun allowVoiceIntentToResolveActivity() {
+ val shadowPackageManager = shadowOf(testContext.packageManager)
+ val component = ComponentName("com.test", "Test")
+ shadowPackageManager.addActivityIfNotPresent(component)
+ shadowPackageManager.addIntentFilterForActivity(
+ component,
+ IntentFilter(ACTION_RECOGNIZE_SPEECH).apply { addCategory(Intent.CATEGORY_DEFAULT) },
+ )
+ }
+
+ @Test
+ fun `process intent with speech processing set to true`() {
+ val intent = Intent()
+ intent.putStringArrayListExtra(EXTRA_RESULTS, ArrayList<String>(listOf("hello world")))
+ val activityResult = ActivityResult(RESULT_OK, intent)
+ controller.get().activityResultImplementation(activityResult)
+
+ assertTrue(activity.isFinishing)
+ }
+
+ @Test
+ fun `process intent with speech processing set to false`() {
+ allowVoiceIntentToResolveActivity()
+ val intent = Intent()
+ intent.putExtra(SPEECH_PROCESSING, false)
+
+ val controller = Robolectric.buildActivity(BaseVoiceSearchActivityExtendedForTests::class.java, intent)
+ val activity = controller.get()
+
+ controller.create()
+
+ assertTrue(activity.isFinishing)
+ }
+
+ @Test
+ fun `process null intent`() {
+ allowVoiceIntentToResolveActivity()
+ val controller = Robolectric.buildActivity(BaseVoiceSearchActivityExtendedForTests::class.java, null)
+ val activity = controller.get()
+
+ controller.create()
+
+ assertTrue(activity.isFinishing)
+ }
+
+ @Test
+ fun `save previous intent to instance state`() {
+ allowVoiceIntentToResolveActivity()
+ val previousIntent = Intent().apply {
+ putExtra(SPEECH_PROCESSING, true)
+ }
+ val savedInstanceState = Bundle().apply {
+ putParcelable(PREVIOUS_INTENT, previousIntent)
+ }
+ val outState = Bundle()
+
+ controller.create(savedInstanceState)
+ controller.saveInstanceState(outState)
+
+ assertEquals(previousIntent, outState.getParcelableCompat(PREVIOUS_INTENT, Intent::class.java))
+ }
+
+ @Test
+ fun `process intent with speech processing in previous intent set to true`() {
+ allowVoiceIntentToResolveActivity()
+ val savedInstanceState = Bundle()
+ val previousIntent = Intent().apply {
+ putExtra(SPEECH_PROCESSING, true)
+ }
+ savedInstanceState.putParcelable(PREVIOUS_INTENT, previousIntent)
+
+ controller.create(savedInstanceState)
+
+ assertFalse(activity.isFinishing)
+ assertNull(shadow.peekNextStartedActivityForResult())
+ }
+
+ @Test
+ fun `handle invalid result code`() {
+ val activityResult = ActivityResult(Activity.RESULT_CANCELED, Intent())
+ controller.get().activityResultImplementation(activityResult)
+
+ assertTrue(activity.isFinishing)
+ }
+}
diff --git a/mobile/android/android-components/components/feature/search/src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker b/mobile/android/android-components/components/feature/search/src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker
new file mode 100644
index 0000000000..cf1c399ea8
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/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/feature/search/src/test/resources/robolectric.properties b/mobile/android/android-components/components/feature/search/src/test/resources/robolectric.properties
new file mode 100644
index 0000000000..932b01b9eb
--- /dev/null
+++ b/mobile/android/android-components/components/feature/search/src/test/resources/robolectric.properties
@@ -0,0 +1 @@
+sdk=28