summaryrefslogtreecommitdiffstats
path: root/mobile/android/android-components
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-06-12 05:35:29 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-06-12 05:35:29 +0000
commit59203c63bb777a3bacec32fb8830fba33540e809 (patch)
tree58298e711c0ff0575818c30485b44a2f21bf28a0 /mobile/android/android-components
parentAdding upstream version 126.0.1. (diff)
downloadfirefox-59203c63bb777a3bacec32fb8830fba33540e809.tar.xz
firefox-59203c63bb777a3bacec32fb8830fba33540e809.zip
Adding upstream version 127.0.upstream/127.0
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'mobile/android/android-components')
-rw-r--r--mobile/android/android-components/.buildconfig.yml38
-rw-r--r--mobile/android/android-components/README.md2
-rw-r--r--mobile/android/android-components/build.gradle22
-rw-r--r--mobile/android/android-components/components/browser/engine-gecko/build.gradle3
-rw-r--r--mobile/android/android-components/components/browser/engine-gecko/src/main/java/mozilla/components/browser/engine/gecko/GeckoEngine.kt4
-rw-r--r--mobile/android/android-components/components/browser/engine-gecko/src/main/java/mozilla/components/browser/engine/gecko/GeckoEngineSession.kt19
-rw-r--r--mobile/android/android-components/components/browser/engine-gecko/src/main/java/mozilla/components/browser/engine/gecko/GeckoEngineView.kt36
-rw-r--r--mobile/android/android-components/components/browser/engine-gecko/src/main/java/mozilla/components/browser/engine/gecko/prompt/GeckoPromptDelegate.kt9
-rw-r--r--mobile/android/android-components/components/browser/engine-gecko/src/main/java/mozilla/components/browser/engine/gecko/translate/GeckoTranslateSessionDelegate.kt9
-rw-r--r--mobile/android/android-components/components/browser/engine-gecko/src/test/java/mozilla/components/browser/engine/gecko/GeckoEngineSessionTest.kt8
-rw-r--r--mobile/android/android-components/components/browser/engine-gecko/src/test/java/mozilla/components/browser/engine/gecko/GeckoEngineTest.kt22
-rw-r--r--mobile/android/android-components/components/browser/engine-gecko/src/test/java/mozilla/components/browser/engine/gecko/GeckoEngineViewTest.kt9
-rw-r--r--mobile/android/android-components/components/browser/engine-gecko/src/test/java/mozilla/components/browser/engine/gecko/translate/GeckoTranslateSessionDelegateTest.kt22
-rw-r--r--mobile/android/android-components/components/browser/engine-system/src/main/res/raw/domain_blocklist.json19382
-rw-r--r--mobile/android/android-components/components/browser/engine-system/src/main/res/raw/domain_safelist.json18901
-rw-r--r--mobile/android/android-components/components/browser/errorpages/src/main/assets/errorPageScripts.js158
-rw-r--r--mobile/android/android-components/components/browser/errorpages/src/main/assets/error_page_js.html106
-rw-r--r--mobile/android/android-components/components/browser/errorpages/src/main/res/values-azb/strings.xml15
-rw-r--r--mobile/android/android-components/components/browser/errorpages/src/main/res/values-su/strings.xml8
-rw-r--r--mobile/android/android-components/components/browser/errorpages/src/main/res/values-sv-rSE/strings.xml2
-rw-r--r--mobile/android/android-components/components/browser/icons/src/main/assets/extensions/browser-icons/icons.js103
-rw-r--r--mobile/android/android-components/components/browser/icons/src/main/java/mozilla/components/browser/icons/BrowserIcons.kt13
-rw-r--r--mobile/android/android-components/components/browser/icons/src/main/java/mozilla/components/browser/icons/loader/HttpIconLoader.kt47
-rw-r--r--mobile/android/android-components/components/browser/icons/src/main/java/mozilla/components/browser/icons/loader/MemoryInfoProvider.kt32
-rw-r--r--mobile/android/android-components/components/browser/icons/src/main/java/mozilla/components/browser/icons/loader/NonBlockingHttpIconLoader.kt3
-rw-r--r--mobile/android/android-components/components/browser/icons/src/test/java/mozilla/components/browser/icons/BrowserIconsTest.kt26
-rw-r--r--mobile/android/android-components/components/browser/icons/src/test/java/mozilla/components/browser/icons/loader/HttpIconLoaderTest.kt175
-rw-r--r--mobile/android/android-components/components/browser/icons/src/test/java/mozilla/components/browser/icons/loader/NonBlockingHttpIconLoaderTest.kt21
-rw-r--r--mobile/android/android-components/components/browser/menu/src/main/java/mozilla/components/browser/menu/item/CustomTooltip.kt3
-rw-r--r--mobile/android/android-components/components/browser/menu/src/main/res/values-be/strings.xml8
-rw-r--r--mobile/android/android-components/components/browser/menu/src/main/res/values-br/strings.xml6
-rw-r--r--mobile/android/android-components/components/browser/menu/src/main/res/values-cak/strings.xml14
-rw-r--r--mobile/android/android-components/components/browser/menu/src/main/res/values-eo/strings.xml14
-rw-r--r--mobile/android/android-components/components/browser/menu/src/main/res/values-eu/strings.xml14
-rw-r--r--mobile/android/android-components/components/browser/menu/src/main/res/values-kab/strings.xml8
-rw-r--r--mobile/android/android-components/components/browser/menu/src/main/res/values-sc/strings.xml12
-rw-r--r--mobile/android/android-components/components/browser/menu2/src/test/java/mozilla/components/browser/menu2/ext/BrowserMenuPositioningTest.kt5
-rw-r--r--mobile/android/android-components/components/browser/session-storage/src/androidTest/assets/index.html8
-rw-r--r--mobile/android/android-components/components/browser/state/src/main/java/mozilla/components/browser/state/action/BrowserAction.kt49
-rw-r--r--mobile/android/android-components/components/browser/state/src/main/java/mozilla/components/browser/state/engine/middleware/CreateEngineSessionMiddleware.kt6
-rw-r--r--mobile/android/android-components/components/browser/state/src/main/java/mozilla/components/browser/state/engine/middleware/EngineDelegateMiddleware.kt4
-rw-r--r--mobile/android/android-components/components/browser/state/src/main/java/mozilla/components/browser/state/engine/middleware/LinkingMiddleware.kt13
-rw-r--r--mobile/android/android-components/components/browser/state/src/main/java/mozilla/components/browser/state/engine/middleware/TranslationsMiddleware.kt160
-rw-r--r--mobile/android/android-components/components/browser/state/src/main/java/mozilla/components/browser/state/ext/TabSessionState.kt18
-rw-r--r--mobile/android/android-components/components/browser/state/src/main/java/mozilla/components/browser/state/reducer/TranslationsStateReducer.kt100
-rw-r--r--mobile/android/android-components/components/browser/state/src/main/java/mozilla/components/browser/state/state/TranslationsBrowserState.kt4
-rw-r--r--mobile/android/android-components/components/browser/state/src/main/java/mozilla/components/browser/state/state/TranslationsState.kt2
-rw-r--r--mobile/android/android-components/components/browser/state/src/test/java/mozilla/components/browser/state/action/TranslationsActionTest.kt101
-rw-r--r--mobile/android/android-components/components/browser/state/src/test/java/mozilla/components/browser/state/engine/middleware/EngineDelegateMiddlewareTest.kt1
-rw-r--r--mobile/android/android-components/components/browser/state/src/test/java/mozilla/components/browser/state/engine/middleware/LinkingMiddlewareTest.kt4
-rw-r--r--mobile/android/android-components/components/browser/state/src/test/java/mozilla/components/browser/state/engine/middleware/TranslationsMiddlewareTest.kt181
-rw-r--r--mobile/android/android-components/components/browser/state/src/test/java/mozilla/components/browser/state/ext/TabSessionStateTest.kt34
-rw-r--r--mobile/android/android-components/components/browser/toolbar/src/main/res/values-nb-rNO/strings.xml3
-rw-r--r--mobile/android/android-components/components/browser/toolbar/src/main/res/values-sc/strings.xml5
-rw-r--r--mobile/android/android-components/components/browser/toolbar/src/main/res/values/strings.xml1
-rw-r--r--mobile/android/android-components/components/browser/toolbar2/README.md37
-rw-r--r--mobile/android/android-components/components/browser/toolbar2/build.gradle56
-rw-r--r--mobile/android/android-components/components/browser/toolbar2/proguard-rules.pro21
-rw-r--r--mobile/android/android-components/components/browser/toolbar2/src/main/AndroidManifest.xml4
-rw-r--r--mobile/android/android-components/components/browser/toolbar2/src/main/java/mozilla/components/browser/toolbar2/BrowserToolbar.kt691
-rw-r--r--mobile/android/android-components/components/browser/toolbar2/src/main/java/mozilla/components/browser/toolbar2/display/DisplayToolbar.kt711
-rw-r--r--mobile/android/android-components/components/browser/toolbar2/src/main/java/mozilla/components/browser/toolbar2/display/DisplayToolbarView.kt51
-rw-r--r--mobile/android/android-components/components/browser/toolbar2/src/main/java/mozilla/components/browser/toolbar2/display/HighlightView.kt91
-rw-r--r--mobile/android/android-components/components/browser/toolbar2/src/main/java/mozilla/components/browser/toolbar2/display/MenuButton.kt106
-rw-r--r--mobile/android/android-components/components/browser/toolbar2/src/main/java/mozilla/components/browser/toolbar2/display/OriginView.kt198
-rw-r--r--mobile/android/android-components/components/browser/toolbar2/src/main/java/mozilla/components/browser/toolbar2/display/SiteSecurityIconView.kt48
-rw-r--r--mobile/android/android-components/components/browser/toolbar2/src/main/java/mozilla/components/browser/toolbar2/display/TrackingProtectionIconView.kt135
-rw-r--r--mobile/android/android-components/components/browser/toolbar2/src/main/java/mozilla/components/browser/toolbar2/edit/EditToolbar.kt415
-rw-r--r--mobile/android/android-components/components/browser/toolbar2/src/main/java/mozilla/components/browser/toolbar2/facts/ToolbarFacts.kt60
-rw-r--r--mobile/android/android-components/components/browser/toolbar2/src/main/java/mozilla/components/browser/toolbar2/internal/ActionContainer.kt134
-rw-r--r--mobile/android/android-components/components/browser/toolbar2/src/main/java/mozilla/components/browser/toolbar2/internal/ActionWrapper.kt16
-rw-r--r--mobile/android/android-components/components/browser/toolbar2/src/main/res/drawable/mozac_browser_toolbar_icons_vertical_separator.xml9
-rw-r--r--mobile/android/android-components/components/browser/toolbar2/src/main/res/drawable/mozac_dot_notification.xml16
-rw-r--r--mobile/android/android-components/components/browser/toolbar2/src/main/res/drawable/mozac_ic_site_security.xml11
-rw-r--r--mobile/android/android-components/components/browser/toolbar2/src/main/res/drawable/mozac_ic_tracking_protection_off_for_a_site.xml12
-rw-r--r--mobile/android/android-components/components/browser/toolbar2/src/main/res/drawable/mozac_ic_tracking_protection_on_no_trackers_blocked.xml12
-rw-r--r--mobile/android/android-components/components/browser/toolbar2/src/main/res/drawable/mozac_ic_tracking_protection_on_trackers_blocked.xml12
-rw-r--r--mobile/android/android-components/components/browser/toolbar2/src/main/res/layout/mozac_browser_toolbar_displaytoolbar.xml175
-rw-r--r--mobile/android/android-components/components/browser/toolbar2/src/main/res/layout/mozac_browser_toolbar_edittoolbar.xml116
-rw-r--r--mobile/android/android-components/components/browser/toolbar2/src/main/res/values-am/strings.xml18
-rw-r--r--mobile/android/android-components/components/browser/toolbar2/src/main/res/values-an/strings.xml16
-rw-r--r--mobile/android/android-components/components/browser/toolbar2/src/main/res/values-ar/strings.xml18
-rw-r--r--mobile/android/android-components/components/browser/toolbar2/src/main/res/values-ast/strings.xml18
-rw-r--r--mobile/android/android-components/components/browser/toolbar2/src/main/res/values-az/strings.xml16
-rw-r--r--mobile/android/android-components/components/browser/toolbar2/src/main/res/values-azb/strings.xml19
-rw-r--r--mobile/android/android-components/components/browser/toolbar2/src/main/res/values-ban/strings.xml8
-rw-r--r--mobile/android/android-components/components/browser/toolbar2/src/main/res/values-be/strings.xml19
-rw-r--r--mobile/android/android-components/components/browser/toolbar2/src/main/res/values-bg/strings.xml19
-rw-r--r--mobile/android/android-components/components/browser/toolbar2/src/main/res/values-bn/strings.xml18
-rw-r--r--mobile/android/android-components/components/browser/toolbar2/src/main/res/values-br/strings.xml19
-rw-r--r--mobile/android/android-components/components/browser/toolbar2/src/main/res/values-bs/strings.xml19
-rw-r--r--mobile/android/android-components/components/browser/toolbar2/src/main/res/values-ca/strings.xml18
-rw-r--r--mobile/android/android-components/components/browser/toolbar2/src/main/res/values-cak/strings.xml19
-rw-r--r--mobile/android/android-components/components/browser/toolbar2/src/main/res/values-ceb/strings.xml18
-rw-r--r--mobile/android/android-components/components/browser/toolbar2/src/main/res/values-ckb/strings.xml18
-rw-r--r--mobile/android/android-components/components/browser/toolbar2/src/main/res/values-co/strings.xml19
-rw-r--r--mobile/android/android-components/components/browser/toolbar2/src/main/res/values-cs/strings.xml19
-rw-r--r--mobile/android/android-components/components/browser/toolbar2/src/main/res/values-cy/strings.xml19
-rw-r--r--mobile/android/android-components/components/browser/toolbar2/src/main/res/values-da/strings.xml19
-rw-r--r--mobile/android/android-components/components/browser/toolbar2/src/main/res/values-de/strings.xml19
-rw-r--r--mobile/android/android-components/components/browser/toolbar2/src/main/res/values-dsb/strings.xml19
-rw-r--r--mobile/android/android-components/components/browser/toolbar2/src/main/res/values-el/strings.xml19
-rw-r--r--mobile/android/android-components/components/browser/toolbar2/src/main/res/values-en-rCA/strings.xml19
-rw-r--r--mobile/android/android-components/components/browser/toolbar2/src/main/res/values-en-rGB/strings.xml19
-rw-r--r--mobile/android/android-components/components/browser/toolbar2/src/main/res/values-eo/strings.xml19
-rw-r--r--mobile/android/android-components/components/browser/toolbar2/src/main/res/values-es-rAR/strings.xml19
-rw-r--r--mobile/android/android-components/components/browser/toolbar2/src/main/res/values-es-rCL/strings.xml19
-rw-r--r--mobile/android/android-components/components/browser/toolbar2/src/main/res/values-es-rES/strings.xml19
-rw-r--r--mobile/android/android-components/components/browser/toolbar2/src/main/res/values-es-rMX/strings.xml18
-rw-r--r--mobile/android/android-components/components/browser/toolbar2/src/main/res/values-es/strings.xml19
-rw-r--r--mobile/android/android-components/components/browser/toolbar2/src/main/res/values-et/strings.xml18
-rw-r--r--mobile/android/android-components/components/browser/toolbar2/src/main/res/values-eu/strings.xml19
-rw-r--r--mobile/android/android-components/components/browser/toolbar2/src/main/res/values-fa/strings.xml18
-rw-r--r--mobile/android/android-components/components/browser/toolbar2/src/main/res/values-ff/strings.xml16
-rw-r--r--mobile/android/android-components/components/browser/toolbar2/src/main/res/values-fi/strings.xml19
-rw-r--r--mobile/android/android-components/components/browser/toolbar2/src/main/res/values-fr/strings.xml19
-rw-r--r--mobile/android/android-components/components/browser/toolbar2/src/main/res/values-fur/strings.xml19
-rw-r--r--mobile/android/android-components/components/browser/toolbar2/src/main/res/values-fy-rNL/strings.xml19
-rw-r--r--mobile/android/android-components/components/browser/toolbar2/src/main/res/values-ga-rIE/strings.xml16
-rw-r--r--mobile/android/android-components/components/browser/toolbar2/src/main/res/values-gd/strings.xml18
-rw-r--r--mobile/android/android-components/components/browser/toolbar2/src/main/res/values-gl/strings.xml19
-rw-r--r--mobile/android/android-components/components/browser/toolbar2/src/main/res/values-gn/strings.xml19
-rw-r--r--mobile/android/android-components/components/browser/toolbar2/src/main/res/values-gu-rIN/strings.xml16
-rw-r--r--mobile/android/android-components/components/browser/toolbar2/src/main/res/values-hi-rIN/strings.xml16
-rw-r--r--mobile/android/android-components/components/browser/toolbar2/src/main/res/values-hil/strings.xml8
-rw-r--r--mobile/android/android-components/components/browser/toolbar2/src/main/res/values-hr/strings.xml18
-rw-r--r--mobile/android/android-components/components/browser/toolbar2/src/main/res/values-hsb/strings.xml19
-rw-r--r--mobile/android/android-components/components/browser/toolbar2/src/main/res/values-hu/strings.xml19
-rw-r--r--mobile/android/android-components/components/browser/toolbar2/src/main/res/values-hy-rAM/strings.xml19
-rw-r--r--mobile/android/android-components/components/browser/toolbar2/src/main/res/values-ia/strings.xml19
-rw-r--r--mobile/android/android-components/components/browser/toolbar2/src/main/res/values-in/strings.xml18
-rw-r--r--mobile/android/android-components/components/browser/toolbar2/src/main/res/values-is/strings.xml19
-rw-r--r--mobile/android/android-components/components/browser/toolbar2/src/main/res/values-it/strings.xml19
-rw-r--r--mobile/android/android-components/components/browser/toolbar2/src/main/res/values-iw/strings.xml19
-rw-r--r--mobile/android/android-components/components/browser/toolbar2/src/main/res/values-ja/strings.xml19
-rw-r--r--mobile/android/android-components/components/browser/toolbar2/src/main/res/values-ka/strings.xml18
-rw-r--r--mobile/android/android-components/components/browser/toolbar2/src/main/res/values-kaa/strings.xml18
-rw-r--r--mobile/android/android-components/components/browser/toolbar2/src/main/res/values-kab/strings.xml19
-rw-r--r--mobile/android/android-components/components/browser/toolbar2/src/main/res/values-kk/strings.xml19
-rw-r--r--mobile/android/android-components/components/browser/toolbar2/src/main/res/values-kmr/strings.xml18
-rw-r--r--mobile/android/android-components/components/browser/toolbar2/src/main/res/values-kn/strings.xml16
-rw-r--r--mobile/android/android-components/components/browser/toolbar2/src/main/res/values-ko/strings.xml19
-rw-r--r--mobile/android/android-components/components/browser/toolbar2/src/main/res/values-ldrtl/dimens.xml8
-rw-r--r--mobile/android/android-components/components/browser/toolbar2/src/main/res/values-lij/strings.xml16
-rw-r--r--mobile/android/android-components/components/browser/toolbar2/src/main/res/values-lo/strings.xml18
-rw-r--r--mobile/android/android-components/components/browser/toolbar2/src/main/res/values-lt/strings.xml18
-rw-r--r--mobile/android/android-components/components/browser/toolbar2/src/main/res/values-mix/strings.xml18
-rw-r--r--mobile/android/android-components/components/browser/toolbar2/src/main/res/values-ml/strings.xml16
-rw-r--r--mobile/android/android-components/components/browser/toolbar2/src/main/res/values-mr/strings.xml16
-rw-r--r--mobile/android/android-components/components/browser/toolbar2/src/main/res/values-my/strings.xml18
-rw-r--r--mobile/android/android-components/components/browser/toolbar2/src/main/res/values-nb-rNO/strings.xml19
-rw-r--r--mobile/android/android-components/components/browser/toolbar2/src/main/res/values-ne-rNP/strings.xml18
-rw-r--r--mobile/android/android-components/components/browser/toolbar2/src/main/res/values-nl/strings.xml19
-rw-r--r--mobile/android/android-components/components/browser/toolbar2/src/main/res/values-nn-rNO/strings.xml19
-rw-r--r--mobile/android/android-components/components/browser/toolbar2/src/main/res/values-oc/strings.xml19
-rw-r--r--mobile/android/android-components/components/browser/toolbar2/src/main/res/values-or/strings.xml16
-rw-r--r--mobile/android/android-components/components/browser/toolbar2/src/main/res/values-pa-rIN/strings.xml19
-rw-r--r--mobile/android/android-components/components/browser/toolbar2/src/main/res/values-pa-rPK/strings.xml18
-rw-r--r--mobile/android/android-components/components/browser/toolbar2/src/main/res/values-pl/strings.xml19
-rw-r--r--mobile/android/android-components/components/browser/toolbar2/src/main/res/values-pt-rBR/strings.xml19
-rw-r--r--mobile/android/android-components/components/browser/toolbar2/src/main/res/values-pt-rPT/strings.xml19
-rw-r--r--mobile/android/android-components/components/browser/toolbar2/src/main/res/values-rm/strings.xml19
-rw-r--r--mobile/android/android-components/components/browser/toolbar2/src/main/res/values-ro/strings.xml16
-rw-r--r--mobile/android/android-components/components/browser/toolbar2/src/main/res/values-ru/strings.xml19
-rw-r--r--mobile/android/android-components/components/browser/toolbar2/src/main/res/values-sat/strings.xml19
-rw-r--r--mobile/android/android-components/components/browser/toolbar2/src/main/res/values-sc/strings.xml19
-rw-r--r--mobile/android/android-components/components/browser/toolbar2/src/main/res/values-si/strings.xml19
-rw-r--r--mobile/android/android-components/components/browser/toolbar2/src/main/res/values-sk/strings.xml19
-rw-r--r--mobile/android/android-components/components/browser/toolbar2/src/main/res/values-skr/strings.xml19
-rw-r--r--mobile/android/android-components/components/browser/toolbar2/src/main/res/values-sl/strings.xml19
-rw-r--r--mobile/android/android-components/components/browser/toolbar2/src/main/res/values-sq/strings.xml19
-rw-r--r--mobile/android/android-components/components/browser/toolbar2/src/main/res/values-sr/strings.xml18
-rw-r--r--mobile/android/android-components/components/browser/toolbar2/src/main/res/values-su/strings.xml19
-rw-r--r--mobile/android/android-components/components/browser/toolbar2/src/main/res/values-sv-rSE/strings.xml19
-rw-r--r--mobile/android/android-components/components/browser/toolbar2/src/main/res/values-szl/strings.xml18
-rw-r--r--mobile/android/android-components/components/browser/toolbar2/src/main/res/values-ta/strings.xml18
-rw-r--r--mobile/android/android-components/components/browser/toolbar2/src/main/res/values-te/strings.xml18
-rw-r--r--mobile/android/android-components/components/browser/toolbar2/src/main/res/values-tg/strings.xml19
-rw-r--r--mobile/android/android-components/components/browser/toolbar2/src/main/res/values-th/strings.xml18
-rw-r--r--mobile/android/android-components/components/browser/toolbar2/src/main/res/values-tl/strings.xml18
-rw-r--r--mobile/android/android-components/components/browser/toolbar2/src/main/res/values-tok/strings.xml14
-rw-r--r--mobile/android/android-components/components/browser/toolbar2/src/main/res/values-tr/strings.xml19
-rw-r--r--mobile/android/android-components/components/browser/toolbar2/src/main/res/values-trs/strings.xml18
-rw-r--r--mobile/android/android-components/components/browser/toolbar2/src/main/res/values-tt/strings.xml18
-rw-r--r--mobile/android/android-components/components/browser/toolbar2/src/main/res/values-tzm/strings.xml10
-rw-r--r--mobile/android/android-components/components/browser/toolbar2/src/main/res/values-ug/strings.xml19
-rw-r--r--mobile/android/android-components/components/browser/toolbar2/src/main/res/values-uk/strings.xml19
-rw-r--r--mobile/android/android-components/components/browser/toolbar2/src/main/res/values-ur/strings.xml18
-rw-r--r--mobile/android/android-components/components/browser/toolbar2/src/main/res/values-uz/strings.xml18
-rw-r--r--mobile/android/android-components/components/browser/toolbar2/src/main/res/values-vec/strings.xml16
-rw-r--r--mobile/android/android-components/components/browser/toolbar2/src/main/res/values-vi/strings.xml19
-rw-r--r--mobile/android/android-components/components/browser/toolbar2/src/main/res/values-yo/strings.xml18
-rw-r--r--mobile/android/android-components/components/browser/toolbar2/src/main/res/values-zh-rCN/strings.xml19
-rw-r--r--mobile/android/android-components/components/browser/toolbar2/src/main/res/values-zh-rTW/strings.xml19
-rw-r--r--mobile/android/android-components/components/browser/toolbar2/src/main/res/values/attrs_browser_toolbar.xml33
-rw-r--r--mobile/android/android-components/components/browser/toolbar2/src/main/res/values/dimens.xml31
-rw-r--r--mobile/android/android-components/components/browser/toolbar2/src/main/res/values/ids.xml8
-rw-r--r--mobile/android/android-components/components/browser/toolbar2/src/main/res/values/strings.xml22
-rw-r--r--mobile/android/android-components/components/browser/toolbar2/src/test/java/mozilla/components/browser/toolbar2/AsyncFilterListenerTest.kt350
-rw-r--r--mobile/android/android-components/components/browser/toolbar2/src/test/java/mozilla/components/browser/toolbar2/BrowserToolbarTest.kt1044
-rw-r--r--mobile/android/android-components/components/browser/toolbar2/src/test/java/mozilla/components/browser/toolbar2/display/DisplayToolbarTest.kt824
-rw-r--r--mobile/android/android-components/components/browser/toolbar2/src/test/java/mozilla/components/browser/toolbar2/display/HighlightViewTest.kt67
-rw-r--r--mobile/android/android-components/components/browser/toolbar2/src/test/java/mozilla/components/browser/toolbar2/display/MenuButtonTest.kt156
-rw-r--r--mobile/android/android-components/components/browser/toolbar2/src/test/java/mozilla/components/browser/toolbar2/display/TrackingProtectionIconViewTest.kt43
-rw-r--r--mobile/android/android-components/components/browser/toolbar2/src/test/java/mozilla/components/browser/toolbar2/edit/EditToolbarTest.kt290
-rw-r--r--mobile/android/android-components/components/browser/toolbar2/src/test/java/mozilla/components/browser/toolbar2/internal/ActionContainerTest.kt99
-rw-r--r--mobile/android/android-components/components/browser/toolbar2/src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker2
-rw-r--r--mobile/android/android-components/components/compose/cfr/src/main/java/mozilla/components/compose/cfr/CFRPopupLayout.kt160
-rw-r--r--mobile/android/android-components/components/concept/engine/src/main/java/mozilla/components/concept/engine/translate/TranslationEngineState.kt2
-rw-r--r--mobile/android/android-components/components/concept/engine/src/main/java/mozilla/components/concept/engine/translate/TranslationOperation.kt7
-rw-r--r--mobile/android/android-components/components/concept/engine/src/main/java/mozilla/components/concept/engine/webextension/WebExtensionDelegate.kt7
-rw-r--r--mobile/android/android-components/components/concept/engine/src/test/resources/manifests/example_mdn.json67
-rw-r--r--mobile/android/android-components/components/concept/engine/src/test/resources/manifests/spec_typical.json78
-rw-r--r--mobile/android/android-components/components/concept/engine/src/test/resources/manifests/twitter_mobile.json29
-rw-r--r--mobile/android/android-components/components/concept/sync/src/main/java/mozilla/components/concept/sync/AccountEvent.kt6
-rw-r--r--mobile/android/android-components/components/concept/sync/src/main/java/mozilla/components/concept/sync/Devices.kt1
-rw-r--r--mobile/android/android-components/components/concept/sync/src/main/java/mozilla/components/concept/sync/OAuthAccount.kt19
-rw-r--r--mobile/android/android-components/components/feature/accounts-push/build.gradle3
-rw-r--r--mobile/android/android-components/components/feature/accounts-push/src/main/java/mozilla/components/feature/accounts/push/CloseTabsFeature.kt93
-rw-r--r--mobile/android/android-components/components/feature/accounts-push/src/main/java/mozilla/components/feature/accounts/push/CloseTabsUseCases.kt63
-rw-r--r--mobile/android/android-components/components/feature/accounts-push/src/main/java/mozilla/components/feature/accounts/push/SendTabFeature.kt8
-rw-r--r--mobile/android/android-components/components/feature/accounts-push/src/test/java/mozilla/components/feature/accounts/push/CloseTabsFeatureTest.kt136
-rw-r--r--mobile/android/android-components/components/feature/accounts-push/src/test/java/mozilla/components/feature/accounts/push/CloseTabsUseCasesTest.kt100
-rw-r--r--mobile/android/android-components/components/feature/accounts-push/src/test/java/mozilla/components/feature/accounts/push/TabReceivedEventsObserverTest.kt (renamed from mobile/android/android-components/components/feature/accounts-push/src/test/java/mozilla/components/feature/accounts/push/EventsObserverTest.kt)6
-rw-r--r--mobile/android/android-components/components/feature/accounts-push/src/test/java/mozilla/components/feature/accounts/push/TabsClosedEventsObserverTest.kt183
-rw-r--r--mobile/android/android-components/components/feature/accounts/src/main/assets/extensions/fxawebchannel/background.js10
-rw-r--r--mobile/android/android-components/components/feature/accounts/src/main/assets/extensions/fxawebchannel/fxawebchannel.js12
-rw-r--r--mobile/android/android-components/components/feature/accounts/src/main/java/mozilla/components/feature/accounts/FirefoxAccountsAuthFeature.kt13
-rw-r--r--mobile/android/android-components/components/feature/accounts/src/main/java/mozilla/components/feature/accounts/FxaWebChannelFeature.kt36
-rw-r--r--mobile/android/android-components/components/feature/accounts/src/test/java/mozilla/components/feature/accounts/FirefoxAccountsAuthFeatureTest.kt14
-rw-r--r--mobile/android/android-components/components/feature/accounts/src/test/java/mozilla/components/feature/accounts/FxaWebChannelFeatureTest.kt86
-rw-r--r--mobile/android/android-components/components/feature/addons/src/main/java/mozilla/components/feature/addons/AddonManager.kt8
-rw-r--r--mobile/android/android-components/components/feature/addons/src/main/java/mozilla/components/feature/addons/ui/PermissionsDialogFragment.kt10
-rw-r--r--mobile/android/android-components/components/feature/addons/src/main/res/values-be/strings.xml14
-rw-r--r--mobile/android/android-components/components/feature/addons/src/main/res/values-br/strings.xml34
-rw-r--r--mobile/android/android-components/components/feature/addons/src/main/res/values-cak/strings.xml68
-rw-r--r--mobile/android/android-components/components/feature/addons/src/main/res/values-eo/strings.xml68
-rw-r--r--mobile/android/android-components/components/feature/addons/src/main/res/values-eu/strings.xml68
-rw-r--r--mobile/android/android-components/components/feature/addons/src/main/res/values-it/strings.xml20
-rw-r--r--mobile/android/android-components/components/feature/addons/src/main/res/values-kab/strings.xml28
-rw-r--r--mobile/android/android-components/components/feature/addons/src/main/res/values-ko/strings.xml2
-rw-r--r--mobile/android/android-components/components/feature/addons/src/main/res/values-nn-rNO/strings.xml28
-rw-r--r--mobile/android/android-components/components/feature/addons/src/main/res/values-sc/strings.xml60
-rw-r--r--mobile/android/android-components/components/feature/addons/src/main/res/values-si/strings.xml8
-rw-r--r--mobile/android/android-components/components/feature/addons/src/main/res/values-su/strings.xml30
-rw-r--r--mobile/android/android-components/components/feature/addons/src/test/java/AddonManagerTest.kt11
-rw-r--r--mobile/android/android-components/components/feature/addons/src/test/java/mozilla/components/feature/addons/ui/PermissionsDialogFragmentTest.kt10
-rw-r--r--mobile/android/android-components/components/feature/addons/src/test/resources/amo_search_localized_single_result.json73
-rw-r--r--mobile/android/android-components/components/feature/addons/src/test/resources/amo_search_multiple_results.json85
-rw-r--r--mobile/android/android-components/components/feature/addons/src/test/resources/amo_search_single_result.json73
-rw-r--r--mobile/android/android-components/components/feature/addons/src/test/resources/collection.json73
-rw-r--r--mobile/android/android-components/components/feature/addons/src/test/resources/collection_with_empty_values.json50
-rw-r--r--mobile/android/android-components/components/feature/addons/src/test/resources/localized_collection.json73
-rw-r--r--mobile/android/android-components/components/feature/app-links/src/main/res/values-sk/strings.xml2
-rw-r--r--mobile/android/android-components/components/feature/contextmenu/build.gradle1
-rw-r--r--mobile/android/android-components/components/feature/downloads/src/main/java/mozilla/components/feature/downloads/DownloadMiddleware.kt12
-rw-r--r--mobile/android/android-components/components/feature/downloads/src/main/java/mozilla/components/feature/downloads/DownloadNotification.kt7
-rw-r--r--mobile/android/android-components/components/feature/downloads/src/main/res/values-ast/strings.xml3
-rw-r--r--mobile/android/android-components/components/feature/findinpage/build.gradle1
-rw-r--r--mobile/android/android-components/components/feature/media/build.gradle1
-rw-r--r--mobile/android/android-components/components/feature/media/src/main/res/values-br/strings.xml19
-rw-r--r--mobile/android/android-components/components/feature/media/src/main/res/values-nn-rNO/strings.xml6
-rw-r--r--mobile/android/android-components/components/feature/media/src/main/res/values-su/strings.xml9
-rw-r--r--mobile/android/android-components/components/feature/prompts/src/main/java/mozilla/components/feature/prompts/PromptFeature.kt37
-rw-r--r--mobile/android/android-components/components/feature/prompts/src/main/java/mozilla/components/feature/prompts/dialog/TextPromptDialogFragment.kt13
-rw-r--r--mobile/android/android-components/components/feature/prompts/src/main/res/values-br/strings.xml76
-rw-r--r--mobile/android/android-components/components/feature/prompts/src/main/res/values-kab/strings.xml2
-rw-r--r--mobile/android/android-components/components/feature/prompts/src/main/res/values-nn-rNO/strings.xml13
-rw-r--r--mobile/android/android-components/components/feature/prompts/src/main/res/values-sc/strings.xml68
-rw-r--r--mobile/android/android-components/components/feature/prompts/src/main/res/values-sl/strings.xml68
-rw-r--r--mobile/android/android-components/components/feature/prompts/src/main/res/values-su/strings.xml70
-rw-r--r--mobile/android/android-components/components/feature/prompts/src/main/res/values/quarantined_strings.xml2
-rw-r--r--mobile/android/android-components/components/feature/prompts/src/test/java/mozilla/components/feature/prompts/PromptFeatureTest.kt133
-rw-r--r--mobile/android/android-components/components/feature/prompts/src/test/java/mozilla/components/feature/prompts/dialog/TextPromptDialogFragmentTest.kt29
-rw-r--r--mobile/android/android-components/components/feature/pwa/src/main/java/mozilla/components/feature/pwa/WebAppShortcutManager.kt3
-rw-r--r--mobile/android/android-components/components/feature/qr/build.gradle1
-rw-r--r--mobile/android/android-components/components/feature/readerview/src/main/assets/extensions/readerview/manifest.template.json5
-rw-r--r--mobile/android/android-components/components/feature/readerview/src/main/assets/extensions/readerview/readerview-background.js24
-rw-r--r--mobile/android/android-components/components/feature/readerview/src/main/assets/extensions/readerview/readerview-content.js64
-rw-r--r--mobile/android/android-components/components/feature/readerview/src/main/assets/extensions/readerview/readerview.html14
-rw-r--r--mobile/android/android-components/components/feature/readerview/src/main/assets/extensions/readerview/readerview.js194
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/assets/extensions/ads/adsTelemetry.js72
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/assets/extensions/search/searchTelemetry.js54
-rw-r--r--mobile/android/android-components/components/feature/search/src/main/assets/search/list.json683
-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-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/java/mozilla/components/feature/search/internal/SearchUrlBuilder.kt6
-rw-r--r--mobile/android/android-components/components/feature/search/src/test/java/mozilla/components/feature/search/middleware/SearchMiddlewareTest.kt215
-rw-r--r--mobile/android/android-components/components/feature/search/src/test/java/mozilla/components/feature/search/storage/BundledSearchEnginesStorageTest.kt18
-rw-r--r--mobile/android/android-components/components/feature/session/src/main/java/mozilla/components/feature/session/SessionFeature.kt17
-rw-r--r--mobile/android/android-components/components/feature/session/src/main/java/mozilla/components/feature/session/SessionUseCases.kt6
-rw-r--r--mobile/android/android-components/components/feature/session/src/test/java/mozilla/components/feature/session/SessionFeatureTest.kt74
-rw-r--r--mobile/android/android-components/components/feature/session/src/test/java/mozilla/components/feature/session/SessionUseCasesTest.kt1
-rw-r--r--mobile/android/android-components/components/feature/sitepermissions/src/main/res/values-ast/strings.xml4
-rw-r--r--mobile/android/android-components/components/feature/tabs/src/main/java/mozilla/components/feature/tabs/TabsUseCases.kt2
-rw-r--r--mobile/android/android-components/components/feature/webcompat-reporter/src/main/assets/extensions/webcompat-reporter/manifest.json11
-rw-r--r--mobile/android/android-components/components/lib/auth/build.gradle1
-rw-r--r--mobile/android/android-components/components/lib/crash/build.gradle1
-rw-r--r--mobile/android/android-components/components/lib/crash/src/main/res/values-ast/strings.xml6
-rw-r--r--mobile/android/android-components/components/lib/crash/src/main/res/values-zh-rCN/strings.xml2
-rw-r--r--mobile/android/android-components/components/lib/push-firebase/build.gradle1
-rw-r--r--mobile/android/android-components/components/lib/push-firebase/src/main/java/mozilla/components/lib/push/firebase/AbstractFirebasePushService.kt2
-rw-r--r--mobile/android/android-components/components/service/firefox-accounts/src/main/java/mozilla/components/service/fxa/AccountStorage.kt19
-rw-r--r--mobile/android/android-components/components/service/firefox-accounts/src/main/java/mozilla/components/service/fxa/FirefoxAccount.kt11
-rw-r--r--mobile/android/android-components/components/service/firefox-accounts/src/main/java/mozilla/components/service/fxa/FxaDeviceConstellation.kt3
-rw-r--r--mobile/android/android-components/components/service/firefox-accounts/src/main/java/mozilla/components/service/fxa/Types.kt25
-rw-r--r--mobile/android/android-components/components/service/firefox-accounts/src/main/java/mozilla/components/service/fxa/manager/FxaAccountManager.kt84
-rw-r--r--mobile/android/android-components/components/service/firefox-accounts/src/main/java/mozilla/components/service/fxa/manager/State.kt31
-rw-r--r--mobile/android/android-components/components/service/firefox-accounts/src/main/java/mozilla/components/service/fxa/store/SyncAction.kt6
-rw-r--r--mobile/android/android-components/components/service/firefox-accounts/src/main/java/mozilla/components/service/fxa/store/SyncState.kt5
-rw-r--r--mobile/android/android-components/components/service/firefox-accounts/src/main/java/mozilla/components/service/fxa/store/SyncStore.kt1
-rw-r--r--mobile/android/android-components/components/service/firefox-accounts/src/main/java/mozilla/components/service/fxa/store/SyncStoreSupport.kt32
-rw-r--r--mobile/android/android-components/components/service/firefox-accounts/src/test/java/mozilla/components/service/fxa/FxaAccountManagerTest.kt192
-rw-r--r--mobile/android/android-components/components/service/firefox-accounts/src/test/java/mozilla/components/service/fxa/manager/StateKtTest.kt4
-rw-r--r--mobile/android/android-components/components/service/firefox-accounts/src/test/java/mozilla/components/service/fxa/store/SyncStoreSupportTest.kt106
-rw-r--r--mobile/android/android-components/components/service/glean/src/main/java/mozilla/components/service/glean/Glean.kt4
-rw-r--r--mobile/android/android-components/components/service/glean/src/main/java/mozilla/components/service/glean/config/Configuration.kt4
-rw-r--r--mobile/android/android-components/components/service/glean/src/main/java/mozilla/components/service/glean/private/MetricAliases.kt87
-rw-r--r--mobile/android/android-components/components/service/nimbus/messaging.fml.yaml29
-rw-r--r--mobile/android/android-components/components/service/pocket/src/test/resources/pocket/stories_recommendations_response.json84
-rw-r--r--mobile/android/android-components/components/service/pocket/src/test/resources/pocket/story_recommendation_response.json20
-rw-r--r--mobile/android/android-components/components/service/sync-logins/src/main/java/mozilla/components/service/sync/logins/GeckoLoginStorageDelegate.kt9
-rw-r--r--mobile/android/android-components/components/support/base/build.gradle1
-rw-r--r--mobile/android/android-components/components/support/base/src/main/java/mozilla/components/support/base/android/BuildVersionProvider.kt31
-rw-r--r--mobile/android/android-components/components/support/base/src/main/java/mozilla/components/support/base/android/PowerManagerInfoProvider.kt39
-rw-r--r--mobile/android/android-components/components/support/base/src/main/java/mozilla/components/support/base/android/ProcessInfoProvider.kt32
-rw-r--r--mobile/android/android-components/components/support/base/src/main/java/mozilla/components/support/base/android/StartForegroundService.kt41
-rw-r--r--mobile/android/android-components/components/support/base/src/main/java/mozilla/components/support/base/feature/UserInteractionHandler.kt7
-rw-r--r--mobile/android/android-components/components/support/base/src/main/java/mozilla/components/support/base/feature/ViewBoundFeatureWrapper.kt18
-rw-r--r--mobile/android/android-components/components/support/base/src/test/java/mozilla/components/support/base/android/StartForegroundServiceTest.kt98
-rw-r--r--mobile/android/android-components/components/support/base/src/test/java/mozilla/components/support/base/feature/ViewBoundFeatureWrapperTest.kt50
-rw-r--r--mobile/android/android-components/components/support/ktx/src/main/java/mozilla/components/support/ktx/android/view/View.kt5
-rw-r--r--mobile/android/android-components/components/support/ktx/src/main/java/mozilla/components/support/ktx/kotlin/String.kt20
-rw-r--r--mobile/android/android-components/components/support/ktx/src/test/java/mozilla/components/support/ktx/kotlin/StringTest.kt88
-rw-r--r--mobile/android/android-components/components/support/webextensions/src/main/java/mozilla/components/support/webextensions/WebExtensionSupport.kt4
-rw-r--r--mobile/android/android-components/components/support/webextensions/src/test/java/mozilla/components/support/webextensions/WebExtensionSupportTest.kt19
-rw-r--r--mobile/android/android-components/components/ui/autocomplete/src/main/java/mozilla/components/ui/autocomplete/InlineAutocompleteEditText.kt4
-rw-r--r--mobile/android/android-components/components/ui/autocomplete/src/test/java/mozilla/components/ui/autocomplete/InlineAutocompleteEditTextTest.kt15
-rw-r--r--mobile/android/android-components/components/ui/icons/src/main/res/drawable/mozac_ic_private_mode_circle_fill_20.xml10
-rw-r--r--mobile/android/android-components/components/ui/icons/src/main/res/drawable/mozac_ic_private_mode_circle_fill_24.xml10
-rw-r--r--mobile/android/android-components/components/ui/icons/src/main/res/values/attrs.xml6
-rw-r--r--mobile/android/android-components/components/ui/widgets/src/test/java/mozilla/components/ui/widgets/behavior/EngineViewScrollingBehaviorTest.kt2
-rw-r--r--mobile/android/android-components/config/detekt-baseline.xml1
-rw-r--r--mobile/android/android-components/docs/_includes/header.html34
-rw-r--r--mobile/android/android-components/docs/_includes/post_detail.html22
-rw-r--r--mobile/android/android-components/docs/_layouts/post.html61
-rw-r--r--mobile/android/android-components/docs/assets/js/icon-js.js145
-rw-r--r--mobile/android/android-components/docs/changelog.md27
-rw-r--r--mobile/android/android-components/gradle/wrapper/gradle-wrapper.properties4
-rw-r--r--mobile/android/android-components/plugins/dependencies/src/main/java/ApplicationServices.kt2
-rw-r--r--mobile/android/android-components/plugins/dependencies/src/main/java/DependenciesPlugin.kt31
-rw-r--r--mobile/android/android-components/plugins/dependencies/src/main/java/moz.yaml4
-rw-r--r--mobile/android/android-components/samples/browser/src/androidTest/assets/index.html6
-rw-r--r--mobile/android/android-components/samples/browser/src/main/assets/extensions/borderify/borderify.js2
-rw-r--r--mobile/android/android-components/samples/browser/src/main/assets/extensions/test/background.js11
-rw-r--r--mobile/android/android-components/samples/browser/src/main/assets/extensions/test/manifest.template.json4
-rw-r--r--mobile/android/android-components/samples/browser/src/main/java/org/mozilla/samples/browser/BaseBrowserFragment.kt1
-rw-r--r--mobile/android/android-components/samples/crash/build.gradle1
-rw-r--r--mobile/android/android-components/samples/firefox-accounts/build.gradle1
-rw-r--r--mobile/android/android-components/samples/sync/src/main/java/org/mozilla/samples/sync/MainActivity.kt9
-rw-r--r--mobile/android/android-components/samples/toolbar/build.gradle1
-rw-r--r--mobile/android/android-components/settings.gradle69
371 files changed, 28136 insertions, 25929 deletions
diff --git a/mobile/android/android-components/.buildconfig.yml b/mobile/android/android-components/.buildconfig.yml
index c8a03c3ab5..5930361a20 100644
--- a/mobile/android/android-components/.buildconfig.yml
+++ b/mobile/android/android-components/.buildconfig.yml
@@ -270,6 +270,33 @@ projects:
- ui-colors
- ui-icons
- ui-widgets
+ browser-toolbar2:
+ description: A customizable toolbar for browsers.
+ path: components/browser/toolbar2
+ publish: true
+ upstream_dependencies:
+ - browser-errorpages
+ - browser-menu
+ - browser-menu2
+ - browser-state
+ - concept-awesomebar
+ - concept-base
+ - concept-engine
+ - concept-fetch
+ - concept-menu
+ - concept-storage
+ - concept-toolbar
+ - lib-publicsuffixlist
+ - lib-state
+ - support-base
+ - support-ktx
+ - support-test
+ - support-utils
+ - tooling-lint
+ - ui-autocomplete
+ - ui-colors
+ - ui-icons
+ - ui-widgets
compose-awesomebar:
description: An awesomebar component showing search results matching text entered
into the toolbar.
@@ -533,7 +560,12 @@ projects:
path: components/feature/accounts-push
publish: true
upstream_dependencies:
+ - browser-errorpages
+ - browser-state
+ - concept-awesomebar
- concept-base
+ - concept-engine
+ - concept-fetch
- concept-push
- concept-storage
- concept-sync
@@ -545,8 +577,10 @@ projects:
- support-base
- support-ktx
- support-test
+ - support-test-libstate
- support-utils
- tooling-lint
+ - ui-icons
feature-addons:
description: A feature that provides for managing add-ons.
path: components/feature/addons
@@ -560,6 +594,7 @@ projects:
- concept-fetch
- concept-menu
- concept-storage
+ - concept-toolbar
- lib-publicsuffixlist
- lib-state
- support-base
@@ -607,6 +642,7 @@ projects:
- concept-engine
- concept-fetch
- concept-storage
+ - concept-toolbar
- lib-fetch-okhttp
- lib-publicsuffixlist
- service-digitalassetlinks
@@ -773,6 +809,7 @@ projects:
- concept-engine
- concept-fetch
- concept-storage
+ - concept-toolbar
- lib-publicsuffixlist
- lib-state
- support-android-test
@@ -2272,6 +2309,7 @@ projects:
- concept-engine
- concept-fetch
- concept-storage
+ - concept-toolbar
- lib-publicsuffixlist
- support-base
- support-ktx
diff --git a/mobile/android/android-components/README.md b/mobile/android/android-components/README.md
index 7076f5e2ac..ed7199de63 100644
--- a/mobile/android/android-components/README.md
+++ b/mobile/android/android-components/README.md
@@ -83,6 +83,8 @@ High-level components for building browser(-like) apps.
* 🔵 [**Toolbar**](components/browser/toolbar/README.md) - A customizable toolbar for browsers.
+* 🔴 [**Toolbar2**](components/browser/toolbar2/README.md) - A customizable toolbar for browsers.
+
## Concept
_API contracts and abstraction layers for browser components._
diff --git a/mobile/android/android-components/build.gradle b/mobile/android/android-components/build.gradle
index f1b46775c1..5907f00712 100644
--- a/mobile/android/android-components/build.gradle
+++ b/mobile/android/android-components/build.gradle
@@ -89,28 +89,6 @@ subprojects {
}
}
-
- // Allow local appservices substitution in each subproject.
- def appServicesSrcDir = null
- if (gradle.hasProperty('localProperties.autoPublish.application-services.dir')) {
- appServicesSrcDir = gradle.getProperty('localProperties.autoPublish.application-services.dir')
- } else if (gradle.hasProperty('localProperties.branchBuild.application-services.dir')) {
- appServicesSrcDir = gradle.getProperty('localProperties.branchBuild.application-services.dir')
- }
- if (appServicesSrcDir) {
- if (appServicesSrcDir.startsWith("/")) {
- apply from: "${appServicesSrcDir}/build-scripts/substitute-local-appservices.gradle"
- } else {
- apply from: "${rootProject.projectDir}/${appServicesSrcDir}/build-scripts/substitute-local-appservices.gradle"
- }
- }
-
- // Allow local Glean substitution in each subproject.
- if (gradle.hasProperty('localProperties.autoPublish.glean.dir')) {
- ext.gleanSrcDir = gradle."localProperties.autoPublish.glean.dir"
- apply from: "${rootProject.projectDir}/${gleanSrcDir}/build-scripts/substitute-local-glean.gradle"
- }
-
if (gradle.hasProperty('localProperties.dependencySubstitutions.geckoviewTopsrcdir')) {
if (gradle.hasProperty('localProperties.dependencySubstitutions.geckoviewTopobjdir')) {
ext.topobjdir = gradle."localProperties.dependencySubstitutions.geckoviewTopobjdir"
diff --git a/mobile/android/android-components/components/browser/engine-gecko/build.gradle b/mobile/android/android-components/components/browser/engine-gecko/build.gradle
index 4e5c2fda65..776c083ee9 100644
--- a/mobile/android/android-components/components/browser/engine-gecko/build.gradle
+++ b/mobile/android/android-components/components/browser/engine-gecko/build.gradle
@@ -76,8 +76,9 @@ dependencies {
api getGeckoViewDependency()
}
+ implementation ComponentsDependencies.androidx_core_ktx
implementation ComponentsDependencies.androidx_paging
- implementation ComponentsDependencies.androidx_data_store_preferences
+ implementation ComponentsDependencies.androidx_datastore_preferences
implementation ComponentsDependencies.androidx_lifecycle_livedata
testImplementation ComponentsDependencies.androidx_test_core
diff --git a/mobile/android/android-components/components/browser/engine-gecko/src/main/java/mozilla/components/browser/engine/gecko/GeckoEngine.kt b/mobile/android/android-components/components/browser/engine-gecko/src/main/java/mozilla/components/browser/engine/gecko/GeckoEngine.kt
index 92e6074a61..f5f1012448 100644
--- a/mobile/android/android-components/components/browser/engine-gecko/src/main/java/mozilla/components/browser/engine/gecko/GeckoEngine.kt
+++ b/mobile/android/android-components/components/browser/engine-gecko/src/main/java/mozilla/components/browser/engine/gecko/GeckoEngine.kt
@@ -426,6 +426,10 @@ class GeckoEngine(
exception as WebExtensionInstallException,
)
}
+
+ override fun onOptionalPermissionsChanged(extension: org.mozilla.geckoview.WebExtension) {
+ webExtensionDelegate.onOptionalPermissionsChanged(GeckoWebExtension(extension, runtime))
+ }
}
val extensionProcessDelegate = object : WebExtensionController.ExtensionProcessDelegate {
diff --git a/mobile/android/android-components/components/browser/engine-gecko/src/main/java/mozilla/components/browser/engine/gecko/GeckoEngineSession.kt b/mobile/android/android-components/components/browser/engine-gecko/src/main/java/mozilla/components/browser/engine/gecko/GeckoEngineSession.kt
index e6907c6dde..dbf7b2d54f 100644
--- a/mobile/android/android-components/components/browser/engine-gecko/src/main/java/mozilla/components/browser/engine/gecko/GeckoEngineSession.kt
+++ b/mobile/android/android-components/components/browser/engine-gecko/src/main/java/mozilla/components/browser/engine/gecko/GeckoEngineSession.kt
@@ -4,7 +4,6 @@
package mozilla.components.browser.engine.gecko
-import android.annotation.SuppressLint
import android.net.Uri
import android.os.Build
import android.view.WindowManager
@@ -58,6 +57,7 @@ import mozilla.components.support.base.facts.Action
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.kotlin.decode
import mozilla.components.support.ktx.kotlin.isEmail
import mozilla.components.support.ktx.kotlin.isExtensionUrl
import mozilla.components.support.ktx.kotlin.isGeoLocation
@@ -557,9 +557,8 @@ class GeckoEngineSession(
/**
* See [EngineSession.findNext]
*/
- @SuppressLint("WrongConstant") // FinderFindFlags annotation doesn't include a 0 value.
override fun findNext(forward: Boolean) {
- val findFlags = if (forward) 0 else GeckoSession.FINDER_FIND_BACKWARDS
+ val findFlags = if (forward) GeckoSession.FINDER_FIND_FORWARD else GeckoSession.FINDER_FIND_BACKWARDS
geckoSession.finder.find(null, findFlags).then { result: GeckoSession.FinderResult? ->
result?.let {
val activeMatchOrdinal = if (it.current > 0) it.current - 1 else it.current
@@ -1159,9 +1158,9 @@ class GeckoEngineSession(
return when {
maybeInterceptRequest(request, false) != null ->
- GeckoResult.fromValue(AllowOrDeny.DENY)
+ GeckoResult.deny()
request.target == NavigationDelegate.TARGET_WINDOW_NEW ->
- GeckoResult.fromValue(AllowOrDeny.ALLOW)
+ GeckoResult.allow()
else -> {
notifyObservers {
onLoadRequest(
@@ -1171,7 +1170,7 @@ class GeckoEngineSession(
)
}
- GeckoResult.fromValue(AllowOrDeny.ALLOW)
+ GeckoResult.allow()
}
}
}
@@ -1181,15 +1180,15 @@ class GeckoEngineSession(
request: NavigationDelegate.LoadRequest,
): GeckoResult<AllowOrDeny> {
if (request.target == NavigationDelegate.TARGET_WINDOW_NEW) {
- return GeckoResult.fromValue(AllowOrDeny.ALLOW)
+ return GeckoResult.allow()
}
return if (maybeInterceptRequest(request, true) != null) {
- GeckoResult.fromValue(AllowOrDeny.DENY)
+ GeckoResult.deny()
} else {
// Not notifying session observer because of performance concern and currently there
// is no use case.
- GeckoResult.fromValue(AllowOrDeny.ALLOW)
+ GeckoResult.allow()
}
}
@@ -1526,7 +1525,7 @@ class GeckoEngineSession(
url = url,
contentLength = contentLength,
contentType = DownloadUtils.sanitizeMimeType(contentType),
- fileName = fileName.sanitizeFileName(),
+ fileName = fileName.sanitizeFileName().decode(),
response = response,
isPrivate = privateMode,
openInApp = webResponse.requestExternalApp,
diff --git a/mobile/android/android-components/components/browser/engine-gecko/src/main/java/mozilla/components/browser/engine/gecko/GeckoEngineView.kt b/mobile/android/android-components/components/browser/engine-gecko/src/main/java/mozilla/components/browser/engine/gecko/GeckoEngineView.kt
index d5d77b3073..39a4c2d6cc 100644
--- a/mobile/android/android-components/components/browser/engine-gecko/src/main/java/mozilla/components/browser/engine/gecko/GeckoEngineView.kt
+++ b/mobile/android/android-components/components/browser/engine-gecko/src/main/java/mozilla/components/browser/engine/gecko/GeckoEngineView.kt
@@ -9,6 +9,7 @@ import android.content.res.Configuration
import android.graphics.Bitmap
import android.graphics.Color
import android.util.AttributeSet
+import android.view.View
import android.widget.FrameLayout
import androidx.annotation.VisibleForTesting
import androidx.core.view.ViewCompat
@@ -63,7 +64,7 @@ class GeckoEngineView @JvmOverloads constructor(
// Explicitly mark this view as important for autofill. The default "auto" doesn't seem to trigger any
// autofill behavior for us here.
@Suppress("WrongConstant")
- ViewCompat.setImportantForAutofill(this, ViewCompat.IMPORTANT_FOR_ACCESSIBILITY_YES)
+ ViewCompat.setImportantForAutofill(this, View.IMPORTANT_FOR_ACCESSIBILITY_YES)
}
internal fun setColorScheme(preferredColorScheme: PreferredColorScheme) {
@@ -205,29 +206,18 @@ class GeckoEngineView @JvmOverloads constructor(
geckoView.activityContextDelegate = GeckoViewActivityContextDelegate(WeakReference(context))
}
- @Suppress("TooGenericExceptionCaught")
override fun captureThumbnail(onFinish: (Bitmap?) -> Unit) {
- try {
- val geckoResult = geckoView.capturePixels()
- geckoResult.then(
- { bitmap ->
- onFinish(bitmap)
- GeckoResult<Void>()
- },
- {
- onFinish(null)
- GeckoResult<Void>()
- },
- )
- } catch (e: Exception) {
- // There's currently no reliable way for consumers of GeckoView to
- // know whether or not the compositor is ready. So we have to add
- // a catch-all here. In the future, GeckoView will invoke our error
- // callback instead and this block can be removed:
- // https://bugzilla.mozilla.org/show_bug.cgi?id=1645114
- // https://github.com/mozilla-mobile/android-components/issues/6680
- onFinish(null)
- }
+ val geckoResult = geckoView.capturePixels()
+ geckoResult.then(
+ { bitmap ->
+ onFinish(bitmap)
+ GeckoResult()
+ },
+ {
+ onFinish(null)
+ GeckoResult<Void>()
+ },
+ )
}
override fun clearSelection() {
diff --git a/mobile/android/android-components/components/browser/engine-gecko/src/main/java/mozilla/components/browser/engine/gecko/prompt/GeckoPromptDelegate.kt b/mobile/android/android-components/components/browser/engine-gecko/src/main/java/mozilla/components/browser/engine/gecko/prompt/GeckoPromptDelegate.kt
index d4276e675a..8fb2e1e0fb 100644
--- a/mobile/android/android-components/components/browser/engine-gecko/src/main/java/mozilla/components/browser/engine/gecko/prompt/GeckoPromptDelegate.kt
+++ b/mobile/android/android-components/components/browser/engine-gecko/src/main/java/mozilla/components/browser/engine/gecko/prompt/GeckoPromptDelegate.kt
@@ -282,17 +282,16 @@ internal class GeckoPromptDelegate(private val geckoEngineSession: GeckoEngineSe
return geckoResult
}
+ @Suppress("MaxLineLength")
override fun onLoginSelect(
session: GeckoSession,
prompt: AutocompleteRequest<Autocomplete.LoginSelectOption>,
): GeckoResult<PromptResponse>? {
val promptOptions = prompt.options
+
val generatedPassword =
- if (promptOptions.isNotEmpty() && promptOptions.first().hint == Autocomplete.SelectOption.Hint.GENERATED) {
- promptOptions.first().value.password
- } else {
- null
- }
+ promptOptions.firstOrNull { option -> option.hint == Autocomplete.SelectOption.Hint.GENERATED }?.value?.password
+
val geckoResult = GeckoResult<PromptResponse>()
val onConfirmSelect: (Login) -> Unit = { login ->
if (!prompt.isComplete) {
diff --git a/mobile/android/android-components/components/browser/engine-gecko/src/main/java/mozilla/components/browser/engine/gecko/translate/GeckoTranslateSessionDelegate.kt b/mobile/android/android-components/components/browser/engine-gecko/src/main/java/mozilla/components/browser/engine/gecko/translate/GeckoTranslateSessionDelegate.kt
index 3266ba8538..884db33824 100644
--- a/mobile/android/android-components/components/browser/engine-gecko/src/main/java/mozilla/components/browser/engine/gecko/translate/GeckoTranslateSessionDelegate.kt
+++ b/mobile/android/android-components/components/browser/engine-gecko/src/main/java/mozilla/components/browser/engine/gecko/translate/GeckoTranslateSessionDelegate.kt
@@ -66,10 +66,11 @@ internal class GeckoTranslateSessionDelegate(
state?.requestedTranslationPair?.toLanguage,
)
val translationsState = TranslationEngineState(
- detectedLanguages,
- state?.error,
- state?.isEngineReady,
- pair,
+ detectedLanguages = detectedLanguages,
+ error = state?.error,
+ isEngineReady = state?.isEngineReady,
+ hasVisibleChange = state?.hasVisibleChange,
+ requestedTranslationPair = pair,
)
engineSession.notifyObservers {
diff --git a/mobile/android/android-components/components/browser/engine-gecko/src/test/java/mozilla/components/browser/engine/gecko/GeckoEngineSessionTest.kt b/mobile/android/android-components/components/browser/engine-gecko/src/test/java/mozilla/components/browser/engine/gecko/GeckoEngineSessionTest.kt
index 87849440b6..871c46a33d 100644
--- a/mobile/android/android-components/components/browser/engine-gecko/src/test/java/mozilla/components/browser/engine/gecko/GeckoEngineSessionTest.kt
+++ b/mobile/android/android-components/components/browser/engine-gecko/src/test/java/mozilla/components/browser/engine/gecko/GeckoEngineSessionTest.kt
@@ -349,7 +349,7 @@ class GeckoEngineSessionTest {
val observer: EngineSession.Observer = mock()
engineSession.register(observer)
- val response = WebResponse.Builder("https://download.mozilla.org/image.png")
+ val response = WebResponse.Builder("https://download.mozilla.org/image%20name.png")
.addHeader(Headers.Names.CONTENT_TYPE, "image/png")
.addHeader(Headers.Names.CONTENT_LENGTH, "42")
.skipConfirmation(true)
@@ -362,8 +362,8 @@ class GeckoEngineSessionTest {
contentDelegate.value.onExternalResponse(mock(), response)
verify(observer).onExternalResource(
- url = eq("https://download.mozilla.org/image.png"),
- fileName = eq("image.png"),
+ url = eq("https://download.mozilla.org/image%20name.png"),
+ fileName = eq("image name.png"),
contentLength = eq(42),
contentType = eq("image/png"),
cookie = eq(null),
@@ -4361,7 +4361,7 @@ class GeckoEngineSessionTest {
mockLoadRequest("sample:about", triggeredByRedirect = true),
)
- assertEquals(geckoResult!!, GeckoResult.fromValue(AllowOrDeny.ALLOW))
+ assertEquals(geckoResult!!, GeckoResult.allow())
}
@Test
diff --git a/mobile/android/android-components/components/browser/engine-gecko/src/test/java/mozilla/components/browser/engine/gecko/GeckoEngineTest.kt b/mobile/android/android-components/components/browser/engine-gecko/src/test/java/mozilla/components/browser/engine/gecko/GeckoEngineTest.kt
index 6a8ed3c330..a7b6c59954 100644
--- a/mobile/android/android-components/components/browser/engine-gecko/src/test/java/mozilla/components/browser/engine/gecko/GeckoEngineTest.kt
+++ b/mobile/android/android-components/components/browser/engine-gecko/src/test/java/mozilla/components/browser/engine/gecko/GeckoEngineTest.kt
@@ -2740,6 +2740,28 @@ class GeckoEngineTest {
}
@Test
+ fun `web extension delegate handles add-on onOptionalPermissionsChanged event`() {
+ val runtime: GeckoRuntime = mock()
+ val webExtensionController: WebExtensionController = mock()
+ whenever(runtime.webExtensionController).thenReturn(webExtensionController)
+
+ val extension = mockNativeWebExtension("test", "uri")
+ val webExtensionsDelegate: WebExtensionDelegate = mock()
+ val engine = GeckoEngine(context, runtime = runtime)
+ engine.registerWebExtensionDelegate(webExtensionsDelegate)
+
+ val geckoDelegateCaptor = argumentCaptor<WebExtensionController.AddonManagerDelegate>()
+ verify(webExtensionController).setAddonManagerDelegate(geckoDelegateCaptor.capture())
+
+ assertEquals(Unit, geckoDelegateCaptor.value.onOptionalPermissionsChanged(extension))
+ val extensionCaptor = argumentCaptor<WebExtension>()
+ verify(webExtensionsDelegate).onOptionalPermissionsChanged(extensionCaptor.capture())
+ val capturedExtension =
+ extensionCaptor.value as mozilla.components.browser.engine.gecko.webextension.GeckoWebExtension
+ assertEquals(extension, capturedExtension.nativeExtension)
+ }
+
+ @Test
fun `web extension delegate handles add-on onInstallationFailed event`() {
val runtime: GeckoRuntime = mock()
val webExtensionController: WebExtensionController = mock()
diff --git a/mobile/android/android-components/components/browser/engine-gecko/src/test/java/mozilla/components/browser/engine/gecko/GeckoEngineViewTest.kt b/mobile/android/android-components/components/browser/engine-gecko/src/test/java/mozilla/components/browser/engine/gecko/GeckoEngineViewTest.kt
index 7056187e09..13fd983483 100644
--- a/mobile/android/android-components/components/browser/engine-gecko/src/test/java/mozilla/components/browser/engine/gecko/GeckoEngineViewTest.kt
+++ b/mobile/android/android-components/components/browser/engine-gecko/src/test/java/mozilla/components/browser/engine/gecko/GeckoEngineViewTest.kt
@@ -90,15 +90,6 @@ class GeckoEngineViewTest {
shadowOf(getMainLooper()).idle()
assertNull(thumbnail)
-
- // Test GeckoView throwing an exception
- whenever(mockGeckoView.capturePixels()).thenThrow(IllegalStateException("Compositor not ready"))
-
- thumbnail = mock()
- engineView.captureThumbnail {
- thumbnail = it
- }
- assertNull(thumbnail)
}
@Test
diff --git a/mobile/android/android-components/components/browser/engine-gecko/src/test/java/mozilla/components/browser/engine/gecko/translate/GeckoTranslateSessionDelegateTest.kt b/mobile/android/android-components/components/browser/engine-gecko/src/test/java/mozilla/components/browser/engine/gecko/translate/GeckoTranslateSessionDelegateTest.kt
index 65a1c7d8f9..f0c9762fa8 100644
--- a/mobile/android/android-components/components/browser/engine-gecko/src/test/java/mozilla/components/browser/engine/gecko/translate/GeckoTranslateSessionDelegateTest.kt
+++ b/mobile/android/android-components/components/browser/engine-gecko/src/test/java/mozilla/components/browser/engine/gecko/translate/GeckoTranslateSessionDelegateTest.kt
@@ -69,13 +69,14 @@ class GeckoTranslateSessionDelegateTest {
val gecko = GeckoTranslateSessionDelegate(mockSession)
// Mock state parameters to check Gecko to AC mapping is correctly occurring
- var userLangTag = "en"
- var isDocLangTagSupported = true
- var docLangTag = "es"
- var fromLanguage = "de"
- var toLanguage = "bg"
- var error = "Error!"
- var isEngineReady = false
+ val userLangTag = "en"
+ val isDocLangTagSupported = true
+ val docLangTag = "es"
+ val fromLanguage = "de"
+ val toLanguage = "bg"
+ val error = "Error!"
+ val isEngineReady = false
+ val hasVisibleChange = true
mockSession.register(
object : EngineSession.Observer {
@@ -88,14 +89,15 @@ class GeckoTranslateSessionDelegateTest {
assertTrue(state.requestedTranslationPair?.toLanguage == toLanguage)
assertTrue(state.error == error)
assertTrue(state.isEngineReady == isEngineReady)
+ assertTrue(state.hasVisibleChange == hasVisibleChange)
}
},
)
// Mock states
- var mockDetectedLanguages = TranslationsController.SessionTranslation.DetectedLanguages(userLangTag, isDocLangTagSupported, docLangTag)
- var mockTranslationsPair = TranslationsController.SessionTranslation.TranslationPair(fromLanguage, toLanguage)
- var mockGeckoState = TranslationsController.SessionTranslation.TranslationState(mockTranslationsPair, error, mockDetectedLanguages, isEngineReady)
+ val mockDetectedLanguages = TranslationsController.SessionTranslation.DetectedLanguages(userLangTag, isDocLangTagSupported, docLangTag)
+ val mockTranslationsPair = TranslationsController.SessionTranslation.TranslationPair(fromLanguage, toLanguage)
+ val mockGeckoState = TranslationsController.SessionTranslation.TranslationState(mockTranslationsPair, error, mockDetectedLanguages, isEngineReady, hasVisibleChange)
gecko.onTranslationStateChange(mock(), mockGeckoState)
assertTrue(onTranslateStateChangeWasCalled)
diff --git a/mobile/android/android-components/components/browser/engine-system/src/main/res/raw/domain_blocklist.json b/mobile/android/android-components/components/browser/engine-system/src/main/res/raw/domain_blocklist.json
index 845571cfa0..05571a483f 100644
--- a/mobile/android/android-components/components/browser/engine-system/src/main/res/raw/domain_blocklist.json
+++ b/mobile/android/android-components/components/browser/engine-system/src/main/res/raw/domain_blocklist.json
@@ -1,11046 +1,8340 @@
{
- "license": "Copyright 2010-2019 Disconnect, Inc. / This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. / This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. / You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>.",
- "categories": {
- "Advertising": [
- {
- "2leep.com": {
- "http://2leep.com/": [
- "2leep.com"
- ]
- }
- },
- {
- "33Across": {
- "http://33across.com/": [
- "33across.com"
- ]
- }
- },
- {
- "365Media": {
- "http://365media.com/": [
- "365media.com"
- ]
- }
- },
- {
- "4INFO": {
- "http://www.4info.com/": [
- "4info.com",
- "adhaven.com"
- ]
- }
- },
- {
- "4mads": {
- "http://4mads.com/": [
- "4mads.com"
- ]
- }
- },
- {
- "Abax Interactive": {
- "http://abaxinteractive.com/": [
- "abaxinteractive.com"
- ]
- }
- },
- {
- "Accelia": {
- "http://www.accelia.net/": [
- "accelia.net",
- "durasite.net"
- ]
- }
- },
- {
- "Accordant Media": {
- "http://www.accordantmedia.com/": [
- "accordantmedia.com"
- ]
- }
- },
- {
- "Acquisio": {
- "http://www.acquisio.com/": [
- "acquisio.com",
- "clickequations.net"
- ]
- }
- },
- {
- "Actisens": {
- "http://www.actisens.com/": [
- "actisens.com",
- "gestionpub.com"
- ]
- }
- },
- {
- "ActiveConversion": {
- "http://www.activeconversion.com/": [
- "activeconversion.com",
- "activemeter.com"
- ]
- }
- },
- {
- "Act-On": {
- "http://www.act-on.com/": [
- "act-on.com",
- "actonsoftware.com"
- ]
- }
- },
- {
- "Acuity": {
- "http://www.acuity.com/": [
- "acuity.com",
- "acuityads.com",
- "acuityplatform.com"
- ]
- }
- },
- {
- "AD2ONE": {
- "http://www.ad2onegroup.com/": [
- "ad2onegroup.com"
- ]
- }
- },
- {
- "Ad4Game": {
- "http://ad4game.com/": [
- "ad4game.com"
- ]
- }
- },
- {
- "ad6media": {
- "http://www.ad6media.fr/": [
- "ad6media.fr"
- ]
- }
- },
- {
- "Adabra": {
- "https://www.adabra.com/": [
- "adabra.com"
- ]
- }
- },
- {
- "Adality": {
- "http://adality.de/": [
- "adality.de",
- "adrtx.net"
- ]
- }
- },
- {
- "AdaptiveAds": {
- "http://www.adaptiveads.com/": [
- "adaptiveads.com"
- ]
- }
- },
- {
- "Adaptly": {
- "http://adaptly.com/": [
- "adaptly.com"
- ]
- }
- },
- {
- "Adara Media": {
- "http://www.adaramedia.com/": [
- "adaramedia.com",
- "opinmind.com",
- "yieldoptimizer.com"
- ]
- }
- },
- {
- "Adatus": {
- "http://www.adatus.com/": [
- "adatus.com"
- ]
- }
- },
- {
- "Adbot": {
- "https://adbot.tw/": [
- "adbot.tw"
- ]
- }
- },
- {
- "Adbrain": {
- "http://www.adbrain.com/": [
- "adbrain.com",
- "adbrn.com"
- ]
- }
- },
- {
- "adBrite": {
- "http://www.adbrite.com/": [
- "adbrite.com"
- ]
- }
- },
- {
- "Adbroker.de": {
- "http://adbroker.de/": [
- "adbroker.de"
- ]
- }
- },
- {
- "Adchemy": {
- "http://www.adchemy.com/": [
- "adchemy.com"
- ]
- }
- },
- {
- "AdCirrus": {
- "http://adcirrus.com/": [
- "adcirrus.com"
- ]
- }
- },
- {
- "Ad Decisive": {
- "http://www.addecisive.com/": [
- "a2dfp.net",
- "addecisive.com"
- ]
- }
- },
- {
- "addGloo": {
- "http://www.addgloo.com/": [
- "addgloo.com"
- ]
- }
- },
- {
- "Addvantage Media": {
- "http://www.addvantagemedia.com/": [
- "addvantagemedia.com"
- ]
- }
- },
- {
- "Ad Dynamo": {
- "http://www.addynamo.com/": [
- "addynamo.com",
- "addynamo.net"
- ]
- }
- },
- {
- "Adelphic": {
- "https://adelphic.com/": [
- "adelphic.com",
- "ipredictive.com"
- ]
- }
- },
- {
- "AdEngage": {
- "http://adengage.com/": [
- "adengage.com"
- ]
- }
- },
- {
- "AD Europe": {
- "http://www.adeurope.com/": [
- "adeurope.com"
- ]
- }
- },
- {
- "AdExtent": {
- "http://www.adextent.com/": [
- "adextent.com"
- ]
- }
- },
- {
- "AdF.ly": {
- "http://adf.ly/": [
- "adf.ly"
- ]
- }
- },
- {
- "Adfonic": {
- "http://adfonic.com/": [
- "adfonic.com"
- ]
- }
- },
- {
- "Adforge": {
- "http://adforgeinc.com/": [
- "adforgeinc.com"
- ]
- }
- },
- {
- "Adform": {
- "http://www.adform.com/": [
- "adform.com",
- "adform.net",
- "adformdsp.net"
- ]
- }
- },
- {
- "AdFox": {
- "http://adfox.ru/": [
- "adfox.ru"
- ]
- }
- },
- {
- "AdFrontiers": {
- "http://www.adfrontiers.com/": [
- "adfrontiers.com"
- ]
- }
- },
- {
- "Adfunky": {
- "http://www.adfunky.com/": [
- "adfunky.com",
- "adfunkyserver.com"
- ]
- }
- },
- {
- "Adfusion": {
- "http://www.adfusion.com/": [
- "adfusion.com"
- ]
- }
- },
- {
- "AdGainerSolutions": {
- "http://adgainersolutions.com/adgainer/": [
- "adgainersolutions.com"
- ]
- }
- },
- {
- "AdGent Digital": {
- "http://www.adgentdigital.com/": [
- "adgentdigital.com",
- "shorttailmedia.com"
- ]
- }
- },
- {
- "AdGibbon": {
- "http://www.adgibbon.com/": [
- "adgibbon.com"
- ]
- }
- },
- {
- "Adglare": {
- "https://www.adglare.com/": [
- "adglare.com",
- "adglare.net"
- ]
- }
- },
- {
- "adhood": {
- "http://www.adhood.com/": [
- "adhood.com"
- ]
- }
- },
- {
- "Adiant": {
- "http://www.adiant.com/": [
- "adblade.com",
- "adiant.com"
- ]
- }
- },
- {
- "AdInsight": {
- "http://www.adinsight.com/": [
- "adinsight.com",
- "adinsight.eu"
- ]
- }
- },
- {
- "AdIQuity": {
- "http://adiquity.com/": [
- "adiquity.com"
- ]
- }
- },
- {
- "ADITION": {
- "http://www.adition.com/": [
- "adition.com"
- ]
- }
- },
- {
- "AdJug": {
- "http://www.adjug.com/": [
- "adjug.com"
- ]
- }
- },
- {
- "AdJuggler": {
- "http://www.adjuggler.com/": [
- "adjuggler.com",
- "adjuggler.net"
- ]
- }
- },
- {
- "Adjust": {
- "https://adjust.com": [
- "adjust.com"
- ]
- }
- },
- {
- "AdKeeper": {
- "http://www.adkeeper.com/": [
- "adkeeper.com",
- "akncdn.com"
- ]
- }
- },
- {
- "AdKernel": {
- "http://adkernel.com": [
- "adkernel.com"
- ]
- }
- },
- {
- "Ad Knife": {
- "http://static.adknife.com/": [
- "adknife.com"
- ]
- }
- },
- {
- "Adknowledge": {
- "http://www.adknowledge.com/": [
- "adknowledge.com",
- "adparlor.com",
- "bidsystem.com",
- "cubics.com",
- "lookery.com"
- ]
- }
- },
- {
- "AdLantis": {
- "http://www.adlantis.jp/": [
- "adimg.net",
- "adlantis.jp"
- ]
- }
- },
- {
- "AdLeave": {
- "http://www.adleave.com/": [
- "adleave.com"
- ]
- }
- },
- {
- "Adlibrium": {
- "http://www.adlibrium.com/": [
- "adlibrium.com"
- ]
- }
- },
- {
- "Adlucent": {
- "http://adlucent.com": [
- "adlucent.com"
- ]
- }
- },
- {
- "Ad Magnet": {
- "http://www.admagnet.com/": [
- "admagnet.com",
- "admagnet.net"
- ]
- }
- },
- {
- "Admarketplace": {
- "http://www.admarketplace.com/": [
- "admarketplace.com",
- "admarketplace.net",
- "ampxchange.com"
- ]
- }
- },
- {
- "AdMarvel": {
- "http://www.admarvel.com/": [
- "admarvel.com"
- ]
- }
- },
- {
- "AdMatrix": {
- "http://www.admatrix.jp/": [
- "admatrix.jp"
- ]
- }
- },
- {
- "AdMaven": {
- "https://ad-maven.com/": [
- "ad-maven.com",
- "agreensdistra.info",
- "boudja.com",
- "rensovetors.info",
- "wrethicap.info"
- ]
- }
- },
- {
- "AdMaximizer Network": {
- "http://admaximizer.com/": [
- "admaximizer.com"
- ]
- }
- },
- {
- "AdMedia": {
- "http://www.admedia.com/": [
- "admedia.com"
- ]
- }
- },
- {
- "Admeta": {
- "http://www.admeta.com/": [
- "admeta.com",
- "atemda.com"
- ]
- }
- },
- {
- "Admicro": {
- "http://www.admicro.vn/": [
- "admicro.vn",
- "vcmedia.vn"
- ]
- }
- },
- {
- "Admixer": {
- "https://admixer.co.kr/main": [
- "admixer.co.kr"
- ]
- }
- },
- {
- "Admized": {
- "http://www.admized.com/": [
- "admized.com"
- ]
- }
- },
- {
- "Admobile": {
- "http://admobile.com/": [
- "admobile.com"
- ]
- }
- },
- {
- "Admotion": {
- "http://www.admotion.com/": [
- "admotion.com",
- "nspmotion.com"
- ]
- }
- },
- {
- "Adnetik": {
- "http://adnetik.com/": [
- "adnetik.com",
- "wtp101.com"
- ]
- }
- },
- {
- "AdNetwork.net": {
- "http://www.adnetwork.net/": [
- "adnetwork.net"
- ]
- }
- },
- {
- "Adnium": {
- "https://adnium.com": [
- "adnium.com"
- ]
- }
- },
- {
- "adnologies": {
- "http://www.adnologies.com/": [
- "adnologies.com",
- "heias.com"
- ]
- }
- },
- {
- "Adobe": {
- "http://www.adobe.com/": [
- "2o7.net",
- "auditude.com",
- "demdex.com",
- "demdex.net",
- "dmtracker.com",
- "efrontier.com",
- "everestads.net",
- "everestjs.net",
- "everesttech.net",
- "hitbox.com",
- "omniture.com",
- "omtrdc.net",
- "touchclarity.com"
- ]
- }
- },
- {
- "AdOcean": {
- "http://www.adocean-global.com/": [
- "adocean-global.com",
- "adocean.pl"
- ]
- }
- },
- {
- "Adometry": {
- "http://www.adometry.com/": [
- "adometry.com",
- "dmtry.com"
- ]
- }
- },
- {
- "Adomik": {
- "http://www.adomik.com/": [
- "adomik.com"
- ]
- }
- },
- {
- "AdOnion": {
- "http://www.adonion.com/": [
- "adonion.com"
- ]
- }
- },
- {
- "Adorika": {
- "http://www.clickotmedia.com/": [
- "clickotmedia.com"
- ]
- }
- },
- {
- "Adotmob": {
- "https://adotmob.com/": [
- "adotmob.com"
- ]
- }
- },
- {
- "ADP Dealer Services": {
- "http://www.adpdealerservices.com/": [
- "admission.net",
- "adpdealerservices.com",
- "cobalt.com"
- ]
- }
- },
- {
- "ad pepper media": {
- "http://www.adpepper.us/": [
- "adpepper.com",
- "adpepper.us"
- ]
- }
- },
- {
- "AdPerfect": {
- "http://www.adperfect.com/": [
- "adperfect.com"
- ]
- }
- },
- {
- "Adperium": {
- "http://www.adperium.com/": [
- "adperium.com"
- ]
- }
- },
- {
- "Adpersia": {
- "http://www.adpersia.com/": [
- "adpersia.com"
- ]
- }
- },
- {
- "adPrecision": {
- "http://adprecision.net/": [
- "adprs.net",
- "aprecision.net"
- ]
- }
- },
- {
- "AdPredictive": {
- "http://www.adpredictive.com/": [
- "adpredictive.com"
- ]
- }
- },
- {
- "AdReactor": {
- "http://www.adreactor.com/": [
- "adreactor.com"
- ]
- }
- },
- {
- "AdReady": {
- "http://www.adready.com/": [
- "adready.com",
- "adreadytractions.com"
- ]
- }
- },
- {
- "AdRevolution": {
- "http://adrevolution.com/": [
- "adrevolution.com"
- ]
- }
- },
- {
- "AdRiver": {
- "http://adriver.ru/": [
- "adriver.ru"
- ]
- }
- },
- {
- "adrolays": {
- "http://adrolays.com/": [
- "adrolays.com",
- "adrolays.de"
- ]
- }
- },
- {
- "AdRoll": {
- "http://www.adroll.com/": [
- "adroll.com"
- ]
- }
- },
- {
- "adscale": {
- "http://www.adscale.de/": [
- "adscale.de"
- ]
- }
- },
- {
- "Adscience": {
- "https://www.adscience.nl/": [
- "adscience.nl"
- ]
- }
- },
- {
- "AdServerPub": {
- "http://www.adserverpub.com/": [
- "adserverpub.com"
- ]
- }
- },
- {
- "AdShuffle": {
- "http://www.adshuffle.com/": [
- "adshuffle.com"
- ]
- }
- },
- {
- "AdSide": {
- "http://www.adside.com/": [
- "adside.com",
- "doclix.com"
- ]
- }
- },
- {
- "AdSpeed": {
- "http://www.adspeed.com/": [
- "adspeed.com",
- "adspeed.net"
- ]
- }
- },
- {
- "Adsperity": {
- "https://www.adsperity.com/": [
- "adsperity.com"
- ]
- }
- },
- {
- "AdSpirit": {
- "http://www.adspirit.de/": [
- "adspirit.com",
- "adspirit.de",
- "adspirit.net"
- ]
- }
- },
- {
- "Adsrevenue.net": {
- "http://adsrevenue.net/": [
- "adsrevenue.net"
- ]
- }
- },
- {
- "AdStir": {
- "https://en.ad-stir.com/": [
- "ad-stir.com"
- ]
- }
- },
- {
- "AdsTours": {
- "http://www.adstours.com/": [
- "adstours.com",
- "clickintext.net"
- ]
- }
- },
- {
- "Adsty": {
- "http://adsty.com/": [
- "adsty.com",
- "adx1.com"
- ]
- }
- },
- {
- "Adsupply": {
- "http://www.adsupply.com/": [
- "4dsply.com",
- "adsupply.com"
- ]
- }
- },
- {
- "Adswizz": {
- "http://adswizz.com": [
- "adswizz.com"
- ]
- }
- },
- {
- "ADTECH": {
- "http://www.adtech.com/": [
- "adtech.com",
- "adtech.de",
- "adtechus.com"
- ]
- }
- },
- {
- "Adtegrity.com": {
- "http://www.adtegrity.com/": [
- "adtegrity.com",
- "adtegrity.net"
- ]
- }
- },
- {
- "ADTELLIGENCE": {
- "http://www.adtelligence.de/": [
- "adtelligence.de"
- ]
- }
- },
- {
- "Adthink": {
- "https://adthink.com/": [
- "adthink.com",
- "audienceinsights.net"
- ]
- }
- },
- {
- "AdTiger": {
- "http://www.adtiger.de/": [
- "adtiger.de"
- ]
- }
- },
- {
- "AdTruth": {
- "http://adtruth.com/": [
- "adtruth.com"
- ]
- }
- },
- {
- "Adult AdWorld": {
- "http://adultadworld.com/": [
- "adultadworld.com"
- ]
- }
- },
- {
- "Adultmoda": {
- "http://www.adultmoda.com/": [
- "adultmoda.com"
- ]
- }
- },
- {
- "Adventive": {
- "http://adventive.com/": [
- "adventive.com"
- ]
- }
- },
- {
- "Adverline": {
- "http://www.adverline.com/": [
- "adnext.fr",
- "adverline.com"
- ]
- }
- },
- {
- "Adversal.com": {
- "http://www.adversal.com/": [
- "adv-adserver.com",
- "adversal.com"
- ]
- }
- },
- {
- "Adverticum": {
- "http://www.adverticum.com/": [
- "adsmart.com",
- "adverticum.com",
- "adverticum.net"
- ]
- }
- },
- {
- "Advertise.com": {
- "http://www.advertise.com/": [
- "advertise.com"
- ]
- }
- },
- {
- "AdvertiseSpace": {
- "http://www.advertisespace.com/": [
- "advertisespace.com"
- ]
- }
- },
- {
- "Advert Stream": {
- "http://www.advertstream.com/": [
- "advertstream.com"
- ]
- }
- },
- {
- "Advisor Media": {
- "http://advisormedia.cz/": [
- "advisormedia.cz"
- ]
- }
- },
- {
- "Adworx": {
- "http://adworx.at/": [
- "adworx.at",
- "adworx.be",
- "adworx.nl"
- ]
- }
- },
- {
- "AdXpansion": {
- "http://www.adxpansion.com/": [
- "adxpansion.com"
- ]
- }
- },
- {
- "Adxvalue": {
- "http://adxvalue.com/": [
- "adxvalue.com",
- "adxvalue.de"
- ]
- }
- },
- {
- "adyard": {
- "http://adyard.de/": [
- "adyard.de"
- ]
- }
- },
- {
- "AdYield": {
- "http://www.adyield.com/": [
- "adxyield.com",
- "adyield.com"
- ]
- }
- },
- {
- "AdYouLike": {
- "https://www.adyoulike.com/": [
- "adyoulike.com",
- "omnitagjs.com",
- "pulpix.com"
- ]
- }
- },
- {
- "ADZ": {
- "http://www.adzcentral.com/": [
- "adzcentral.com"
- ]
- }
- },
- {
- "Adzerk": {
- "http://www.adzerk.com/": [
- "adzerk.com",
- "adzerk.net"
- ]
- }
- },
- {
- "adzly": {
- "http://www.adzly.com/": [
- "adzly.com"
- ]
- }
- },
- {
- "Aegis Group": {
- "http://www.aemedia.com/": [
- "aemedia.com",
- "bluestreak.com"
- ]
- }
- },
- {
- "AERIFY MEDIA": {
- "http://aerifymedia.com/": [
- "aerifymedia.com",
- "anonymous-media.com"
- ]
- }
- },
- {
- "Affectv": {
- "http://affectv.co.uk/": [
- "affectv.co.uk"
- ]
- }
- },
- {
- "affilinet": {
- "http://www.affili.net/": [
- "affili.net",
- "affilinet-inside.de",
- "banner-rotation.com",
- "successfultogether.co.uk"
- ]
- }
- },
- {
- "Affine": {
- "http://www.affine.tv/": [
- "affine.tv",
- "affinesystems.com"
- ]
- }
- },
- {
- "Affinity": {
- "http://www.affinity.com/": [
- "affinity.com"
- ]
- }
- },
- {
- "AfterDownload": {
- "http://www.afterdownload.com/": [
- "afdads.com",
- "afterdownload.com"
- ]
- }
- },
- {
- "Aim4Media": {
- "http://aim4media.com/": [
- "aim4media.com"
- ]
- }
- },
- {
- "Airpush": {
- "http://www.airpush.com/": [
- "airpush.com"
- ]
- }
- },
- {
- "AK": {
- "http://www.aggregateknowledge.com/": [
- "aggregateknowledge.com",
- "agkn.com"
- ]
- }
- },
- {
- "Akamai": {
- "http://www.akamai.com/": [
- "imiclk.com"
- ]
- }
- },
- {
- "Albacross": {
- "https://albacross.com": [
- "albacross.com"
- ]
- }
- },
- {
- "AllStarMediaGroup": {
- "http://allstarmediagroup.com/": [
- "allstarmediagroup.com"
- ]
- }
- },
- {
- "Aloodo": {
- "https://aloodo.com/": [
- "aloodo.com"
- ]
- }
- },
- {
- "AlterGeo": {
- "http://altergeo.ru/": [
- "altergeo.ru"
- ]
- }
- },
- {
- "Amazon.com": {
- "http://www.amazon.com/": [
- "amazon-adsystem.com",
- "amazon.ca",
- "amazon.co.jp",
- "amazon.co.uk",
- "amazon.de",
- "amazon.es",
- "amazon.fr",
- "amazon.it",
- "assoc-amazon.com"
- ]
- }
- },
- {
- "Ambient Digital": {
- "http://ambientdigital.com.vn/": [
- "adnetwork.vn",
- "ambientdigital.com.vn"
- ]
- }
- },
- {
- "Amobee": {
- "http://amobee.com/": [
- "adconion.com",
- "amgdgt.com",
- "amobee.com",
- "euroclick.com",
- "smartclip.com",
- "turn.com"
- ]
- }
- },
- {
- "AndBeyond": {
- "http://andbeyond.media/": [
- "andbeyond.media"
- ]
- }
- },
- {
- "Answers.com": {
- "http://www.answers.com/": [
- "dsply.com"
- ]
- }
- },
- {
- "AOL": {
- "http://www.aol.com/": [
- "adsonar.com",
- "adtechjp.com",
- "advertising.com",
- "aolcloud.net",
- "atwola.com",
- "leadback.com",
- "tacoda.net",
- "vidible.tv"
- ]
- }
- },
- {
- "AppCast": {
- "https://appcast.io/": [
- "appcast.io"
- ]
- }
- },
- {
- "Appenda": {
- "http://www.appenda.com/": [
- "appenda.com"
- ]
- }
- },
- {
- "AppFlood": {
- "http://appflood.com/": [
- "appflood.com"
- ]
- }
- },
- {
- "Appier": {
- "http://appier.com/": [
- "appier.com"
- ]
- }
- },
- {
- "Applifier": {
- "http://www.applifier.com/": [
- "applifier.com"
- ]
- }
- },
- {
- "Applovin": {
- "http://www.applovin.com/": [
- "applovin.com"
- ]
- }
- },
- {
- "AppNexus": {
- "http://www.appnexus.com/": [
- "adlantic.nl",
- "adnxs.com",
- "adrdgt.com",
- "alenty.com",
- "appnexus.com"
- ]
- }
- },
- {
- "AppsFlyer": {
- "http://appsflyer.com/": [
- "appsflyer.com"
- ]
- }
- },
- {
- "appssavvy": {
- "http://appssavvy.com/": [
- "appssavvy.com"
- ]
- }
- },
- {
- "Arkwrights Homebrew": {
- "http://www.arkwrightshomebrew.com/": [
- "arkwrightshomebrew.com",
- "ctasnet.com"
- ]
- }
- },
- {
- "AT Internet": {
- "http://www.atinternet.com/": [
- "hit-parade.com"
- ]
- }
- },
- {
- "ATN": {
- "http://affiliatetracking.com/": [
- "affiliatetracking.com"
- ]
- }
- },
- {
- "Atoomic.com": {
- "http://www.atoomic.com/": [
- "atoomic.com"
- ]
- }
- },
- {
- "Atrinsic": {
- "http://atrinsic.com/": [
- "atrinsic.com"
- ]
- }
- },
- {
- "AT&T": {
- "http://www.att.com/": [
- "att.com",
- "yp.com"
- ]
- }
- },
- {
- "Audience2Media": {
- "http://www.audience2media.com/": [
- "audience2media.com"
- ]
- }
- },
- {
- "Audience Ad Network": {
- "http://audienceadnetwork.com/": [
- "audienceadnetwork.com"
- ]
- }
- },
- {
- "AudienceScience": {
- "http://www.audiencescience.com/": [
- "audiencescience.com",
- "revsci.net",
- "targetingmarketplace.com",
- "wunderloop.net"
- ]
- }
- },
- {
- "Augme": {
- "http://www.augme.com/": [
- "augme.com",
- "hipcricket.com"
- ]
- }
- },
- {
- "Augur": {
- "http://www.augur.io/": [
- "augur.io"
- ]
- }
- },
- {
- "AUTOCENTRE.UA": {
- "http://www.autocentre.ua/": [
- "am.ua",
- "autocentre.ua"
- ]
- }
- },
- {
- "Automattic": {
- "http://automattic.com/": [
- "pubmine.com"
- ]
- }
- },
- {
- "Avalanchers": {
- "http://www.avalanchers.com/": [
- "avalanchers.com"
- ]
- }
- },
- {
- "AvantLink": {
- "http://www.avantlink.com/": [
- "avantlink.com"
- ]
- }
- },
- {
- "Avocet": {
- "https://avocet.io/": [
- "avocet.io"
- ]
- }
- },
- {
- "Avsads": {
- "http://avsads.com/": [
- "avsads.com"
- ]
- }
- },
- {
- "AWeber": {
- "http://www.aweber.com/": [
- "aweber.com"
- ]
- }
- },
- {
- "Awin": {
- "http://www.awin.com/": [
- "digitalwindow.com",
- "dwin1.com",
- "perfiliate.com"
- ]
- }
- },
- {
- "Azet": {
- "http://mediaimpact.sk/": [
- "azetklik.sk",
- "rsz.sk"
- ]
- }
- },
- {
- "BackBeat Media": {
- "http://www.backbeatmedia.com/": [
- "backbeatmedia.com"
- ]
- }
- },
- {
- "Bannerconnect": {
- "http://www.bannerconnect.net/": [
- "bannerconnect.net"
- ]
- }
- },
- {
- "Barilliance": {
- "http://www.barilliance.com/": [
- "barilliance.com"
- ]
- }
- },
- {
- "BaronsNetworks": {
- "http://baronsoffers.com/": [
- "baronsoffers.com"
- ]
- }
- },
- {
- "Batanga Network": {
- "http://www.batanganetwork.com/": [
- "batanga.com",
- "batanganetwork.com"
- ]
- }
- },
- {
- "BeachFront": {
- "http://beachfront.com/": [
- "beachfront.com"
- ]
- }
- },
- {
- "Beanstock Media": {
- "http://www.beanstockmedia.com/": [
- "beanstockmedia.com"
- ]
- }
- },
- {
- "beencounter": {
- "http://www.beencounter.com/": [
- "beencounter.com"
- ]
- }
- },
- {
- "Begun": {
- "http://www.begun.ru/": [
- "begun.ru"
- ]
- }
- },
- {
- "belboon": {
- "http://www.belboon.com/": [
- "adbutler.de",
- "belboon.com"
- ]
- }
- },
- {
- "Betgenius": {
- "http://www.betgenius.com/": [
- "betgenius.com",
- "connextra.com"
- ]
- }
- },
- {
- "BetweenDigital": {
- "http://betweendigital.com": [
- "betweendigital.com"
- ]
- }
- },
- {
- "Bidfluence": {
- "https://www.bidfluence.com/": [
- "bidfluence.com"
- ]
- }
- },
- {
- "Bidr": {
- "http://bidr.io": [
- "bidr.io"
- ]
- }
- },
- {
- "BidSwitch": {
- "https://www.bidswitch.com/": [
- "bidswitch.net",
- "mfadsrvr.com"
- ]
- }
- },
- {
- "Bidtellect": {
- "https://www.bidtellect.com/": [
- "bidtellect.com",
- "bttrack.com"
- ]
- }
- },
- {
- "BidVertiser": {
- "http://www.bidvertiser.com/": [
- "bidvertiser.com"
- ]
- }
- },
- {
- "BigClick": {
- "http://bigclick.me/": [
- "bgclck.me",
- "xcvgdf.party"
- ]
- }
- },
- {
- "bigmirnet": {
- "http://www.bigmir.net/": [
- "bigmir.net"
- ]
- }
- },
- {
- "BinLayer": {
- "http://binlayer.com/": [
- "binlayer.com"
- ]
- }
- },
- {
- "Bitcoin Plus": {
- "http://www.bitcoinplus.com/": [
- "bitcoinplus.com"
- ]
- }
- },
- {
- "BitMedia": {
- "https://bitmedia.io/": [
- "bitmedia.io"
- ]
- }
- },
- {
- "BittAds": {
- "http://www.bittads.com/": [
- "bittads.com"
- ]
- }
- },
- {
- "Bizo": {
- "http://www.bizo.com/": [
- "bizo.com",
- "bizographics.com"
- ]
- }
- },
- {
- "Black Label Ads": {
- "http://www.blacklabelads.com/": [
- "blacklabelads.com"
- ]
- }
- },
- {
- "BlogCatalog": {
- "http://www.blogcatalog.com/": [
- "blogcatalog.com"
- ]
- }
- },
- {
- "BlogFrog": {
- "http://theblogfrog.com/": [
- "theblogfrog.com"
- ]
- }
- },
- {
- "BlogHer": {
- "http://www.blogher.com/": [
- "blogher.com",
- "blogherads.com"
- ]
- }
- },
- {
- "BlogRollr": {
- "http://blogrollr.com/": [
- "blogrollr.com"
- ]
- }
- },
- {
- "BLOOM Digital Platforms": {
- "http://bloom-hq.com/": [
- "adgear.com",
- "adgrx.com",
- "bloom-hq.com"
- ]
- }
- },
- {
- "BlueKai": {
- "http://www.bluekai.com/": [
- "bkrtx.com",
- "bluekai.com",
- "tracksimple.com"
- ]
- }
- },
- {
- "Blu Trumpet": {
- "http://www.blutrumpet.com/": [
- "blutrumpet.com"
- ]
- }
- },
- {
- "Boo-Box": {
- "http://boo-box.com/": [
- "boo-box.com"
- ]
- }
- },
- {
- "BoostBox": {
- "https://www.boostbox.com.br/": [
- "boostbox.com.br"
- ]
- }
- },
- {
- "Bouncex": {
- "https://www.bouncex.com/": [
- "bounceexchange.com",
- "bouncex.com",
- "bouncex.net"
- ]
- }
- },
- {
- "Brainient": {
- "http://brainient.com/": [
- "brainient.com"
- ]
- }
- },
- {
- "Brand Affinity Technologies": {
- "http://www.brandaffinity.net/": [
- "brandaffinity.net"
- ]
- }
- },
- {
- "Brandcrumb": {
- "http://www.brandcrumb.com": [
- "brandcrumb.com"
- ]
- }
- },
- {
- "Brand.net": {
- "http://www.brand.net/": [
- "brand.net"
- ]
- }
- },
- {
- "Brandscreen": {
- "http://www.brandscreen.com/": [
- "brandscreen.com",
- "rtbidder.net"
- ]
- }
- },
- {
- "BreakTime": {
- "https://www.breaktime.com.tw/": [
- "breaktime.com.tw"
- ]
- }
- },
- {
- "BrightRoll": {
- "http://www.brightroll.com/": [
- "brightroll.com",
- "btrll.com"
- ]
- }
- },
- {
- "BrightTag": {
- "http://www.brighttag.com/": [
- "brighttag.com",
- "btstatic.com",
- "thebrighttag.com"
- ]
- }
- },
- {
- "Brilig": {
- "http://www.brilig.com/": [
- "brilig.com"
- ]
- }
- },
- {
- "BuckSense": {
- "http://www.bucksense.com": [
- "bucksense.com"
- ]
- }
- },
- {
- "Burstly": {
- "http://www.burstly.com/": [
- "burstly.com"
- ]
- }
- },
- {
- "Burst Media": {
- "http://www.burstmedia.com/": [
- "burstbeacon.com",
- "burstdirectads.com",
- "burstmedia.com",
- "burstnet.com",
- "giantrealm.com"
- ]
- }
- },
- {
- "BusinessOnline": {
- "http://www.businessol.com/": [
- "businessol.com"
- ]
- }
- },
- {
- "Button": {
- "https://www.usebutton.com": [
- "usebutton.com"
- ]
- }
- },
- {
- "BuySellAds": {
- "http://buysellads.com/": [
- "beaconads.com",
- "buysellads.com"
- ]
- }
- },
- {
- "Buysight": {
- "http://www.buysight.com/": [
- "buysight.com",
- "permuto.com",
- "pulsemgr.com"
- ]
- }
- },
- {
- "BuzzParadise": {
- "http://www.buzzparadise.com/": [
- "buzzparadise.com"
- ]
- }
- },
- {
- "BV! MEDIA": {
- "http://www.bvmedia.ca/": [
- "bvmedia.ca",
- "networldmedia.com",
- "networldmedia.net"
- ]
- }
- },
- {
- "c1exchange": {
- "https://c1exchange.com/": [
- "c1exchange.com"
- ]
- }
- },
- {
- "C3 Metrics": {
- "http://c3metrics.com/": [
- "attributionmodel.com",
- "c3metrics.com",
- "c3tag.com"
- ]
- }
- },
- {
- "Cadreon": {
- "http://www.cadreon.com/": [
- "cadreon.com"
- ]
- }
- },
- {
- "CampaignGrid": {
- "http://www.campaigngrid.com/": [
- "campaigngrid.com"
- ]
- }
- },
- {
- "CAPITALDATA": {
- "http://www.capitaldata.fr/": [
- "capitaldata.fr"
- ]
- }
- },
- {
- "Carambola": {
- "https://www.carambola.com/": [
- "carambo.la"
- ]
- }
- },
- {
- "Caraytech": {
- "http://www.caraytech.com.ar/": [
- "caraytech.com.ar",
- "e-planning.net"
- ]
- }
- },
- {
- "Cart.ro": {
- "http://www.cart.ro/": [
- "cart.ro",
- "statistics.ro"
- ]
- }
- },
- {
- "CartsGuru": {
- "https://carts.guru/": [
- "carts.guru"
- ]
- }
- },
- {
- "Casale Media": {
- "http://www.casalemedia.com/": [
- "casalemedia.com",
- "medianet.com"
- ]
- }
- },
- {
- "CBproADS": {
- "http://www.cbproads.com/": [
- "cbproads.com"
- ]
- }
- },
- {
- "Cedato": {
- "https://www.cedato.com/": [
- "cedato.com"
- ]
- }
- },
- {
- "Chango": {
- "http://www.chango.com/": [
- "chango.ca",
- "chango.com"
- ]
- }
- },
- {
- "ChannelAdvisor": {
- "http://www.channeladvisor.com/": [
- "channeladvisor.com",
- "searchmarketing.com"
- ]
- }
- },
- {
- "Channel Intelligence": {
- "http://www.channelintelligence.com/": [
- "channelintelligence.com"
- ]
- }
- },
- {
- "Chartboost": {
- "https://www.chartboost.com/": [
- "chartboost.com"
- ]
- }
- },
- {
- "CheckM8": {
- "http://www.checkm8.com/": [
- "checkm8.com"
- ]
- }
- },
- {
- "Chitika": {
- "http://chitika.com/": [
- "chitika.com",
- "chitika.net"
- ]
- }
- },
- {
- "ChoiceStream": {
- "http://www.choicestream.com/": [
- "choicestream.com"
- ]
- }
- },
- {
- "ClearLink": {
- "https://www.clearlink.com/": [
- "clearlink.com"
- ]
- }
- },
- {
- "ClearSaleing": {
- "http://www.clearsaleing.com/": [
- "clearsaleing.com",
- "csdata1.com",
- "csdata2.com",
- "csdata3.com"
- ]
- }
- },
- {
- "Clearsearch Media": {
- "http://www.clearsearchmedia.com/": [
- "clearsearchmedia.com",
- "csm-secure.com"
- ]
- }
- },
- {
- "ClearSight Interactive": {
- "http://www.clearsightinteractive.com/": [
- "clearsightinteractive.com",
- "csi-tracking.com"
- ]
- }
- },
- {
- "ClickAider": {
- "http://clickaider.com/": [
- "clickaider.com"
- ]
- }
- },
- {
- "Clickayab": {
- "http://www.clickyab.com": [
- "clickyab.com"
- ]
- }
- },
- {
- "Clickbooth": {
- "http://www.clickbooth.com/": [
- "adtoll.com",
- "clickbooth.com"
- ]
- }
- },
- {
- "ClickDimensions": {
- "http://www.clickdimensions.com/": [
- "clickdimensions.com"
- ]
- }
- },
- {
- "ClickDistrict": {
- "http://www.clickdistrict.com/": [
- "clickdistrict.com",
- "creative-serving.com"
- ]
- }
- },
- {
- "ClickFrog": {
- "https://clickfrog.ru/": [
- "bashirian.biz",
- "buckridge.link",
- "clickfrog.ru",
- "franecki.net",
- "quitzon.net",
- "reichelcormier.bid",
- "wisokykulas.bid"
- ]
- }
- },
- {
- "ClickFuel": {
- "http://clickfuel.com/": [
- "conversiondashboard.com"
- ]
- }
- },
- {
- "ClickInc": {
- "http://www.clickinc.com/": [
- "clickinc.com"
- ]
- }
- },
- {
- "Clicksor": {
- "http://www.clicksor.com/": [
- "clicksor.com",
- "clicksor.net"
- ]
- }
- },
- {
- "Clickwinks": {
- "http://www.clickwinks.com/": [
- "clickwinks.com"
- ]
- }
- },
- {
- "ClicManager": {
- "http://www.clicmanager.fr/": [
- "clicmanager.fr"
- ]
- }
- },
- {
- "Clixtell": {
- "https://www.clixtell.com/": [
- "clixtell.com"
- ]
- }
- },
- {
- "Clove Network": {
- "http://www.clovenetwork.com/": [
- "clovenetwork.com"
- ]
- }
- },
- {
- "Cognitive Match": {
- "http://www.cognitivematch.com/": [
- "cmads.com.tw",
- "cmadsasia.com",
- "cmadseu.com",
- "cmmeglobal.com",
- "cognitivematch.com"
- ]
- }
- },
- {
- "Collective": {
- "http://collective.com/": [
- "collective-media.net",
- "collective.com",
- "oggifinogi.com",
- "tumri.com",
- "tumri.net",
- "yt1187.net"
- ]
- }
- },
- {
- "Commission Junction": {
- "http://www.cj.com/": [
- "apmebf.com",
- "awltovhc.com",
- "cj.com",
- "ftjcfx.com",
- "kcdwa.com",
- "qksz.com",
- "qksz.net",
- "tqlkg.com",
- "yceml.net"
- ]
- }
- },
- {
- "Communicator Corp": {
- "http://www.communicatorcorp.com/": [
- "communicatorcorp.com"
- ]
- }
- },
- {
- "Compass Labs": {
- "http://compasslabs.com/": [
- "compasslabs.com"
- ]
- }
- },
- {
- "Complex Media": {
- "http://www.complexmedianetwork.com/": [
- "complex.com",
- "complexmedianetwork.com"
- ]
- }
- },
- {
- "comScore": {
- "http://www.comscore.com/": [
- "adxpose.com",
- "proxilinks.com",
- "proximic.com",
- "proximic.net"
- ]
- }
- },
- {
- "Connatix.com": {
- "https://connatix.com/": [
- "connatix.com"
- ]
- }
- },
- {
- "Connexity": {
- "http://www.connexity.com/": [
- "pricegrabber.com"
- ]
- }
- },
- {
- "Consilium Media": {
- "http://www.consiliummedia.com/": [
- "consiliummedia.com"
- ]
- }
- },
- {
- "Consumable": {
- "http://consumable.com/": [
- "consumable.com"
- ]
- }
- },
- {
- "CONTAXE": {
- "http://www.contaxe.com/": [
- "contaxe.com"
- ]
- }
- },
- {
- "ContentABC": {
- "http://contentabc.com/": [
- "contentabc.com"
- ]
- }
- },
- {
- "CONTEXTin": {
- "http://www.contextin.com/": [
- "admailtiser.com",
- "contextin.com"
- ]
- }
- },
- {
- "ContextuAds": {
- "http://www.contextuads.com/": [
- "agencytradingdesk.net",
- "contextuads.com"
- ]
- }
- },
- {
- "CONTEXTWEB": {
- "http://www.contextweb.com/": [
- "contextweb.com"
- ]
- }
- },
- {
- "ConvergeDirect": {
- "http://www.convergedirect.com/": [
- "convergedirect.com",
- "convergetrack.com"
- ]
- }
- },
- {
- "ConversantMedia": {
- "http://conversantmedia.com": [
- "adserver.com",
- "conversantmedia.com",
- "dotomi.com",
- "dtmpub.com",
- "emjcd.com",
- "fastclick.com",
- "fastclick.net",
- "greystripe.com",
- "lduhtrp.net",
- "mediaplex.com",
- "valueclick.com",
- "valueclick.net",
- "valueclickmedia.com"
- ]
- }
- },
- {
- "ConversionRuler": {
- "http://www.conversionruler.com/": [
- "conversionruler.com"
- ]
- }
- },
- {
- "Conversive": {
- "http://www.conversive.nl/": [
- "conversive.nl"
- ]
- }
- },
- {
- "CoreMotives": {
- "http://coremotives.com/": [
- "coremotives.com"
- ]
- }
- },
- {
- "Cox Digital Solutions": {
- "http://www.coxdigitalsolutions.com/": [
- "adify.com",
- "afy11.net",
- "coxdigitalsolutions.com"
- ]
- }
- },
- {
- "CPMStar": {
- "http://www.cpmstar.com/": [
- "cpmstar.com"
- ]
- }
- },
- {
- "CPX Interactive": {
- "http://www.cpxinteractive.com/": [
- "adreadypixels.com",
- "cpxadroit.com",
- "cpxinteractive.com"
- ]
- }
- },
- {
- "Creafi": {
- "http://www.creafi.com/": [
- "creafi.com"
- ]
- }
- },
- {
- "Crimtan": {
- "http://www.crimtan.com/": [
- "crimtan.com"
- ]
- }
- },
- {
- "Crisp Media": {
- "http://www.crispmedia.com/": [
- "crispmedia.com"
- ]
- }
- },
- {
- "Criteo": {
- "http://www.criteo.com/": [
- "criteo.com",
- "criteo.net",
- "hlserve.com",
- "hooklogic.com",
- "storetail.io"
- ]
- }
- },
- {
- "Cross Pixel": {
- "http://crosspixel.net/": [
- "crosspixel.net",
- "crosspixelmedia.com",
- "crsspxl.com"
- ]
- }
- },
- {
- "cXense": {
- "http://www.cxense.com/": [
- "cxense.com",
- "emediate.biz",
- "emediate.com",
- "emediate.dk",
- "emediate.eu"
- ]
- }
- },
- {
- "Cyberplex": {
- "http://www.cyberplex.com/": [
- "cyberplex.com"
- ]
- }
- },
- {
- "Dada": {
- "http://dada.pro/": [
- "dada.pro",
- "simply.com"
- ]
- }
- },
- {
- "Datalogix": {
- "http://www.datalogix.com/": [
- "nexac.com",
- "nextaction.net"
- ]
- }
- },
- {
- "DataXu": {
- "http://www.dataxu.com/": [
- "dataxu.com",
- "dataxu.net",
- "mexad.com",
- "w55c.net"
- ]
- }
- },
- {
- "Datonics": {
- "http://datonics.com/": [
- "datonics.com",
- "pro-market.net"
- ]
- }
- },
- {
- "Datran Media": {
- "http://www.datranmedia.com/": [
- "datranmedia.com",
- "displaymarketplace.com"
- ]
- }
- },
- {
- "Datvantage": {
- "http://datvantage.com/": [
- "datvantage.com"
- ]
- }
- },
- {
- "DC Storm": {
- "http://www.dc-storm.com/": [
- "dc-storm.com",
- "stormiq.com"
- ]
- }
- },
- {
- "Dedicated Media": {
- "http://www.dedicatedmedia.com/": [
- "dedicatedmedia.com",
- "dedicatednetworks.com"
- ]
- }
- },
- {
- "Delivr": {
- "http://delivr.com/": [
- "delivr.com",
- "percentmobile.com"
- ]
- }
- },
- {
- "Delta Projects": {
- "http://www.deltaprojects.se/": [
- "adaction.se",
- "de17a.com",
- "deltaprojects.se"
- ]
- }
- },
- {
- "Demand Media": {
- "http://www.demandmedia.com/": [
- "demandmedia.com",
- "indieclick.com"
- ]
- }
- },
- {
- "Deutsche Post DHL": {
- "http://www.dp-dhl.com/": [
- "adcloud.com",
- "adcloud.net",
- "dp-dhl.com"
- ]
- }
- },
- {
- "Developer Media": {
- "http://developermedia.com/": [
- "developermedia.com",
- "lqcdn.com"
- ]
- }
- },
- {
- "DG": {
- "http://www.dgit.com/": [
- "dgit.com",
- "eyeblaster.com",
- "eyewonder.com",
- "mdadx.com",
- "serving-sys.com",
- "unicast.com"
- ]
- }
- },
- {
- "dianomi": {
- "http://www.dianomi.com/": [
- "dianomi.com"
- ]
- }
- },
- {
- "Didit": {
- "http://www.didit.com/": [
- "did-it.com",
- "didit.com"
- ]
- }
- },
- {
- "DigitalAdConsortium": {
- "https://www.dac.co.jp/": [
- "impact-ad.jp"
- ]
- }
- },
- {
- "Digital River": {
- "http://www.digitalriver.com/": [
- "digitalriver.com",
- "keywordmax.com",
- "netflame.cc"
- ]
- }
- },
- {
- "Digital Target": {
- "http://digitaltarget.ru": [
- "digitaltarget.ru"
- ]
- }
- },
- {
- "Digitize": {
- "http://www.digitize.ie/": [
- "digitize.ie"
- ]
- }
- },
- {
- "DirectAdvert": {
- "http://www.directadvert.ru/": [
- "directadvert.ru"
- ]
- }
- },
- {
- "Direct Response Group": {
- "http://www.directresponsegroup.com/": [
- "directresponsegroup.com",
- "ppctracking.net"
- ]
- }
- },
- {
- "Directtrack": {
- "http://directtrack.com/": [
- "directtrack.com"
- ]
- }
- },
- {
- "Disqus": {
- "http://disqus.com/": [
- "disqusads.com"
- ]
- }
- },
- {
- "DistrictM": {
- "https://districtm.net": [
- "districtm.io"
- ]
- }
- },
- {
- "dmpxs": {
- "http://bob.dmpxs.com": [
- "dmpxs.com"
- ]
- }
- },
- {
- "DoublePimp": {
- "http://doublepimp.com/": [
- "doublepimp.com"
- ]
- }
- },
- {
- "DoublePositive": {
- "http://www.doublepositive.com/": [
- "bid-tag.com",
- "doublepositive.com"
- ]
- }
- },
- {
- "Drawbridge": {
- "http://drawbrid.ge/": [
- "adsymptotic.com",
- "drawbrid.ge"
- ]
- }
- },
- {
- "DS-IQ": {
- "http://www.ds-iq.com/": [
- "ds-iq.com"
- ]
- }
- },
- {
- "DSNR Group": {
- "http://www.dsnrmg.com/": [
- "dsnrgroup.com",
- "dsnrmg.com",
- "traffiliate.com",
- "z5x.com",
- "z5x.net"
- ]
- }
- },
- {
- "DynAdmic": {
- "https://dynadmic.com/": [
- "dynadmic.com",
- "dyntrk.com"
- ]
- }
- },
- {
- "DynamicOxygen": {
- "http://www.dynamicoxygen.com/": [
- "dynamicoxygen.com",
- "exitjunction.com"
- ]
- }
- },
- {
- "DynamicYield": {
- "https://www.dynamicyield.com/": [
- "px-eu.dynamicyield.com",
- "px.dynamicyield.com"
- ]
- }
- },
- {
- "Earnify": {
- "http://earnify.com/": [
- "earnify.com"
- ]
- }
- },
- {
- "eBay": {
- "http://www.ebay.com/": [
- "ebay.com"
- ]
- }
- },
- {
- "Effective Measure": {
- "http://www.effectivemeasure.com/": [
- "effectivemeasure.com",
- "effectivemeasure.net"
- ]
- }
- },
- {
- "ekolay": {
- "http://www.ekolay.net/": [
- "e-kolay.net",
- "ekolay.net"
- ]
- }
- },
- {
- "Eleavers": {
- "http://eleavers.com/": [
- "eleavers.com"
- ]
- }
- },
- {
- "Emego": {
- "http://www.usemax.de/": [
- "usemax.de"
- ]
- }
- },
- {
- "Emerse": {
- "https://www.emerse.com": [
- "emerse.com"
- ]
- }
- },
- {
- "EMX": {
- "https://emxdigital.com/": [
- "brealtime.com",
- "clearstream.tv",
- "emxdgt.com",
- "emxdigital.com"
- ]
- }
- },
- {
- "Enecto": {
- "http://www.enecto.com/": [
- "enecto.com"
- ]
- }
- },
- {
- "engage:BDR": {
- "http://engagebdr.com/": [
- "bnmla.com",
- "engagebdr.com"
- ]
- }
- },
- {
- "Engago Technology": {
- "http://www.engago.com/": [
- "appmetrx.com",
- "engago.com"
- ]
- }
- },
- {
- "Engine Network": {
- "http://enginenetwork.com/": [
- "enginenetwork.com"
- ]
- }
- },
- {
- "Ensighten": {
- "http://www.ensighten.com/": [
- "ensighten.com"
- ]
- }
- },
- {
- "Entireweb": {
- "http://www.entireweb.com/": [
- "entireweb.com"
- ]
- }
- },
- {
- "Epic Media Group": {
- "http://www.theepicmediagroup.com/": [
- "epicadvertising.com",
- "epicmarketplace.com",
- "epicmobileads.com",
- "theepicmediagroup.com",
- "trafficmp.com"
- ]
- }
- },
- {
- "Epsilon": {
- "http://www.epsilon.com/": [
- "epsilon.com"
- ]
- }
- },
- {
- "EQ Ads": {
- "http://www.eqads.com/": [
- "eqads.com"
- ]
- }
- },
- {
- "EroAdvertising": {
- "http://www.ero-advertising.com/": [
- "ero-advertising.com"
- ]
- }
- },
- {
- "Etarget": {
- "http://etargetnet.com/": [
- "etarget.eu",
- "etargetnet.com"
- ]
- }
- },
- {
- "Etineria": {
- "http://www.etineria.com/": [
- "adwitserver.com",
- "etineria.com"
- ]
- }
- },
- {
- "eTrigue": {
- "http://www.etrigue.com/": [
- "etrigue.com"
- ]
- }
- },
- {
- "Evergage": {
- "http://www.evergage.com": [
- "mybuys.com",
- "veruta.com"
- ]
- }
- },
- {
- "Everyday Health": {
- "http://www.everydayhealth.com/": [
- "everydayhealth.com",
- "waterfrontmedia.com"
- ]
- }
- },
- {
- "Evisions Marketing": {
- "http://www.evisionsmarketing.com/": [
- "engineseeker.com",
- "evisionsmarketing.com"
- ]
- }
- },
- {
- "Evolve": {
- "http://www.evolvemediacorp.com/": [
- "evolvemediacorp.com",
- "evolvemediametrics.com",
- "gorillanation.com"
- ]
- }
- },
- {
- "eWayDirect": {
- "http://www.ewaydirect.com/": [
- "ewaydirect.com",
- "ixs1.net"
- ]
- }
- },
- {
- "ewebse": {
- "http://ewebse.com/": [
- "777seo.com",
- "ewebse.com"
- ]
- }
- },
- {
- "excitad": {
- "http://excitad.com/": [
- "excitad.com"
- ]
- }
- },
- {
- "eXelate": {
- "http://exelate.com/": [
- "exelate.com",
- "exelator.com"
- ]
- }
- },
- {
- "ExoClick": {
- "http://www.exoclick.com/": [
- "exoclick.com"
- ]
- }
- },
- {
- "Exosrv": {
- "http://main.exosrv.com/": [
- "exosrv.com"
- ]
- }
- },
- {
- "Experian": {
- "http://www.experian.com/": [
- "audienceiq.com",
- "experian.com"
- ]
- }
- },
- {
- "expo-MAX": {
- "http://expo-max.com/": [
- "expo-max.com"
- ]
- }
- },
- {
- "Exponential Interactive": {
- "http://www.exponential.com/": [
- "adotube.com",
- "exponential.com",
- "fulltango.com",
- "tribalfusion.com"
- ]
- }
- },
- {
- "Extension Factory": {
- "http://www.extensionfactory.com/": [
- "extensionfactory.com"
- ]
- }
- },
- {
- "EXTENSIONS.RU": {
- "http://extensions.ru/": [
- "extensions.ru"
- ]
- }
- },
- {
- "Eyeconomy": {
- "http://www.eyeconomy.co.uk/": [
- "eyeconomy.co.uk",
- "eyeconomy.com",
- "sublimemedia.net"
- ]
- }
- },
- {
- "EyeNewton": {
- "http://eyenewton.ru/": [
- "eyenewton.ru"
- ]
- }
- },
- {
- "eyeReturn Marketing": {
- "http://www.eyereturnmarketing.com/": [
- "eyereturn.com",
- "eyereturnmarketing.com"
- ]
- }
- },
- {
- "Eyeviewdigital": {
- "http://www.eyeviewdigital.com/": [
- "eyeviewdigital.com"
- ]
- }
- },
- {
- "Facebook": {
- "http://www.facebook.com/": [
- "atlassolutions.com"
- ]
- }
- },
- {
- "Facilitate Digital": {
- "http://www.facilitatedigital.com/": [
- "adsfac.eu",
- "adsfac.info",
- "adsfac.net",
- "adsfac.sg",
- "adsfac.us",
- "facilitatedigital.com"
- ]
- }
- },
- {
- "Fairfax Media": {
- "http://www.fxj.com.au/": [
- "fairfax.com.au",
- "fxj.com.au"
- ]
- }
- },
- {
- "faithadnet": {
- "http://www.faithadnet.com/": [
- "faithadnet.com"
- ]
- }
- },
- {
- "Fanplayr": {
- "https://fanplayr.com/": [
- "fanplayr.com"
- ]
- }
- },
- {
- "Fathom": {
- "http://www.fathomdelivers.com/": [
- "fathomdelivers.com",
- "fathomseo.com"
- ]
- }
- },
- {
- "Federated Media": {
- "http://www.federatedmedia.net/": [
- "federatedmedia.net",
- "fmpub.net",
- "lijit.com"
- ]
- }
- },
- {
- "FetchBack": {
- "http://www.fetchback.com/": [
- "fetchback.com"
- ]
- }
- },
- {
- "Fiksu": {
- "http://www.fiksu.com/": [
- "fiksu.com"
- ]
- }
- },
- {
- "FinancialContent": {
- "http://www.financialcontent.com/": [
- "financialcontent.com"
- ]
- }
- },
- {
- "Fizz-Buzz Media": {
- "http://www.fizzbuzzmedia.com/": [
- "fizzbuzzmedia.com",
- "fizzbuzzmedia.net"
- ]
- }
- },
- {
- "Flashtalking": {
- "http://www.flashtalking.com/": [
- "flashtalking.com"
- ]
- }
- },
- {
- "Flite": {
- "http://www.flite.com/": [
- "flite.com",
- "widgetserver.com"
- ]
- }
- },
- {
- "Fluct": {
- "https://corp.fluct.jp/": [
- "adingo.jp",
- "fluct.jp"
- ]
- }
- },
- {
- "Flytxt": {
- "http://www.flytxt.com/": [
- "flytxt.com"
- ]
- }
- },
- {
- "Forbes": {
- "http://www.forbes.com/": [
- "brandsideplatform.com",
- "forbes.com"
- ]
- }
- },
- {
- "Fox One Stop Media": {
- "http://www.foxonestop.com/": [
- "fimserve.com",
- "foxnetworks.com",
- "foxonestop.com",
- "mobsmith.com",
- "myads.com",
- "othersonline.com"
- ]
- }
- },
- {
- "FreakOut": {
- "http://fout.jp/": [
- "fout.jp"
- ]
- }
- },
- {
- "Freedom Communications": {
- "http://www.freedom.com/": [
- "freedom.com"
- ]
- }
- },
- {
- "FreeWheel": {
- "http://www.freewheel.tv/": [
- "stickyadstv.com"
- ]
- }
- },
- {
- "FriendFinder Networks": {
- "http://ffn.com/": [
- "adultfriendfinder.com",
- "ffn.com",
- "pop6.com"
- ]
- }
- },
- {
- "Friends2Follow": {
- "https://friends2follow.com/": [
- "tracking.friends2follow.com"
- ]
- }
- },
- {
- "Frog Sex": {
- "http://www.frogsex.com/": [
- "double-check.com",
- "frogsex.com"
- ]
- }
- },
- {
- "FuelX": {
- "https://fuelx.com/": [
- "fuel451.com",
- "fuelx.com"
- ]
- }
- },
- {
- "Future Ads": {
- "https://www.futureads.com/": [
- "futureads.com",
- "resultlinks.com"
- ]
- }
- },
- {
- "Fyber": {
- "https://www.fyber.com/": [
- "fyber.com"
- ]
- }
- },
- {
- "Game Advertising Online": {
- "http://www.game-advertising-online.com/": [
- "game-advertising-online.com"
- ]
- }
- },
- {
- "Games2win": {
- "http://www.games2win.com/": [
- "games2win.com",
- "inviziads.com"
- ]
- }
- },
- {
- "Gamned": {
- "http://www.gamned.com/": [
- "gamned.com"
- ]
- }
- },
- {
- "Gannett": {
- "http://www.gannett.com/": [
- "gannett.com",
- "pointroll.com"
- ]
- }
- },
- {
- "GB-World": {
- "http://www.gb-world.net/": [
- "gb-world.net"
- ]
- }
- },
- {
- "Gemius": {
- "http://www.gemius.com/": [
- "gemius.com",
- "gemius.pl"
- ]
- }
- },
- {
- "Genesis Media": {
- "http://www.genesismedia.com/": [
- "genesismedia.com",
- "genesismediaus.com"
- ]
- }
- },
- {
- "GENIEE": {
- "https://geniee.co.jp/": [
- "geniee.co.jp",
- "gssprt.jp"
- ]
- }
- },
- {
- "GENIE GROUP": {
- "http://www.geniegroupltd.co.uk/": [
- "geniegroupltd.co.uk"
- ]
- }
- },
- {
- "GeoAds": {
- "http://www.geoads.com/": [
- "geoads.com"
- ]
- }
- },
- {
- "GetGlue": {
- "http://getglue.com/": [
- "getglue.com",
- "smrtlnks.com"
- ]
- }
- },
- {
- "GetIntent": {
- "http://getintent.com/": [
- "adhigh.net",
- "getintent.com"
- ]
- }
- },
- {
- "GISMAds": {
- "http://www.gismads.jp/": [
- "gismads.jp"
- ]
- }
- },
- {
- "Glam Media": {
- "http://www.glammedia.com/": [
- "glam.com",
- "glammedia.com"
- ]
- }
- },
- {
- "Gleam": {
- "https://gleam.io/": [
- "fraudjs.io",
- "gleam.io"
- ]
- }
- },
- {
- "Globe7": {
- "http://www.globe7.com/": [
- "globe7.com"
- ]
- }
- },
- {
- "GoDataFeed": {
- "http://godatafeed.com/": [
- "godatafeed.com"
- ]
- }
- },
- {
- "Goldbach": {
- "http://www.goldbachgroup.com/": [
- "goldbach.com",
- "goldbachgroup.com"
- ]
- }
- },
- {
- "GoldSpot Media": {
- "http://www.goldspotmedia.com/": [
- "goldspotmedia.com"
- ]
- }
- },
- {
- "Google": {
- "http://www.google.com/": [
- "2mdn.net",
- "admeld.com",
- "admob.com",
- "adservice.google.ca",
- "adservice.google.com",
- "adwords.google.com",
- "cc-dt.com",
- "destinationurl.com",
- "doubleclick.net",
- "googleadservices.com",
- "googlesyndication.com",
- "googletagservices.com",
- "invitemedia.com",
- "smtad.net",
- "teracent.com",
- "teracent.net",
- "ytsa.net"
- ]
- }
- },
- {
- "Grapeshot": {
- "http://www.grapeshot.co.uk/": [
- "grapeshot.co.uk"
- ]
- }
- },
- {
- "Graphnium": {
- "https://www.graphinium.com/": [
- "crm4d.com"
- ]
- }
- },
- {
- "Grocery Shopping Network": {
- "http://www.groceryshopping.net/": [
- "groceryshopping.net"
- ]
- }
- },
- {
- "GroovinAds": {
- "http://www.groovinads.com/": [
- "groovinads.com"
- ]
- }
- },
- {
- "Gruner + Jahr": {
- "http://www.guj.de/": [
- "guj.de",
- "ligatus.com"
- ]
- }
- },
- {
- "GumGum": {
- "http://gumgum.com/": [
- "gumgum.com"
- ]
- }
- },
- {
- "Gunggo": {
- "http://www.gunggo.com/": [
- "gunggo.com"
- ]
- }
- },
- {
- "Hands Mobile": {
- "http://www.hands.com.br/": [
- "hands.com.br"
- ]
- }
- },
- {
- "Harrenmedia": {
- "http://www.harrenmedia.com/": [
- "harrenmedia.com",
- "harrenmedianetwork.com"
- ]
- }
- },
- {
- "HealthPricer": {
- "http://www.healthpricer.com/": [
- "adacado.com",
- "healthpricer.com"
- ]
- }
- },
- {
- "Hearst": {
- "http://www.hearst.com/": [
- "hearst.com",
- "ic-live.com",
- "iclive.com",
- "icrossing.com",
- "sptag.com",
- "sptag1.com",
- "sptag2.com",
- "sptag3.com"
- ]
- }
- },
- {
- "HilltopAds": {
- "https://hilltopads.com/": [
- "hilltopads.com",
- "hilltopads.net",
- "shoporielder.pro"
- ]
- }
- },
- {
- "Hi-media": {
- "http://www.hi-media.com/": [
- "comclick.com",
- "hi-media.com"
- ]
- }
- },
- {
- "Horyzon Media": {
- "http://www.horyzon-media.com/": [
- "horyzon-media.com"
- ]
- }
- },
- {
- "HotMart": {
- "https://www.hotmart.com/en/": [
- "hotmart.com"
- ]
- }
- },
- {
- "HOTWords": {
- "http://www.hotwords.com/": [
- "hotwords.com",
- "hotwords.es"
- ]
- }
- },
- {
- "HP": {
- "http://www.hp.com/": [
- "hp.com",
- "optimost.com"
- ]
- }
- },
- {
- "Httpool": {
- "http://www.httpool.com/": [
- "httpool.com"
- ]
- }
- },
- {
- "HUNT Mobile Ads": {
- "http://www.huntmads.com/": [
- "huntmads.com"
- ]
- }
- },
- {
- "Hurra.com": {
- "http://www.hurra.com/": [
- "hurra.com"
- ]
- }
- },
- {
- "IAB": {
- "https://iabtechlab.com/": [
- "digitru.st"
- ]
- }
- },
- {
- "IAC": {
- "http://www.iac.com/": [
- "iac.com",
- "iacadvertising.com"
- ]
- }
- },
- {
- "iBehavior": {
- "http://www.i-behavior.com/": [
- "i-behavior.com",
- "ib-ibi.com"
- ]
- }
- },
- {
- "IBM": {
- "http://www.ibm.com/": [
- "unica.com"
- ]
- }
- },
- {
- "ID5": {
- "http://id5.io/": [
- "id5-sync.com"
- ]
- }
- },
- {
- "IDG": {
- "http://www.idg.com/": [
- "idg.com",
- "idgtechnetwork.com"
- ]
- }
- },
- {
- "iEntry": {
- "http://www.ientry.com/": [
- "600z.com",
- "ientry.com"
- ]
- }
- },
- {
- "IgnitAd": {
- "http://www.ignitad.com/": [
- "ignitad.com"
- ]
- }
- },
- {
- "IgnitionOne": {
- "http://www.ignitionone.com/": [
- "ignitionone.com",
- "ignitionone.net",
- "searchignite.com"
- ]
- }
- },
- {
- "Improve Digital": {
- "www.improvedigital.com/": [
- "360yield.com",
- "improvedigital.com"
- ]
- }
- },
- {
- "Inadco": {
- "http://www.inadco.com/": [
- "anadcoads.com",
- "inadco.com",
- "inadcoads.com"
- ]
- }
- },
- {
- "IndexExchange": {
- "https://www.indexexchange.com": [
- "indexexchange.com"
- ]
- }
- },
- {
- "Infectious Media": {
- "http://www.infectiousmedia.com/": [
- "impressiondesk.com",
- "infectiousmedia.com"
- ]
- }
- },
- {
- "Inflection Point Media": {
- "http://www.inflectionpointmedia.com/": [
- "inflectionpointmedia.com"
- ]
- }
- },
- {
- "Infogroup": {
- "http://www.infogroup.com/": [
- "infogroup.com"
- ]
- }
- },
- {
- "Infolinks": {
- "http://www.infolinks.com/": [
- "infolinks.com"
- ]
- }
- },
- {
- "Infra-Ad": {
- "http://www.infra-ad.com/": [
- "infra-ad.com"
- ]
- }
- },
- {
- "InMobi": {
- "http://www.inmobi.com/": [
- "aerserv.com",
- "inmobi.com",
- "sproutinc.com"
- ]
- }
- },
- {
- "inneractive": {
- "http://inner-active.com/": [
- "inner-active.com"
- ]
- }
- },
- {
- "Innity": {
- "http://innity.com/": [
- "innity.com"
- ]
- }
- },
- {
- "InsightExpress": {
- "http://www.insightexpress.com/": [
- "insightexpress.com",
- "insightexpressai.com"
- ]
- }
- },
- {
- "InSkin Media": {
- "http://inskinmedia.com/": [
- "inskinmedia.com"
- ]
- }
- },
- {
- "Instinctive": {
- "https://instinctive.io/": [
- "instinctive.io",
- "instinctiveads.com"
- ]
- }
- },
- {
- "Integral Ad Science": {
- "https://integralads.com/": [
- "adsafemedia.com",
- "adsafeprotected.com",
- "iasds01.com",
- "integralads.com"
- ]
- }
- },
- {
- "Intent Media": {
- "http://www.intentmedia.com/": [
- "intentmedia.com",
- "intentmedia.net"
- ]
- }
- },
- {
- "Intergi": {
- "http://intergi.com/": [
- "intergi.com"
- ]
- }
- },
- {
- "Intermarkets": {
- "http://www.intermarkets.net/": [
- "intermarkets.net"
- ]
- }
- },
- {
- "Intermundo Media": {
- "http://intermundomedia.com/": [
- "intermundomedia.com"
- ]
- }
- },
- {
- "Internet Brands": {
- "http://www.internetbrands.com/": [
- "ibpxl.com",
- "internetbrands.com"
- ]
- }
- },
- {
- "Interpolls": {
- "http://www.interpolls.com/": [
- "interpolls.com"
- ]
- }
- },
- {
- "Inuvo": {
- "http://inuvo.com/": [
- "inuvo.com"
- ]
- }
- },
- {
- "InvestingChannel": {
- "http://investingchannel.com/": [
- "investingchannel.com"
- ]
- }
- },
- {
- "IponWeb": {
- "https://www.iponweb.com/": [
- "iponweb.com",
- "iponweb.net"
- ]
- }
- },
- {
- "iPROM": {
- "http://www.iprom.si/": [
- "centraliprom.com",
- "iprom.net",
- "iprom.si",
- "mediaiprom.com"
- ]
- }
- },
- {
- "iPromote": {
- "http://www.ipromote.com/": [
- "ipromote.com"
- ]
- }
- },
- {
- "iProspect": {
- "http://www.iprospect.com/": [
- "clickmanage.com",
- "iprospect.com"
- ]
- }
- },
- {
- "ISI Technologies": {
- "http://digbro.com/": [
- "adversalservers.com",
- "digbro.com"
- ]
- }
- },
- {
- "ismatlab.com": {
- "http://ismatlab.com": [
- "ismatlab.com"
- ]
- }
- },
- {
- "I.UA": {
- "http://www.i.ua/": [
- "i.ua"
- ]
- }
- },
- {
- "Jaroop": {
- "http://www.jaroop.com/": [
- "jaroop.com"
- ]
- }
- },
- {
- "JasperLabs": {
- "http://www.jasperlabs.com/": [
- "jasperlabs.com"
- ]
- }
- },
- {
- "Jemm": {
- "http://jemmgroup.com/": [
- "jemmgroup.com"
- ]
- }
- },
- {
- "Jink": {
- "http://www.jink.de/": [
- "jink.de",
- "jinkads.com"
- ]
- }
- },
- {
- "Jirbo": {
- "http://jirbo.com/": [
- "adcolony.com",
- "jirbo.com"
- ]
- }
- },
- {
- "Jivox": {
- "http://www.jivox.com/": [
- "jivox.com"
- ]
- }
- },
- {
- "JobThread": {
- "http://www.jobthread.com/": [
- "jobthread.com"
- ]
- }
- },
- {
- "JuicyAds": {
- "http://www.juicyads.com/": [
- "juicyads.com"
- ]
- }
- },
- {
- "Jumptap": {
- "http://www.jumptap.com/": [
- "jumptap.com"
- ]
- }
- },
- {
- "justuno": {
- "https://www.justuno.com/": [
- "justuno.com"
- ]
- }
- },
- {
- "Kargo": {
- "https://kargo.com/": [
- "kargo.com"
- ]
- }
- },
- {
- "Kenshoo": {
- "http://www.kenshoo.com/": [
- "kenshoo.com",
- "xg4ken.com"
- ]
- }
- },
- {
- "Keyade": {
- "http://www.keyade.com/": [
- "keyade.com"
- ]
- }
- },
- {
- "Keywee": {
- "https://keywee.co": [
- "keywee.co"
- ]
- }
- },
- {
- "KissMyAds": {
- "http://kissmyads.com/": [
- "kissmyads.com"
- ]
- }
- },
- {
- "Kitara Media": {
- "http://www.kitaramedia.com/": [
- "103092804.com",
- "kitaramedia.com"
- ]
- }
- },
- {
- "KIT digital": {
- "http://kitd.com/": [
- "keewurd.com",
- "kitd.com",
- "peerset.com"
- ]
- }
- },
- {
- "Kokteyl": {
- "http://www.kokteyl.com/": [
- "admost.com",
- "kokteyl.com"
- ]
- }
- },
- {
- "Komli": {
- "http://www.komli.com/": [
- "komli.com"
- ]
- }
- },
- {
- "Kontera": {
- "http://www.kontera.com/": [
- "kontera.com"
- ]
- }
- },
- {
- "Korrelate": {
- "http://korrelate.com/": [
- "adsummos.com",
- "adsummos.net",
- "korrelate.com"
- ]
- }
- },
- {
- "Krux": {
- "http://www.krux.com/": [
- "krux.com",
- "kruxdigital.com",
- "krxd.net"
- ]
- }
- },
- {
- "Lakana": {
- "http://www.lakana.com/": [
- "ibsys.com",
- "lakana.com"
- ]
- }
- },
- {
- "Layer-Ad.org": {
- "http://layer-ad.org/": [
- "layer-ad.org"
- ]
- }
- },
- {
- "Layer Ads": {
- "http://layer-ads.net/": [
- "layer-ads.net"
- ]
- }
- },
- {
- "LeadBolt": {
- "http://www.leadbolt.com/": [
- "leadbolt.com"
- ]
- }
- },
- {
- "LeadFormix": {
- "http://www.leadformix.com/": [
- "leadforce1.com",
- "leadformix.com"
- ]
- }
- },
- {
- "LeanPlum": {
- "https://www.leanplum.com/": [
- "leanplum.com"
- ]
- }
- },
- {
- "Legolas Media": {
- "http://www.legolas-media.com/": [
- "legolas-media.com"
- ]
- }
- },
- {
- "Levexis": {
- "http://www.levexis.com/": [
- "levexis.com"
- ]
- }
- },
- {
- "Lexos Media": {
- "http://www.lexosmedia.com/": [
- "adbull.com",
- "lexosmedia.com"
- ]
- }
- },
- {
- "LifeStreet": {
- "http://lifestreetmedia.com/": [
- "lfstmedia.com",
- "lifestreetmedia.com"
- ]
- }
- },
- {
- "LinkConnector": {
- "http://www.linkconnector.com/": [
- "linkconnector.com"
- ]
- }
- },
- {
- "LinkShare": {
- "http://www.linkshare.com/": [
- "linkshare.com",
- "linksynergy.com"
- ]
- }
- },
- {
- "Linkz": {
- "http://www.linkz.net/": [
- "linkz.net"
- ]
- }
- },
- {
- "Listrak": {
- "http://www.listrak.com/": [
- "listrak.com",
- "listrakbi.com"
- ]
- }
- },
- {
- "LiveIntent": {
- "http://www.liveintent.com/": [
- "liadm.com",
- "liveintent.com"
- ]
- }
- },
- {
- "LiveInternet": {
- "http://www.liveinternet.ru": [
- "liveinternet.ru",
- "yadro.ru"
- ]
- }
- },
- {
- "LiveRamp": {
- "https://liveramp.com/": [
- "liveramp.com",
- "tvpixel.com"
- ]
- }
- },
- {
- "LKQD": {
- "http://lkqd.com": [
- "lkqd.com",
- "lkqd.net"
- ]
- }
- },
- {
- "Local Yokel Media": {
- "http://www.localyokelmedia.com/": [
- "localyokelmedia.com"
- ]
- }
- },
- {
- "Localytics": {
- "https://www.localytics.com/": [
- "localytics.com"
- ]
- }
- },
- {
- "LockerDome": {
- "https://lockerdome.com/": [
- "lockerdome.com"
- ]
- }
- },
- {
- "Longboard Media": {
- "http://longboardmedia.com/": [
- "longboardmedia.com"
- ]
- }
- },
- {
- "Loomia": {
- "http://www.loomia.com/": [
- "loomia.com"
- ]
- }
- },
- {
- "LoopFuse": {
- "https://www.loopfuse.net/": [
- "lfov.net",
- "loopfuse.net"
- ]
- }
- },
- {
- "LoopMe": {
- "https://loopme.com/": [
- "loopme.com"
- ]
- }
- },
- {
- "LotLinx": {
- "https://www.lotlinx.com": [
- "lotlinx.com"
- ]
- }
- },
- {
- "Lower My Bills": {
- "http://lowermybills.com": [
- "lowermybills.com"
- ]
- }
- },
- {
- "lptracker": {
- "https://lptracker.io/": [
- "lptracker.io"
- ]
- }
- },
- {
- "LucidMedia": {
- "http://www.lucidmedia.com/": [
- "lucidmedia.com"
- ]
- }
- },
- {
- "m6d": {
- "http://m6d.com/": [
- "m6d.com",
- "media6degrees.com"
- ]
- }
- },
- {
- "Madhouse": {
- "http://www.madhouse.cn/": [
- "madhouse.cn"
- ]
- }
- },
- {
- "Madison Logic": {
- "http://www.madisonlogic.com/": [
- "dinclinx.com",
- "madisonlogic.com"
- ]
- }
- },
- {
- "madvertise": {
- "http://madvertise.com/": [
- "madvertise.com"
- ]
- }
- },
- {
- "Magnetic": {
- "http://www.magnetic.com/": [
- "domdex.com",
- "domdex.net",
- "magnetic.com",
- "qjex.net"
- ]
- }
- },
- {
- "Magnify360": {
- "http://www.magnify360.com/": [
- "dialogmgr.com",
- "magnify360.com"
- ]
- }
- },
- {
- "MailChimp": {
- "http://mailchimp.com/": [
- "campaign-archive1.com",
- "list-manage.com",
- "mailchimp.com"
- ]
- }
- },
- {
- "Manifest": {
- "http://www.manifest.ru/": [
- "bannerbank.ru",
- "manifest.ru"
- ]
- }
- },
- {
- "Marchex": {
- "http://www.marchex.com/": [
- "industrybrains.com",
- "marchex.com"
- ]
- }
- },
- {
- "Marimedia": {
- "http://www.marimedia.net/": [
- "marimedia.net"
- ]
- }
- },
- {
- "MarketGid": {
- "http://www.marketgid.com/": [
- "dt00.net",
- "dt07.net",
- "marketgid.com"
- ]
- }
- },
- {
- "Marketo": {
- "http://www.marketo.com/": [
- "marketo.com",
- "marketo.net"
- ]
- }
- },
- {
- "Martini Media": {
- "http://martinimedianetwork.com/": [
- "martiniadnetwork.com",
- "martinimedianetwork.com"
- ]
- }
- },
- {
- "mashero": {
- "http://www.mashero.com/": [
- "mashero.com"
- ]
- }
- },
- {
- "Match.com": {
- "http://www.match.com/": [
- "chemistry.com",
- "match.com",
- "meetic-partners.com"
- ]
- }
- },
- {
- "Matomy": {
- "http://www.matomy.com/": [
- "adnetinteractive.com",
- "adsmarket.com",
- "matomy.com",
- "matomymarket.com",
- "matomymedia.com",
- "mediawhiz.com",
- "optimatic.com",
- "xtendmedia.com"
- ]
- }
- },
- {
- "MaxBounty": {
- "http://www.maxbounty.com/": [
- "maxbounty.com",
- "mb01.com"
- ]
- }
- },
- {
- "MaxPoint": {
- "http://maxpointinteractive.com/": [
- "maxpointinteractive.com",
- "maxusglobal.com",
- "mxptint.net"
- ]
- }
- },
- {
- "MdotM": {
- "http://mdotm.com/": [
- "mdotm.com"
- ]
- }
- },
- {
- "MediaBrix": {
- "http://www.mediabrix.com/": [
- "mediabrix.com"
- ]
- }
- },
- {
- "MediaCom": {
- "http://www.mediacom.com/": [
- "mediacom.com"
- ]
- }
- },
- {
- "mediaFORGE": {
- "http://www.mediaforge.com/": [
- "mediaforge.com"
- ]
- }
- },
- {
- "Medialets": {
- "http://www.medialets.com/": [
- "medialets.com"
- ]
- }
- },
- {
- "MediaMath": {
- "http://www.mediamath.com/": [
- "adroitinteractive.com",
- "designbloxlive.com",
- "mathtag.com",
- "mediamath.com"
- ]
- }
- },
- {
- "media.net": {
- "http://www.media.net/": [
- "media.net"
- ]
- }
- },
- {
- "Mediaocean": {
- "http://www.mediaocean.com/": [
- "adbuyer.com",
- "mediaocean.com"
- ]
- }
- },
- {
- "MediaShakers": {
- "http://www.mediashakers.com/": [
- "media-servers.net",
- "mediashakers.com"
- ]
- }
- },
- {
- "MediaTrust": {
- "http://www.mediatrust.com/": [
- "mediatrust.com"
- ]
- }
- },
- {
- "Medicx Media Solutions": {
- "http://www.medicxmedia.com/": [
- "medicxmedia.com"
- ]
- }
- },
- {
- "MegaIndex": {
- "http://www.megaindex.ru/": [
- "megaindex.ru"
- ]
- }
- },
- {
- "Mercent": {
- "http://www.mercent.com/": [
- "mercent.com"
- ]
- }
- },
- {
- "MerchantAdvantage": {
- "http://www.merchantadvantage.com/": [
- "merchantadvantage.com"
- ]
- }
- },
- {
- "Merchenta": {
- "http://www.merchenta.com/": [
- "merchenta.com"
- ]
- }
- },
- {
- "Merkle": {
- "https://www.merkleinc.com/": [
- "rimmkaufman.com",
- "rkdms.com"
- ]
- }
- },
- {
- "Meta Network": {
- "http://www.metanetwork.com/": [
- "metanetwork.com"
- ]
- }
- },
- {
- "Meteor": {
- "http://www.meteorsolutions.com/": [
- "meteorsolutions.com"
- ]
- }
- },
- {
- "MetrixLab": {
- "https://www.metrixlab.com": [
- "adoftheyear.com",
- "crm-metrix.com",
- "customerconversio.com",
- "metrixlab.com",
- "opinionbar.com"
- ]
- }
- },
- {
- "MicroAd": {
- "http://www.microad.jp/": [
- "microad.jp"
- ]
- }
- },
- {
- "Microsoft": {
- "http://www.microsoft.com/": [
- "adbureau.net",
- "adecn.com",
- "aquantive.com",
- "msads.net",
- "netconversions.com",
- "roiservice.com"
- ]
- }
- },
- {
- "Millennial Media": {
- "http://www.millennialmedia.com/": [
- "decktrade.com",
- "millennialmedia.com",
- "mydas.mobi"
- ]
- }
- },
- {
- "Mindset Media": {
- "http://www.mindset-media.com/": [
- "mindset-media.com",
- "mmismm.com"
- ]
- }
- },
- {
- "Mirando": {
- "http://www.mirando.de/": [
- "mirando.de"
- ]
- }
- },
- {
- "Mixpo": {
- "http://www.mixpo.com/": [
- "mixpo.com"
- ]
- }
- },
- {
- "Moat": {
- "http://www.moat.com/": [
- "moat.com",
- "moatads.com"
- ]
- }
- },
- {
- "MobFox": {
- "http://www.mobfox.com/": [
- "mobfox.com"
- ]
- }
- },
- {
- "Mobials": {
- "http://mobials.com": [
- "mobials.com"
- ]
- }
- },
- {
- "MobileAdTrading": {
- "https://mobileadtrading.com/": [
- "mobileadtrading.com"
- ]
- }
- },
- {
- "Mobile Meteor": {
- "http://mobilemeteor.com/": [
- "mobilemeteor.com",
- "showmeinn.com"
- ]
- }
- },
- {
- "Mobile Storm": {
- "http://mobilestorm.com/": [
- "mobilestorm.com"
- ]
- }
- },
- {
- "MobVision": {
- "http://www.mobvision.com/": [
- "admoda.com",
- "mobvision.com"
- ]
- }
- },
- {
- "Mocean Mobile": {
- "http://www.moceanmobile.com/": [
- "moceanmobile.com"
- ]
- }
- },
- {
- "Mochila": {
- "http://www.mochila.com/": [
- "mochila.com"
- ]
- }
- },
- {
- "Mojiva": {
- "http://www.mojiva.com/": [
- "mojiva.com"
- ]
- }
- },
- {
- "Monetate": {
- "http://monetate.com/": [
- "monetate.com",
- "monetate.net"
- ]
- }
- },
- {
- "MONETIZEdigital": {
- "https://www.cpalead.com/": [
- "cpalead.com"
- ]
- }
- },
- {
- "Monetize More": {
- "http://monetizemore.com/": [
- "monetizemore.com"
- ]
- }
- },
- {
- "Monoloop": {
- "http://www.monoloop.com/": [
- "monoloop.com"
- ]
- }
- },
- {
- "Monster": {
- "http://www.monster.com/": [
- "monster.com"
- ]
- }
- },
- {
- "Moolah Media": {
- "http://www.moolahmedia.com/": [
- "moolah-media.com",
- "moolahmedia.com"
- ]
- }
- },
- {
- "MoPub": {
- "http://www.mopub.com/": [
- "mopub.com"
- ]
- }
- },
- {
- "MovieLush.com": {
- "https://www.movielush.com/": [
- "affbuzzads.com",
- "movielush.com"
- ]
- }
- },
- {
- "Multiple Stream Media": {
- "http://www.multiplestreammktg.com/": [
- "adclickmedia.com",
- "multiplestreammktg.com"
- ]
- }
- },
- {
- "MUNDO Media": {
- "http://www.mundomedia.com/": [
- "mundomedia.com",
- "silver-path.com"
- ]
- }
- },
- {
- "MyCounter": {
- "http://mycounter.com.ua/": [
- "mycounter.com.ua"
- ]
- }
- },
- {
- "MyPressPlus": {
- "http://www.mypressplus.com/": [
- "mypressplus.com",
- "ppjol.net"
- ]
- }
- },
- {
- "myThings": {
- "http://www.mythings.com/": [
- "mythings.com",
- "mythingsmedia.com"
- ]
- }
- },
- {
- "MyWebGrocer": {
- "http://www.mywebgrocer.com/": [
- "mywebgrocer.com"
- ]
- }
- },
- {
- "Nanigans": {
- "http://www.nanigans.com/": [
- "nanigans.com"
- ]
- }
- },
- {
- "NativeAds": {
- "https://nativeads.com/": [
- "nativeads.com"
- ]
- }
- },
- {
- "Nativo": {
- "http://www.nativo.net/": [
- "postrelease.com"
- ]
- }
- },
- {
- "Navegg": {
- "http://www.navegg.com/": [
- "navdmp.com",
- "navegg.com"
- ]
- }
- },
- {
- "NetAffiliation": {
- "http://www.netaffiliation.com/": [
- "netaffiliation.com"
- ]
- }
- },
- {
- "NetBina": {
- "http://www.netbina.com/": [
- "netbina.com"
- ]
- }
- },
- {
- "NetElixir": {
- "http://www.netelixir.com/": [
- "adelixir.com",
- "netelixir.com"
- ]
- }
- },
- {
- "Netmining": {
- "http://www.netmining.com/": [
- "netmining.com",
- "netmng.com"
- ]
- }
- },
- {
- "Net-Results": {
- "http://www.net-results.com/": [
- "cdnma.com",
- "net-results.com",
- "nr7.us"
- ]
- }
- },
- {
- "NetSeer": {
- "http://www.netseer.com/": [
- "netseer.com"
- ]
- }
- },
- {
- "NetShelter": {
- "http://netshelter.com/": [
- "netshelter.com",
- "netshelter.net"
- ]
- }
- },
- {
- "Neustar": {
- "http://www.neustar.biz/": [
- "adadvisor.net",
- "neustar.biz"
- ]
- }
- },
- {
- "newtention": {
- "http://newtention.de/": [
- "newtention.de",
- "newtention.net",
- "newtentionassets.net"
- ]
- }
- },
- {
- "Nexage": {
- "http://nexage.com/": [
- "nexage.com"
- ]
- }
- },
- {
- "Nextag": {
- "http://www.nextag.com/": [
- "nextag.com"
- ]
- }
- },
- {
- "NextPerformance": {
- "http://www.nextperformance.com/": [
- "nextperformance.com",
- "nxtck.com"
- ]
- }
- },
- {
- "Nielsen": {
- "http://www.nielsen.com/": [
- "imrworldwide.com",
- "imrworldwide.net"
- ]
- }
- },
- {
- "Ninua": {
- "http://www.ninua.com/": [
- "networkedblogs.com",
- "ninua.com"
- ]
- }
- },
- {
- "Nokta": {
- "http://www.noktamedya.com/": [
- "noktamedya.com",
- "virgul.com"
- ]
- }
- },
- {
- "NowSpots": {
- "http://nowspots.com/": [
- "nowspots.com"
- ]
- }
- },
- {
- "nrelate": {
- "http://nrelate.com/": [
- "nrelate.com"
- ]
- }
- },
- {
- "Nuffnang": {
- "http://www.nuffnang.com.my/": [
- "nuffnang.com",
- "nuffnang.com.my"
- ]
- }
- },
- {
- "nugg.ad": {
- "http://www.nugg.ad/": [
- "nugg.ad",
- "nuggad.net"
- ]
- }
- },
- {
- "Ohana Media": {
- "http://www.ohana-media.com/": [
- "adohana.com",
- "ohana-media.com",
- "ohanaqb.com"
- ]
- }
- },
- {
- "Omnicom Group": {
- "http://www.omnicomgroup.com/": [
- "accuenmedia.com",
- "omnicomgroup.com",
- "p-td.com"
- ]
- }
- },
- {
- "onAd": {
- "http://www.onad.eu/": [
- "onad.eu"
- ]
- }
- },
- {
- "Onclusive": {
- "https://onclusive.com/": [
- "airpr.com"
- ]
- }
- },
- {
- "OneAd": {
- "https://www.onead.com.tw/": [
- "guoshipartners.com",
- "onevision.com.tw"
- ]
- }
- },
- {
- "One iota": {
- "http://www.itsoneiota.com/": [
- "itsoneiota.com",
- "oneiota.co.uk"
- ]
- }
- },
- {
- "Oneupweb": {
- "http://www.oneupweb.com/": [
- "oneupweb.com",
- "sodoit.com"
- ]
- }
- },
- {
- "OnlineMetrix": {
- "http://h.online-metrix.net": [
- "online-metrix.net"
- ]
- }
- },
- {
- "Open New Media": {
- "http://www.onm.de/": [
- "onm.de"
- ]
- }
- },
- {
- "OpenX": {
- "http://openx.com/": [
- "liftdna.com",
- "openx.com",
- "openx.net",
- "openx.org",
- "openxenterprise.com",
- "servedbyopenx.com"
- ]
- }
- },
- {
- "Opera": {
- "http://www.opera.com/": [
- "mobiletheory.com",
- "opera.com",
- "operamediaworks.com",
- "operasoftware.com"
- ]
- }
- },
- {
- "OPT": {
- "http://www.opt.ne.jp/": [
- "advg.jp",
- "opt.ne.jp",
- "p-advg.com"
- ]
- }
- },
- {
- "Optify": {
- "http://www.optify.net/": [
- "optify.net"
- ]
- }
- },
- {
- "Optimal": {
- "http://optim.al/": [
- "cpmadvisors.com",
- "cpmatic.com",
- "nprove.com",
- "optim.al",
- "orbengine.com",
- "xa.net"
- ]
- }
- },
- {
- "OptimumResponse": {
- "http://www.optimumresponse.com/": [
- "optimumresponse.com"
- ]
- }
- },
- {
- "OptinMonster": {
- "https://optinmonster.com/": [
- "optinmonster.com",
- "optnmstr.com"
- ]
- }
- },
- {
- "OptMD": {
- "http://optmd.com/": [
- "optmd.com"
- ]
- }
- },
- {
- "Oracle": {
- "http://www.oracle.com/": [
- "estara.com"
- ]
- }
- },
- {
- "OrangeSoda": {
- "http://www.orangesoda.com/": [
- "orangesoda.com",
- "otracking.com"
- ]
- }
- },
- {
- "Outbrain": {
- "http://www.outbrain.com/": [
- "outbrain.com",
- "sphere.com",
- "visualrevenue.com"
- ]
- }
- },
- {
- "Out There Media": {
- "http://www.out-there-media.com/": [
- "out-there-media.com"
- ]
- }
- },
- {
- "Oversee.net": {
- "http://www.oversee.net/": [
- "dsnextgen.com",
- "oversee.net"
- ]
- }
- },
- {
- "OwnerIQ": {
- "http://www.owneriq.com/": [
- "owneriq.com",
- "owneriq.net"
- ]
- }
- },
- {
- "OxaMedia": {
- "http://www.oxamedia.com/": [
- "adconnexa.com",
- "adsbwm.com",
- "oxamedia.com"
- ]
- }
- },
- {
- "PageFair": {
- "https://pagefair.com/": [
- "pagefair.com",
- "pagefair.net"
- ]
- }
- },
- {
- "Paid-To-Promote.net": {
- "http://www.paid-to-promote.net/": [
- "paid-to-promote.net"
- ]
- }
- },
- {
- "Pardot": {
- "http://www.pardot.com/": [
- "pardot.com"
- ]
- }
- },
- {
- "PayHit": {
- "http://www.payhit.com/": [
- "payhit.com"
- ]
- }
- },
- {
- "Paypopup.com": {
- "http://www.paypopup.com/": [
- "lzjl.com",
- "paypopup.com"
- ]
- }
- },
- {
- "PebblePost": {
- "https://www.pebblepost.com/": [
- "pbbl.co"
- ]
- }
- },
- {
- "Peer39": {
- "http://www.peer39.com/": [
- "peer39.com",
- "peer39.net"
- ]
- }
- },
- {
- "PeerFly": {
- "http://peerfly.com/": [
- "peerfly.com"
- ]
- }
- },
- {
- "Performancing": {
- "http://performancing.com/": [
- "performancing.com"
- ]
- }
- },
- {
- "PerimeterX": {
- "https://www.perimeterx.com": [
- "perimeterx.net"
- ]
- }
- },
- {
- "Pheedo": {
- "http://site.pheedo.com/": [
- "pheedo.com"
- ]
- }
- },
- {
- "Pictela": {
- "http://www.pictela.com/": [
- "pictela.com",
- "pictela.net"
- ]
- }
- },
- {
- "PinPoll": {
- "https://pinpoll.com/": [
- "pinpoll.com"
- ]
- }
- },
- {
- "Pixel.sg": {
- "http://www.pixel.sg/": [
- "pixel.sg"
- ]
- }
- },
- {
- "Piximedia": {
- "http://www.piximedia.com/": [
- "piximedia.com"
- ]
- }
- },
- {
- "Pixlee": {
- "https://www.pixlee.com/": [
- "pixlee.com"
- ]
- }
- },
- {
- "PLATFORM ONE": {
- "http://www.platform-one.co.jp/": [
- "platform-one.co.jp"
- ]
- }
- },
- {
- "plista": {
- "http://www.plista.com/": [
- "plista.com"
- ]
- }
- },
- {
- "PocketCents": {
- "http://pocketcents.com/": [
- "pocketcents.com"
- ]
- }
- },
- {
- "Polar Mobile": {
- "http://polarmobile.com": [
- "mediavoice.com",
- "polarmobile.com"
- ]
- }
- },
- {
- "Politads": {
- "http://politads.com/": [
- "politads.com"
- ]
- }
- },
- {
- "Polymorph": {
- "http://getpolymorph.com/": [
- "adsnative.com",
- "getpolymorph.com"
- ]
- }
- },
- {
- "Pontiflex": {
- "http://www.pontiflex.com/": [
- "pontiflex.com"
- ]
- }
- },
- {
- "PopAds": {
- "https://www.popads.net/": [
- "popads.net",
- "popadscdn.net"
- ]
- }
- },
- {
- "PopRule": {
- "http://poprule.com/": [
- "gocampaignlive.com",
- "poprule.com"
- ]
- }
- },
- {
- "Popunder.ru": {
- "http://popunder.ru/": [
- "popunder.ru"
- ]
- }
- },
- {
- "Po.st": {
- "http://www.po.st/": [
- "po.st"
- ]
- }
- },
- {
- "Powerlinks": {
- "https://www.powerlinks.com/": [
- "powerlinks.com"
- ]
- }
- },
- {
- "PPCProtect": {
- "https://ppcprotect.com": [
- "ppcprotect.com"
- ]
- }
- },
- {
- "PrecisionClick": {
- "http://www.precisionclick.com/": [
- "precisionclick.com"
- ]
- }
- },
- {
- "PredictAd": {
- "http://www.predictad.com/": [
- "predictad.com"
- ]
- }
- },
- {
- "Pressflex": {
- "http://www.pressflex.com/": [
- "blogads.com",
- "pressflex.com"
- ]
- }
- },
- {
- "Prime Visibility": {
- "http://www.primevisibility.com/": [
- "adcde.com",
- "addlvr.com",
- "adonnetwork.com",
- "adonnetwork.net",
- "adtrgt.com",
- "bannertgt.com",
- "cptgt.com",
- "cpvfeed.com",
- "cpvtgt.com",
- "dashboardad.net",
- "popcde.com",
- "primevisibility.com",
- "sdfje.com",
- "urtbk.com"
- ]
- }
- },
- {
- "Primis": {
- "https://www.primis.tech": [
- "sekindo.com"
- ]
- }
- },
- {
- "PrismApp": {
- "https://www.prismapp.io/": [
- "prismapp.io"
- ]
- }
- },
- {
- "Proclivity": {
- "http://www.proclivitymedia.com/": [
- "proclivitymedia.com",
- "proclivitysystems.com",
- "pswec.com"
- ]
- }
- },
- {
- "Project Wonderful": {
- "http://www.projectwonderful.com/": [
- "projectwonderful.com"
- ]
- }
- },
- {
- "PrometheusIntelligenceTechnology": {
- "https://prometheusintelligencetechnology.com/": [
- "prometheusintelligencetechnology.com"
- ]
- }
- },
- {
- "Propeller Ads": {
- "http://propellerads.com/": [
- "propellerads.com"
- ]
- }
- },
- {
- "Prosperent": {
- "http://prosperent.com/": [
- "prosperent.com"
- ]
- }
- },
- {
- "Protected Media": {
- "http://www.protected.media/": [
- "ad-score.com",
- "protected.media"
- ]
- }
- },
- {
- "Provers": {
- "http://provers.pro": [
- "provers.pro"
- ]
- }
- },
- {
- "Psonstrentie": {
- "http://psonstrentie.info": [
- "psonstrentie.info"
- ]
- }
- },
- {
- "Public-Idées": {
- "http://www.publicidees.com/": [
- "publicidees.com"
- ]
- }
- },
- {
- "Publishers Clearing House": {
- "http://www.pch.com/": [
- "pch.com"
- ]
- }
- },
- {
- "PubMatic": {
- "http://www.pubmatic.com/": [
- "pubmatic.com",
- "revinet.com"
- ]
- }
- },
- {
- "PulsePoint": {
- "https://www.pulsepoint.com/": [
- "pulsepoint.com"
- ]
- }
- },
- {
- "quadrantOne": {
- "http://www.quadrantone.com/": [
- "quadrantone.com"
- ]
- }
- },
- {
- "Quake Marketing": {
- "http://quakemarketing.com/": [
- "quakemarketing.com"
- ]
- }
- },
- {
- "Quantcast": {
- "http://www.quantcast.com/": [
- "quantcast.com",
- "quantcount.com",
- "quantserve.com"
- ]
- }
- },
- {
- "QuantumAdvertising": {
- "http://quantum-advertising.com": [
- "quantum-advertising.com"
- ]
- }
- },
- {
- "QuinStreet": {
- "http://quinstreet.com/": [
- "qnsr.com",
- "qsstats.com",
- "quinstreet.com"
- ]
- }
- },
- {
- "QUISMA": {
- "https://quisma.com/": [
- "iaded.com",
- "quisma.com",
- "quismatch.com",
- "xaded.com",
- "xmladed.com"
- ]
- }
- },
- {
- "Radial": {
- "https://www.radial.com": [
- "gsicommerce.com",
- "gsimedia.net"
- ]
- }
- },
- {
- "Radiate Media": {
- "http://www.radiatemedia.com/": [
- "matchbin.com",
- "radiatemedia.com"
- ]
- }
- },
- {
- "RadiumOne": {
- "http://www.radiumone.com/": [
- "gwallet.com",
- "radiumone.com"
- ]
- }
- },
- {
- "Radius Marketing": {
- "http://www.radiusmarketing.com/": [
- "radiusmarketing.com"
- ]
- }
- },
- {
- "Rambler": {
- "http://www.rambler.ru/": [
- "rambler.ru"
- ]
- }
- },
- {
- "Rapleaf": {
- "http://www.rapleaf.com/": [
- "rapleaf.com",
- "rlcdn.com"
- ]
- }
- },
- {
- "ReachLocal": {
- "http://www.reachlocal.com/": [
- "reachlocal.com",
- "rlcdn.net"
- ]
- }
- },
- {
- "React2Media": {
- "http://www.react2media.com/": [
- "react2media.com"
- ]
- }
- },
- {
- "Redux Media": {
- "http://reduxmedia.com/": [
- "reduxmedia.com"
- ]
- }
- },
- {
- "Rekko": {
- "http://rekko.com/": [
- "convertglobal.com",
- "rekko.com"
- ]
- }
- },
- {
- "Reklamport": {
- "http://www.reklamport.com/": [
- "reklamport.com"
- ]
- }
- },
- {
- "Reklam Store": {
- "http://reklamstore.com/": [
- "reklamstore.com"
- ]
- }
- },
- {
- "Reklamz": {
- "http://www.reklamz.com/": [
- "reklamz.com"
- ]
- }
- },
- {
- "Relevad": {
- "http://www.relevad.com/": [
- "relestar.com",
- "relevad.com"
- ]
- }
- },
- {
- "Renegade Internet": {
- "http://www.renegadeinternet.com/": [
- "advertserve.com",
- "renegadeinternet.com"
- ]
- }
- },
- {
- "Reporo": {
- "http://www.reporo.com/": [
- "buzzcity.com"
- ]
- }
- },
- {
- "ResolutionMedia": {
- "https://nonstoppartner.net/": [
- "nonstoppartner.net"
- ]
- }
- },
- {
- "Resolution Media": {
- "http://resolutionmedia.com/": [
- "resolutionmedia.com"
- ]
- }
- },
- {
- "Resonate": {
- "http://www.resonateinsights.com/": [
- "reson8.com",
- "resonateinsights.com",
- "resonatenetworks.com"
- ]
- }
- },
- {
- "Responsys": {
- "http://www.responsys.com/": [
- "responsys.com"
- ]
- }
- },
- {
- "ReTargeter": {
- "http://www.retargeter.com/": [
- "retargeter.com"
- ]
- }
- },
- {
- "Retirement Living": {
- "www.retirement-living.com/": [
- "blvdstatus.com",
- "retirement-living.com"
- ]
- }
- },
- {
- "RevContent": {
- "http://revcontent.com/": [
- "revcontent.com"
- ]
- }
- },
- {
- "RevenueMax": {
- "http://revenuemax.de/": [
- "revenuemax.de"
- ]
- }
- },
- {
- "Rhythm": {
- "http://rhythmnewmedia.com/": [
- "1rx.io",
- "rhythmnewmedia.com",
- "rhythmone.com",
- "rhythmxchange.com",
- "rnmd.net"
- ]
- }
- },
- {
- "RichAudience": {
- "https://richaudience.com/": [
- "richaudience.com"
- ]
- }
- },
- {
- "RichRelevance": {
- "http://www.richrelevance.com/": [
- "richrelevance.com"
- ]
- }
- },
- {
- "RightAction": {
- "http://rightaction.com/": [
- "rightaction.com"
- ]
- }
- },
- {
- "RMBN": {
- "http://rmbn.net/": [
- "rmbn.net",
- "rmbn.ru"
- ]
- }
- },
- {
- "RMM": {
- "http://www.rmmonline.com/": [
- "rmmonline.com"
- ]
- }
- },
- {
- "Rocket Fuel": {
- "http://rocketfuel.com/": [
- "rfihub.com",
- "rfihub.net",
- "rocketfuel.com",
- "ru4.com",
- "xplusone.com"
- ]
- }
- },
- {
- "Rovion": {
- "http://www.rovion.com/": [
- "rovion.com"
- ]
- }
- },
- {
- "rtk": {
- "http://rtk.io/": [
- "rtk.io"
- ]
- }
- },
- {
- "RubiconProject": {
- "http://rubiconproject.com/": [
- "adsbyisocket.com",
- "isocket.com",
- "rubiconproject.com"
- ]
- }
- },
- {
- "RunAds": {
- "http://www.runads.com/": [
- "runads.com",
- "rundsp.com"
- ]
- }
- },
- {
- "RuTarget": {
- "http://www.rutarget.ru/": [
- "rutarget.ru"
- ]
- }
- },
- {
- "Sabavision": {
- "http://www.sabavision.com": [
- "sabavision.com"
- ]
- }
- },
- {
- "Sabre": {
- "http://www.sabre.com/": [
- "reztrack.com",
- "sabre.com",
- "sabrehospitality.com"
- ]
- }
- },
- {
- "Salesforce.com": {
- "http://www.salesforce.com/": [
- "salesforce.com"
- ]
- }
- },
- {
- "Samurai Factory": {
- "http://www.samurai-factory.jp/": [
- "samurai-factory.jp",
- "shinobi.jp"
- ]
- }
- },
- {
- "SAP": {
- "https://www.sap.com": [
- "seewhy.com"
- ]
- }
- },
- {
- "Sapient": {
- "http://www.sapient.com/": [
- "bridgetrack.com",
- "sapient.com"
- ]
- }
- },
- {
- "SAS": {
- "http://www.sas.com/": [
- "aimatch.com",
- "sas.com"
- ]
- }
- },
- {
- "Scandinavian AdNetworks": {
- "http://www.scandinavianadnetworks.com/": [
- "scandinavianadnetworks.com"
- ]
- }
- },
- {
- "Scribol": {
- "http://scribol.com/": [
- "scribol.com"
- ]
- }
- },
- {
- "SearchForce": {
- "http://www.searchforce.com/": [
- "searchforce.com",
- "searchforce.net"
- ]
- }
- },
- {
- "Seevast": {
- "http://www.seevast.com/": [
- "kanoodle.com",
- "pulse360.com",
- "seevast.com",
- "syndigonetworks.com"
- ]
- }
- },
- {
- "Selectable Media": {
- "http://selectablemedia.com/": [
- "nabbr.com",
- "selectablemedia.com"
- ]
- }
- },
- {
- "Semantiqo": {
- "http://semantiqo.com/": [
- "semantiqo.com"
- ]
- }
- },
- {
- "Semasio": {
- "http://www.semasio.com/": [
- "semasio.com",
- "semasio.net"
- ]
- }
- },
- {
- "SevenAds": {
- "http://www.sevenads.net/": [
- "sevenads.net"
- ]
- }
- },
- {
- "SexInYourCity": {
- "http://www.sexinyourcity.com/": [
- "sexinyourcity.com"
- ]
- }
- },
- {
- "ShaftTraffic": {
- "https://shafttraffic.com": [
- "libertystmedia.com"
- ]
- }
- },
- {
- "ShareASale": {
- "http://www.shareasale.com/": [
- "shareasale.com"
- ]
- }
- },
- {
- "Sharethrough": {
- "http://sharethrough.com/": [
- "sharethrough.com"
- ]
- }
- },
- {
- "Shopzilla": {
- "http://www.shopzilla.com/": [
- "shopzilla.com"
- ]
- }
- },
- {
- "Shortest": {
- "http://shorte.st/": [
- "shorte.st"
- ]
- }
- },
- {
- "Silverpop": {
- "http://www.silverpop.com/": [
- "mkt51.net",
- "pages05.net",
- "silverpop.com",
- "vtrenz.net"
- ]
- }
- },
- {
- "Simpli.fi": {
- "http://www.simpli.fi/": [
- "simpli.fi"
- ]
- }
- },
- {
- "SiteScout": {
- "http://www.sitescout.com/": [
- "sitescout.com"
- ]
- }
- },
- {
- "Skimlinks": {
- "http://skimlinks.com/": [
- "skimlinks.com",
- "skimresources.com"
- ]
- }
- },
- {
- "Skupe Net": {
- "http://www.skupenet.com/": [
- "adcentriconline.com",
- "skupenet.com"
- ]
- }
- },
- {
- "Smaato": {
- "http://www.smaato.com/": [
- "smaato.com"
- ]
- }
- },
- {
- "SmartAdServer": {
- "http://smartadserver.com/": [
- "smartadserver.com"
- ]
- }
- },
- {
- "SmartyAds": {
- "https://smartyads.com/": [
- "smartyads.com"
- ]
- }
- },
- {
- "Smiley Media": {
- "http://www.smileymedia.com/": [
- "smileymedia.com"
- ]
- }
- },
- {
- "Smowtion": {
- "http://smowtion.com/": [
- "smowtion.com"
- ]
- }
- },
- {
- "Snap": {
- "http://www.snap.com/": [
- "snap.com"
- ]
- }
- },
- {
- "SocialChorus": {
- "http://www.socialchorus.com/": [
- "halogenmediagroup.com",
- "halogennetwork.com",
- "socialchorus.com"
- ]
- }
- },
- {
- "SocialInterface": {
- "http://socialinterface.com/": [
- "ratevoice.com",
- "socialinterface.com"
- ]
- }
- },
- {
- "SocialTwist": {
- "http://tellafriend.socialtwist.com/": [
- "socialtwist.com"
- ]
- }
- },
- {
- "sociomantic labs": {
- "http://www.sociomantic.com/": [
- "sociomantic.com"
- ]
- }
- },
- {
- "Socital": {
- "https://www.socital.com": [
- "socital.com"
- ]
- }
- },
- {
- "Sojern": {
- "https://www.sojern.com": [
- "sojern.com"
- ]
- }
- },
- {
- "SomoAudience": {
- "https://somoaudience.com/": [
- "somoaudience.com"
- ]
- }
- },
- {
- "Sonobi": {
- "http://sonobi.com/": [
- "sonobi.com"
- ]
- }
- },
- {
- "sophus3": {
- "http://www.sophus3.com/": [
- "sophus3.co.uk",
- "sophus3.com"
- ]
- }
- },
- {
- "Sortable": {
- "https://www.sortable.com/": [
- "deployads.com"
- ]
- }
- },
- {
- "Sovrn": {
- "https://www.sovrn.com/": [
- "sovrn.com"
- ]
- }
- },
- {
- "Space Chimp Media": {
- "http://spacechimpmedia.com/": [
- "spacechimpmedia.com"
- ]
- }
- },
- {
- "Sparklit": {
- "http://www.sparklit.com/": [
- "adbutler.com",
- "sparklit.com"
- ]
- }
- },
- {
- "Spark Studios": {
- "http://www.sparkstudios.com/": [
- "sparkstudios.com"
- ]
- }
- },
- {
- "Specific Media": {
- "http://www.specificmedia.com/": [
- "adviva.co.uk",
- "adviva.net",
- "sitemeter.com",
- "specificclick.net",
- "specificmedia.co.uk",
- "specificmedia.com"
- ]
- }
- },
- {
- "Spectate": {
- "http://spectate.com/": [
- "spectate.com"
- ]
- }
- },
- {
- "Sponge": {
- "http://spongegroup.com/": [
- "spongegroup.com"
- ]
- }
- },
- {
- "Spongecell": {
- "http://www.spongecell.com/": [
- "spongecell.com"
- ]
- }
- },
- {
- "SponsorAds": {
- "http://www.sponsorads.de/": [
- "sponsorads.de"
- ]
- }
- },
- {
- "Spot200": {
- "http://spot200.com/": [
- "spot200.com"
- ]
- }
- },
- {
- "SpotX": {
- "https://www.spotx.tv": [
- "spotx.tv"
- ]
- }
- },
- {
- "SpotXchange": {
- "http://www.spotxchange.com/": [
- "spotxchange.com"
- ]
- }
- },
- {
- "SpringServe": {
- "https://springserve.com/": [
- "springserve.com"
- ]
- }
- },
- {
- "StackAdapt": {
- "https://www.stackadapt.com/": [
- "stackadapt.com"
- ]
- }
- },
- {
- "StarGames": {
- "https://www.stargames.net/": [
- "stargamesaffiliate.com"
- ]
- }
- },
- {
- "SteelHouse": {
- "http://www.steelhouse.com/": [
- "steelhouse.com",
- "steelhousemedia.com"
- ]
- }
- },
- {
- "Storygize": {
- "http://www.storygize.com/": [
- "storygize.com",
- "storygize.net"
- ]
- }
- },
- {
- "Streamray": {
- "http://streamray.com/": [
- "cams.com",
- "streamray.com"
- ]
- }
- },
- {
- "StrikeAd": {
- "http://www.strikead.com/": [
- "strikead.com"
- ]
- }
- },
- {
- "StrongMail": {
- "http://www.strongmail.com/": [
- "popularmedia.com"
- ]
- }
- },
- {
- "Struq": {
- "http://struq.com/": [
- "struq.com"
- ]
- }
- },
- {
- "Sublime Skinz": {
- "http://sublime.xyz/": [
- "ayads.co",
- "sublime.xyz"
- ]
- }
- },
- {
- "Suite 66": {
- "http://www.suite66.com/": [
- "suite66.com"
- ]
- }
- },
- {
- "Summit": {
- "http://www.summit.co.uk/": [
- "summitmedia.co.uk"
- ]
- }
- },
- {
- "Superfish": {
- "http://www.superfish.com/": [
- "superfish.com"
- ]
- }
- },
- {
- "SupersonicAds": {
- "http://www.supersonicads.com/": [
- "supersonicads.com"
- ]
- }
- },
- {
- "Survata": {
- "https://www.survata.com/": [
- "survata.com"
- ]
- }
- },
- {
- "Switch": {
- "http://www.switchconcepts.com/": [
- "ethicalads.net",
- "switchadhub.com",
- "switchconcepts.co.uk",
- "switchconcepts.com"
- ]
- }
- },
- {
- "Swoop": {
- "http://swoop.com/": [
- "swoop.com"
- ]
- }
- },
- {
- "SymphonyAM": {
- "http://www.factortg.com/": [
- "factortg.com"
- ]
- }
- },
- {
- "Syncapse": {
- "http://www.syncapse.com/": [
- "clickable.net",
- "syncapse.com"
- ]
- }
- },
- {
- "Syrup Ad": {
- "http://adotsolution.com/": [
- "adotsolution.com"
- ]
- }
- },
- {
- "Taboola": {
- "https://www.taboola.com/": [
- "perfectmarket.com",
- "taboola.com"
- ]
- }
- },
- {
- "Tailsweep": {
- "http://www.tailsweep.com/": [
- "tailsweep.com"
- ]
- }
- },
- {
- "Taleria": {
- "https://outstream.telaria.com/": [
- "freeskreen.com"
- ]
- }
- },
- {
- "Tapad": {
- "http://www.tapad.com/": [
- "tapad.com"
- ]
- }
- },
- {
- "Tapgage": {
- "http://www.tapgage.com/": [
- "bizmey.com",
- "tapgage.com"
- ]
- }
- },
- {
- "TapIt!": {
- "http://tapit.com/": [
- "tapit.com"
- ]
- }
- },
- {
- "Tap.me": {
- "http://tap.me/": [
- "tap.me"
- ]
- }
- },
- {
- "Targetix": {
- "http://targetix.net/": [
- "targetix.net"
- ]
- }
- },
- {
- "Tatto Media": {
- "http://tattomedia.com/": [
- "quicknoodles.com",
- "tattomedia.com"
- ]
- }
- },
- {
- "Teadma": {
- "http://www.teadma.com/": [
- "teadma.com"
- ]
- }
- },
- {
- "Teads.tv": {
- "http://teads.tv/": [
- "ebuzzing.com",
- "teads.tv"
- ]
- }
- },
- {
- "Technorati": {
- "http://technorati.com/": [
- "technorati.com",
- "technoratimedia.com"
- ]
- }
- },
- {
- "TellApart": {
- "http://tellapart.com/": [
- "tellapart.com",
- "tellapt.com"
- ]
- }
- },
- {
- "Telstra": {
- "http://www.telstra.com.au/": [
- "sensis.com.au",
- "sensisdata.com.au",
- "sensisdigitalmedia.com.au",
- "telstra.com.au"
- ]
- }
- },
- {
- "Terra": {
- "http://www.terra.com.br/": [
- "eztargetmedia.com",
- "terra.com.br"
- ]
- }
- },
- {
- "The Numa Group": {
- "http://www.thenumagroup.com/": [
- "hittail.com",
- "thenumagroup.com"
- ]
- }
- },
- {
- "The Search Agency": {
- "http://www.thesearchagency.com/": [
- "thesearchagency.com",
- "thesearchagency.net"
- ]
- }
- },
- {
- "The Trade Desk": {
- "http://thetradedesk.com/": [
- "adsrvr.org",
- "thetradedesk.com"
- ]
- }
- },
- {
- "Think Realtime": {
- "http://www.thinkrealtime.com/": [
- "echosearch.com",
- "esm1.net",
- "thinkrealtime.com"
- ]
- }
- },
- {
- "Tinder": {
- "http://tinder.com/": [
- "carbonads.com",
- "tinder.com"
- ]
- }
- },
- {
- "TiqIQ": {
- "http://www.tiqiq.com/": [
- "tiqiq.com"
- ]
- }
- },
- {
- "Tisoomi": {
- "http://www.tisoomi.com/": [
- "adternal.com",
- "tisoomi.com"
- ]
- }
- },
- {
- "TLVMedia": {
- "http://tlvmedia.com/": [
- "tlvmedia.com"
- ]
- }
- },
- {
- "Todacell": {
- "http://www.todacell.com/": [
- "todacell.com"
- ]
- }
- },
- {
- "ToneFuse": {
- "http://tonefuse.com/": [
- "tonefuse.com"
- ]
- }
- },
- {
- "ToneMedia": {
- "http://tonemedia.com/": [
- "clickfuse.com",
- "tonemedia.com"
- ]
- }
- },
- {
- "TouchCommerce": {
- "http://www.touchcommerce.com/": [
- "inq.com",
- "touchcommerce.com"
- ]
- }
- },
- {
- "TrackingSoft": {
- "http://trackingsoft.com/": [
- "trackingsoft.com"
- ]
- }
- },
- {
- "Tradedoubler": {
- "http://www.tradedoubler.com/": [
- "tradedoubler.com"
- ]
- }
- },
- {
- "TradeTracker": {
- "http://www.tradetracker.com/": [
- "tradetracker.com",
- "tradetracker.net"
- ]
- }
- },
- {
- "TrafficHaus": {
- "http://www.traffichaus.com/": [
- "traffichaus.com",
- "traffichouse.com"
- ]
- }
- },
- {
- "TrafficRevenue": {
- "http://www.trafficrevenue.net/": [
- "trafficrevenue.net"
- ]
- }
- },
- {
- "Traffiq": {
- "http://www.traffiq.com/": [
- "traffiq.com"
- ]
- }
- },
- {
- "Trafmag": {
- "http://trafmag.com/": [
- "trafmag.com"
- ]
- }
- },
- {
- "Traverse": {
- "http://www.traversedata.com/": [
- "traversedlp.com"
- ]
- }
- },
- {
- "Travora Media": {
- "http://www.travoramedia.com/": [
- "traveladnetwork.com",
- "traveladvertising.com",
- "travoramedia.com"
- ]
- }
- },
- {
- "Tremor Video": {
- "http://www.tremorvideo.com/": [
- "scanscout.com",
- "tmnetads.com",
- "tremorhub.com",
- "tremormedia.com",
- "tremorvideo.com"
- ]
- }
- },
- {
- "Triggit": {
- "http://triggit.com/": [
- "triggit.com"
- ]
- }
- },
- {
- "TripleLift": {
- "http://triplelift.com/": [
- "3lift.com",
- "triplelift.com"
- ]
- }
- },
- {
- "TruEffect": {
- "http://www.trueffect.com/": [
- "adlegend.com",
- "trueffect.com"
- ]
- }
- },
- {
- "TrustX": {
- "https://trustx.org/": [
- "trustx.org"
- ]
- }
- },
- {
- "TubeMogul": {
- "http://www.tubemogul.com/": [
- "tmogul.com",
- "tubemogul.com"
- ]
- }
- },
- {
- "Twelvefold": {
- "http://www.twelvefold.com/": [
- "buzzlogic.com",
- "twelvefold.com"
- ]
- }
- },
- {
- "Twitter": {
- "https://twitter.com/": [
- "ads-twitter.com"
- ]
- }
- },
- {
- "Twyn Group": {
- "http://www.twyn.com/": [
- "twyn-group.com",
- "twyn.com"
- ]
- }
- },
- {
- "Tyroo": {
- "http://www.tyroo.com/": [
- "tyroo.com"
- ]
- }
- },
- {
- "ucfunnel": {
- "https://www.ucfunnel.com/": [
- "aralego.com",
- "ucfunnel.com"
- ]
- }
- },
- {
- "uCoz": {
- "http://www.ucoz.com/": [
- "ucoz.ae",
- "ucoz.br",
- "ucoz.com",
- "ucoz.du",
- "ucoz.fr",
- "ucoz.net",
- "ucoz.ru"
- ]
- }
- },
- {
- "Unanimis": {
- "http://www.unanimis.co.uk/": [
- "unanimis.co.uk"
- ]
- }
- },
- {
- "Underdog Media": {
- "http://www.underdogmedia.com/": [
- "udmserve.net",
- "underdogmedia.com"
- ]
- }
- },
- {
- "Undertone": {
- "http://www.undertone.com/": [
- "undertone.com",
- "undertonenetworks.com",
- "undertonevideo.com"
- ]
- }
- },
- {
- "UniQlick": {
- "http://www.uniqlick.com/": [
- "51network.com",
- "uniqlick.com",
- "wanmo.com"
- ]
- }
- },
- {
- "Unruly": {
- "https://unruly.co/": [
- "unrulymedia.com"
- ]
- }
- },
- {
- "Upland": {
- "https://uplandsoftware.com/": [
- "leadlander.com",
- "trackalyzer.com"
- ]
- }
- },
- {
- "up-value": {
- "http://www.up-value.de/": [
- "up-value.de"
- ]
- }
- },
- {
- "Value Ad": {
- "http://valuead.com/": [
- "valuead.com"
- ]
- }
- },
- {
- "Various": {
- "http://www.various.com/": [
- "amigos.com",
- "getiton.com",
- "medley.com",
- "nostringsattached.com",
- "various.com"
- ]
- }
- },
- {
- "Vdopia": {
- "http://www.vdopia.com/": [
- "ivdopia.com",
- "vdopia.com"
- ]
- }
- },
- {
- "Veeseo": {
- "http://veeseo.com": [
- "veeseo.com"
- ]
- }
- },
- {
- "Velocity Media": {
- "http://adsvelocity.com/": [
- "adsvelocity.com"
- ]
- }
- },
- {
- "Velti": {
- "http://www.velti.com/": [
- "mobclix.com",
- "velti.com"
- ]
- }
- },
- {
- "Vemba": {
- "https://www.vemba.com/": [
- "vemba.com"
- ]
- }
- },
- {
- "Venatus Media": {
- "http://venatusmedia.com": [
- "venatusmedia.com"
- ]
- }
- },
- {
- "Vendemore": {
- "https://vendemore.com/": [
- "vendemore.com"
- ]
- }
- },
- {
- "Vendio": {
- "http://www.vendio.com/": [
- "singlefeed.com",
- "vendio.com"
- ]
- }
- },
- {
- "Veoxa": {
- "http://www.veoxa.com/": [
- "veoxa.com"
- ]
- }
- },
- {
- "Veremedia": {
- "http://www.veremedia.com/": [
- "veremedia.com"
- ]
- }
- },
- {
- "VerticalHealth": {
- "https://www.verticalhealth.com/": [
- "verticalhealth.net"
- ]
- }
- },
- {
- "VerticalResponse": {
- "http://www.verticalresponse.com/": [
- "verticalresponse.com",
- "vresp.com"
- ]
- }
- },
- {
- "Vibrant Media": {
- "http://www.vibrantmedia.com/": [
- "intellitxt.com",
- "picadmedia.com",
- "vibrantmedia.com"
- ]
- }
- },
- {
- "VideoIntelligence": {
- "https://www.vi.ai/": [
- "vi.ai"
- ]
- }
- },
- {
- "VigLink": {
- "http://www.viglink.com/": [
- "viglink.com"
- ]
- }
- },
- {
- "VisibleBrands": {
- "http://www.visbrands.com/": [
- "visbrands.com"
- ]
- }
- },
- {
- "Visible Measures": {
- "http://www.visiblemeasures.com/": [
- "viewablemedia.net",
- "visiblemeasures.com"
- ]
- }
- },
- {
- "VisualDNA": {
- "http://www.visualdna.com/": [
- "vdna-assets.com",
- "visualdna-stats.com",
- "visualdna.com"
- ]
- }
- },
- {
- "Vizu": {
- "http://www.vizu.com/": [
- "vizu.com"
- ]
- }
- },
- {
- "Vizury": {
- "http://www.vizury.com/": [
- "vizury.com"
- ]
- }
- },
- {
- "Vserv": {
- "http://www.vserv.com/": [
- "vserv.com",
- "vserv.mobi"
- ]
- }
- },
- {
- "Vuble": {
- "https://vuble.tv/us/": [
- "mediabong.com"
- ]
- }
- },
- {
- "Wahoha": {
- "http://wahoha.com/": [
- "contentwidgets.net",
- "wahoha.com"
- ]
- }
- },
- {
- "Wayfair": {
- "https://www.wayfair.com/": [
- "wayfair.com"
- ]
- }
- },
- {
- "WebAds": {
- "http://www.webads.co.uk/": [
- "webads.co.uk"
- ]
- }
- },
- {
- "Web.com": {
- "http://www.web.com/": [
- "feedperfect.com",
- "web.com"
- ]
- }
- },
- {
- "WebGozar.com": {
- "http://www.webgozar.com/": [
- "webgozar.com",
- "webgozar.ir"
- ]
- }
- },
- {
- "Webmecanik": {
- "https://www.webmecanik.com/": [
- "webmecanik.com"
- ]
- }
- },
- {
- "WebMetro": {
- "http://www.webmetro.com/": [
- "dsmmadvantage.com",
- "webmetro.com"
- ]
- }
- },
- {
- "Weborama": {
- "http://weborama.com/": [
- "weborama.com",
- "weborama.fr"
- ]
- }
- },
- {
- "Webtraffic": {
- "http://www.webtraffic.se/": [
- "webtraffic.no",
- "webtraffic.se"
- ]
- }
- },
- {
- "WideOrbit": {
- "https://www.wideorbit.com/": [
- "dep-x.com"
- ]
- }
- },
- {
- "WiredMinds": {
- "http://www.wiredminds.com/": [
- "wiredminds.com",
- "wiredminds.de"
- ]
- }
- },
- {
- "Wishabi": {
- "http://wishabi.com": [
- "wishabi.com",
- "wishabi.net"
- ]
- }
- },
- {
- "WordStream": {
- "http://www.wordstream.com/": [
- "wordstream.com"
- ]
- }
- },
- {
- "WPP": {
- "http://www.wpp.com/": [
- "247realmedia.com",
- "accelerator-media.com",
- "acceleratorusa.com",
- "decdna.net",
- "decideinteractive.com",
- "gmads.net",
- "groupm.com",
- "kantarmedia.com",
- "mecglobal.com",
- "mindshare.nl",
- "mookie1.com",
- "pm14.com",
- "realmedia.com",
- "targ.ad",
- "themig.com",
- "wpp.com",
- "xaxis.com"
- ]
- }
- },
- {
- "xAd": {
- "http://www.xad.com/": [
- "xad.com"
- ]
- }
- },
- {
- "Xertive Media": {
- "http://www.xertivemedia.com/": [
- "admanager-xertive.com",
- "xertivemedia.com"
- ]
- }
- },
- {
- "xplosion interactive": {
- "http://www.xplosion.de/": [
- "xplosion.de"
- ]
- }
- },
- {
- "Xrost DS": {
- "http://www.adplan-ds.com/": [
- "adplan-ds.com"
- ]
- }
- },
- {
- "Yabuka": {
- "http://www.yabuka.com/": [
- "yabuka.com"
- ]
- }
- },
- {
- "Yahoo!": {
- "http://www.yahoo.com/": [
- "adinterax.com",
- "adrevolver.com",
- "ads.yahoo.com",
- "adserver.yahoo.com",
- "advertising.yahoo.com",
- "bluelithium.com",
- "dapper.net",
- "flurry.com",
- "interclick.com",
- "marketingsolutions.yahoo.com",
- "overture.com",
- "rightmedia.com",
- "rmxads.com",
- "secure-adserver.com",
- "thewheelof.com",
- "yieldmanager.com",
- "yieldmanager.net",
- "yldmgrimg.net"
- ]
- }
- },
- {
- "Yandex": {
- "http://www.yandex.com/": [
- "adfox.yandex.ru",
- "an.yandex.ru",
- "awaps.yandex.ru",
- "mc.yandex.ru",
- "moikrug.ru",
- "web-visor.com",
- "yandex.ru/clck/click",
- "yandex.ru/clck/counter",
- "yandex.ru/cycounter",
- "yandex.ru/portal/set/any",
- "yandex.ru/set/s/rsya-tag-users/data"
- ]
- }
- },
- {
- "Ybrant Digital": {
- "http://www.ybrantdigital.com/": [
- "addynamix.com",
- "adserverplus.com",
- "oridian.com",
- "ybrantdigital.com"
- ]
- }
- },
- {
- "YD": {
- "http://www.ydworld.com/": [
- "ydworld.com",
- "yieldivision.com"
- ]
- }
- },
- {
- "YellowHammer": {
- "http://www.yhmg.com/": [
- "attracto.com",
- "clickhype.com",
- "yellowhammermg.com",
- "yhmg.com"
- ]
- }
- },
- {
- "Yes Ads": {
- "http://yesads.com/": [
- "yesads.com"
- ]
- }
- },
- {
- "YieldAds": {
- "http://yieldads.com/": [
- "yieldads.com"
- ]
- }
- },
- {
- "YieldBids": {
- "http://ybx.io/": [
- "ybx.io"
- ]
- }
- },
- {
- "YieldBot": {
- "http://yieldbot.com/": [
- "yldbt.com"
- ]
- }
- },
- {
- "YieldBuild": {
- "http://yieldbuild.com/": [
- "yieldbuild.com"
- ]
- }
- },
- {
- "Yieldify": {
- "https://www.yieldify.com/": [
- "yieldify.com"
- ]
- }
- },
- {
- "Yieldlab": {
- "http://www.yieldlab.de/": [
- "yieldlab.de",
- "yieldlab.net"
- ]
- }
- },
- {
- "Yieldmo": {
- "https://yieldmo.com": [
- "yieldmo.com"
- ]
- }
- },
- {
- "YieldNexus": {
- "https://www.yieldnexus.com/": [
- "ynxs.io"
- ]
- }
- },
- {
- "YOC": {
- "http://group.yoc.com/": [
- "yoc-performance.com",
- "yoc.com"
- ]
- }
- },
- {
- "Yoggrt": {
- "http://www.yoggrt.com/": [
- "yoggrt.com"
- ]
- }
- },
- {
- "youknowbest": {
- "http://www.youknowbest.com/": [
- "youknowbest.com"
- ]
- }
- },
- {
- "YuMe": {
- "http://www.yume.com/": [
- "yume.com",
- "yumenetworks.com"
- ]
- }
- },
- {
- "ZafulAffiliate": {
- "https://affiliate.zaful.com/": [
- "affasi.com",
- "gw-ec.com",
- "zaful.com"
- ]
- }
- },
- {
- "Zango": {
- "http://www.zango.com/": [
- "metricsdirect.com",
- "zango.com"
- ]
- }
- },
- {
- "zanox": {
- "http://www.zanox.com/": [
- "buy.at",
- "zanox-affiliate.de",
- "zanox.com"
- ]
- }
- },
- {
- "zapunited": {
- "http://www.zapunited.com/": [
- "zaparena.com",
- "zapunited.com"
- ]
- }
- },
- {
- "ZEDO": {
- "http://www.zedo.com/": [
- "zedo.com",
- "zincx.com"
- ]
- }
- },
- {
- "Zefir": {
- "https://ze-fir.com/": [
- "ze-fir.com"
- ]
- }
- },
- {
- "Zemanta": {
- "http://www.zemanta.com/": [
- "zemanta.com"
- ]
- }
- },
- {
- "ZestAd": {
- "http://www.zestad.com/": [
- "zestad.com"
- ]
- }
- },
- {
- "Zeta Email Solutions": {
- "http://www.zetaemailsolutions.com/": [
- "insightgrit.com",
- "zetaemailsolutions.com"
- ]
- }
- },
- {
- "Zumobi": {
- "http://www.zumobi.com/": [
- "zumobi.com"
- ]
- }
- },
- {
- "ZypMedia": {
- "http://www.zypmedia.com/": [
- "extend.tv",
- "zypmedia.com"
- ]
- }
- }
- ],
- "Content": [
- {
- "33Across": {
- "http://33across.com/": [
- "tynt.com"
- ]
- }
- },
- {
- "ActivEngage": {
- "http://www.activengage.com/": [
- "activengage.com"
- ]
- }
- },
- {
- "Adap.tv": {
- "http://adap.tv/": [
- "adap.tv"
- ]
- }
- },
- {
- "Adobe": {
- "http://www.adobe.com/": [
- "adobe.com",
- "fyre.co",
- "livefyre.com",
- "typekit.com"
- ]
- }
- },
- {
- "Akamai": {
- "http://www.akamai.com/": [
- "abmr.net",
- "akamai.com",
- "edgesuite.net"
- ]
- }
- },
- {
- "AKQA": {
- "http://www.akqa.com/": [
- "akqa.com",
- "srtk.net"
- ]
- }
- },
- {
- "Amazon.com": {
- "http://www.amazon.com/": [
- "alexa.com",
- "amazon.com",
- "cloudfront.net"
- ]
- }
- },
- {
- "AOL": {
- "http://www.aol.com/": [
- "5min.com",
- "aim.com",
- "aol.com",
- "aolanswers.com",
- "aolcdn.com",
- "aoltechguru.com",
- "autoblog.com",
- "cambio.com",
- "dailyfinance.com",
- "editions.com",
- "engadget.com",
- "games.com",
- "homesessive.com",
- "huffingtonpost.com",
- "joystiq.com",
- "kitchendaily.com",
- "makers.com",
- "mandatory.com",
- "mapquest.com",
- "moviefone.com",
- "noisecreep.com",
- "patch.com",
- "pawnation.com",
- "shortcuts.com",
- "shoutcast.com",
- "spinner.com",
- "stylelist.com",
- "stylemepretty.com",
- "surphace.com",
- "techcrunch.com",
- "theboombox.com",
- "theboot.com",
- "tuaw.com",
- "userplane.com",
- "winamp.com"
- ]
- }
- },
- {
- "Automattic": {
- "http://automattic.com/": [
- "automattic.com",
- "gravatar.com",
- "intensedebate.com"
- ]
- }
- },
- {
- "Baynote": {
- "http://www.baynote.com/": [
- "baynote.com",
- "baynote.net"
- ]
- }
- },
- {
- "Bazaarvoice": {
- "http://www.bazaarvoice.com/": [
- "bazaarvoice.com"
- ]
- }
- },
- {
- "BigDoor": {
- "http://www.bigdoor.com/": [
- "bigdoor.com",
- "onetruefan.com"
- ]
- }
- },
- {
- "Brightcove": {
- "http://www.brightcove.com/": [
- "brightcove.com"
- ]
- }
- },
- {
- "Browser-Update.org": {
- "www.browser-update.org/": [
- "browser-update.org"
- ]
- }
- },
- {
- "BTBuckets": {
- "http://btbuckets.com/": [
- "btbuckets.com"
- ]
- }
- },
- {
- "Buffer": {
- "http://bufferapp.com/": [
- "bufferapp.com"
- ]
- }
- },
- {
- "Bunchball": {
- "http://www.bunchball.com/": [
- "bunchball.com"
- ]
- }
- },
- {
- "buySAFE": {
- "http://www.buysafe.com/": [
- "buysafe.com"
- ]
- }
- },
- {
- "BuzzFeed": {
- "http://www.buzzfeed.com/": [
- "buzzfed.com",
- "buzzfeed.com"
- ]
- }
- },
- {
- "Cbox": {
- "http://www.cbox.ws/": [
- "cbox.ws"
- ]
- }
- },
- {
- "CBS Interactive": {
- "http://www.cbsinteractive.com/": [
- "cbsinteractive.com",
- "com.com"
- ]
- }
- },
- {
- "Cedexis": {
- "http://www.cedexis.com/": [
- "cedexis.com",
- "cedexis.net"
- ]
- }
- },
- {
- "Certona": {
- "http://www.certona.com/": [
- "certona.com",
- "res-x.com"
- ]
- }
- },
- {
- "ClipSyndicate": {
- "http://www.clipsyndicate.com/": [
- "clipsyndicate.com"
- ]
- }
- },
- {
- "Collarity": {
- "http://www.collarity.com/": [
- "collarity.com"
- ]
- }
- },
- {
- "Conduit": {
- "http://www.conduit.com/": [
- "conduit-banners.com",
- "conduit-services.com",
- "conduit.com",
- "wibiya.com"
- ]
- }
- },
- {
- "Congoo": {
- "http://www.congoo.com/": [
- "congoo.com"
- ]
- }
- },
- {
- "Contact At Once!": {
- "http://www.contactatonce.com/": [
- "contactatonce.com"
- ]
- }
- },
- {
- "Conviva": {
- "http://www.conviva.com/": [
- "conviva.com"
- ]
- }
- },
- {
- "DailyMe": {
- "http://dailyme.com/": [
- "dailyme.com",
- "newstogram.com"
- ]
- }
- },
- {
- "DataSift": {
- "http://datasift.com/": [
- "datasift.com",
- "tweetmeme.com"
- ]
- }
- },
- {
- "Disqus": {
- "http://disqus.com/": [
- "disqus.com"
- ]
- }
- },
- {
- "Echo": {
- "http://aboutecho.com/": [
- "aboutecho.com",
- "haloscan.com",
- "js-kit.com"
- ]
- }
- },
- {
- "Facebook": {
- "http://www.facebook.com/": [
- "fbcdn.net",
- "instagram.com",
- "messenger.com"
- ]
- }
- },
- {
- "Flattr": {
- "http://flattr.com/": [
- "flattr.com"
- ]
- }
- },
- {
- "FreeWheel": {
- "http://www.freewheel.tv/": [
- "freewheel.tv",
- "fwmrm.net"
- ]
- }
- },
- {
- "Genius.com": {
- "http://www.genius.com/": [
- "genius.com"
- ]
- }
- },
- {
- "Get Satisfaction": {
- "https://getsatisfaction.com/": [
- "getsatisfaction.com"
- ]
- }
- },
- {
- "Gigya": {
- "http://www.gigya.com/": [
- "gigcount.com",
- "gigya.com"
- ]
- }
- },
- {
- "Global Takeoff": {
- "http://www.globaltakeoff.com/": [
- "globaltakeoff.com",
- "globaltakeoff.net"
- ]
- }
- },
- {
- "GoGrid": {
- "http://www.gogrid.com/": [
- "formalyzer.com",
- "gogrid.com",
- "komli.net"
- ]
- }
- },
- {
- "Google": {
- "http://www.google.com/": [
- "accounts.google.com",
- "apis.google.com",
- "appengine.google.com",
- "apture.com",
- "blogger.com",
- "books.google.com",
- "checkout.google.com",
- "chrome.google.com",
- "code.google.com",
- "codesearch.google.com",
- "docs.google.com",
- "drive.google.com",
- "earth.google.com",
- "encrypted.google.com",
- "feedburner.com",
- "feedburner.google.com",
- "feedproxy.google.com",
- "finance.google.com",
- "ggpht.com",
- "gmodules.com",
- "google-melange.com",
- "google.ad",
- "google.ae",
- "google.al",
- "google.am",
- "google.as",
- "google.at",
- "google.az",
- "google.ba",
- "google.be",
- "google.bf",
- "google.bg",
- "google.bi",
- "google.bj",
- "google.bs",
- "google.bt",
- "google.by",
- "google.ca",
- "google.cat",
- "google.cd",
- "google.cf",
- "google.cg",
- "google.ch",
- "google.ci",
- "google.cl",
- "google.cm",
- "google.cn",
- "google.co.ao",
- "google.co.bw",
- "google.co.ck",
- "google.co.cr",
- "google.co.id",
- "google.co.il",
- "google.co.in",
- "google.co.jp",
- "google.co.ke",
- "google.co.kr",
- "google.co.ls",
- "google.co.ma",
- "google.co.mz",
- "google.co.nz",
- "google.co.th",
- "google.co.tz",
- "google.co.ug",
- "google.co.uk",
- "google.co.uz",
- "google.co.ve",
- "google.co.vi",
- "google.co.za",
- "google.co.zm",
- "google.co.zw",
- "google.com",
- "google.com.af",
- "google.com.ag",
- "google.com.ai",
- "google.com.ar",
- "google.com.au",
- "google.com.bd",
- "google.com.bh",
- "google.com.bn",
- "google.com.bo",
- "google.com.br",
- "google.com.bz",
- "google.com.co",
- "google.com.cu",
- "google.com.cy",
- "google.com.do",
- "google.com.ec",
- "google.com.eg",
- "google.com.et",
- "google.com.fj",
- "google.com.gh",
- "google.com.gi",
- "google.com.gt",
- "google.com.hk",
- "google.com.jm",
- "google.com.kh",
- "google.com.kw",
- "google.com.lb",
- "google.com.ly",
- "google.com.mm",
- "google.com.mt",
- "google.com.mx",
- "google.com.my",
- "google.com.na",
- "google.com.nf",
- "google.com.ng",
- "google.com.ni",
- "google.com.np",
- "google.com.om",
- "google.com.pa",
- "google.com.pe",
- "google.com.pg",
- "google.com.ph",
- "google.com.pk",
- "google.com.pr",
- "google.com.py",
- "google.com.qa",
- "google.com.sa",
- "google.com.sb",
- "google.com.sg",
- "google.com.sl",
- "google.com.sv",
- "google.com.tj",
- "google.com.tr",
- "google.com.tw",
- "google.com.ua",
- "google.com.uy",
- "google.com.vc",
- "google.com.vn",
- "google.cv",
- "google.cz",
- "google.de",
- "google.dj",
- "google.dk",
- "google.dm",
- "google.dz",
- "google.ee",
- "google.es",
- "google.fi",
- "google.fm",
- "google.fr",
- "google.ga",
- "google.ge",
- "google.gg",
- "google.gl",
- "google.gm",
- "google.gp",
- "google.gr",
- "google.gy",
- "google.hn",
- "google.hr",
- "google.ht",
- "google.hu",
- "google.ie",
- "google.im",
- "google.iq",
- "google.is",
- "google.it",
- "google.je",
- "google.jo",
- "google.kg",
- "google.ki",
- "google.kz",
- "google.la",
- "google.li",
- "google.lk",
- "google.lt",
- "google.lu",
- "google.lv",
- "google.md",
- "google.me",
- "google.mg",
- "google.mk",
- "google.ml",
- "google.mn",
- "google.ms",
- "google.mu",
- "google.mv",
- "google.mw",
- "google.ne",
- "google.nl",
- "google.no",
- "google.nr",
- "google.nu",
- "google.pl",
- "google.pn",
- "google.ps",
- "google.pt",
- "google.ro",
- "google.rs",
- "google.ru",
- "google.rw",
- "google.sc",
- "google.se",
- "google.sh",
- "google.si",
- "google.sk",
- "google.sm",
- "google.sn",
- "google.so",
- "google.st",
- "google.td",
- "google.tg",
- "google.tk",
- "google.tl",
- "google.tm",
- "google.tn",
- "google.to",
- "google.tt",
- "google.vg",
- "google.vu",
- "google.ws",
- "googleapis.com",
- "googleartproject.com",
- "googleusercontent.com",
- "groups.google.com",
- "gstatic.com",
- "health.google.com",
- "images.google.com",
- "investor.google.com",
- "knol.google.com",
- "maps.google.com",
- "music.google.com",
- "news.google.com",
- "panoramio.com",
- "picasa.google.com",
- "picasaweb.google.com",
- "play.google.com",
- "postini.com",
- "recaptcha.net",
- "script.google.com",
- "shopping.google.com",
- "sites.google.com",
- "sketchup.google.com",
- "support.google.com",
- "talk.google.com",
- "talkgadget.google.com",
- "toolbar.google.com",
- "translate.google.com",
- "trends.google.com",
- "video.google.com",
- "videos.google.com",
- "wallet.google.com",
- "youtube.com"
- ]
- }
- },
- {
- "Gravity": {
- "http://www.gravity.com/": [
- "gravity.com",
- "grvcdn.com"
- ]
- }
- },
- {
- "Heyzap": {
- "http://www.heyzap.com/": [
- "heyzap.com"
- ]
- }
- },
- {
- "HubSpot": {
- "http://www.hubspot.com/": [
- "hubspot.com"
- ]
- }
- },
- {
- "IBM": {
- "http://www.ibm.com/": [
- "xtify.com"
- ]
- }
- },
- {
- "iovation": {
- "http://www.iovation.com/": [
- "iesnare.com",
- "iovation.com"
- ]
- }
- },
- {
- "Kaltura": {
- "http://corp.kaltura.com/": [
- "kaltura.com"
- ]
- }
- },
- {
- "kikin": {
- "http://www.kikin.com/": [
- "kikin.com"
- ]
- }
- },
- {
- "Limelight Networks": {
- "http://www.limelight.com/": [
- "clickability.com",
- "limelight.com",
- "llnwd.net"
- ]
- }
- },
- {
- "LivePerson": {
- "http://www.liveperson.net/": [
- "liveperson.net"
- ]
- }
- },
- {
- "LiveRail": {
- "http://liverail.com/": [
- "liverail.com"
- ]
- }
- },
- {
- "LongTail Video": {
- "http://www.longtailvideo.com/": [
- "longtailvideo.com",
- "ltassrv.com"
- ]
- }
- },
- {
- "Markit": {
- "http://www.markit.com/": [
- "markit.com",
- "wsod.com"
- ]
- }
- },
- {
- "MashLogic": {
- "http://www.mashlogic.com/": [
- "mashlogic.com"
- ]
- }
- },
- {
- "McAfee": {
- "http://www.mcafee.com/": [
- "mcafee.com",
- "scanalert.com"
- ]
- }
- },
- {
- "Microsoft": {
- "http://www.microsoft.com/": [
- "bing.com",
- "gamesforwindows.com",
- "getgamesmart.com",
- "healthvault.com",
- "ieaddons.com",
- "iegallery.com",
- "live.com",
- "microsoft.com",
- "microsoftalumni.com",
- "microsoftalumni.org",
- "microsoftstore.com",
- "msn.com",
- "msndirect.com",
- "office.com",
- "officelive.com",
- "outlook.com",
- "s-msn.com",
- "skype.com",
- "windowsphone.com",
- "worldwidetelescope.org",
- "xbox.com",
- "zune.com",
- "zune.net"
- ]
- }
- },
- {
- "NDN": {
- "http://www.newsinc.com/": [
- "newsinc.com"
- ]
- }
- },
- {
- "Oberon Media": {
- "http://www.oberon-media.com/": [
- "blaze.com",
- "oberon-media.com"
- ]
- }
- },
- {
- "Ooyala": {
- "http://www.ooyala.com/": [
- "oo4.com",
- "ooyala.com"
- ]
- }
- },
- {
- "Oracle": {
- "http://www.oracle.com/": [
- "atgsvcs.com",
- "instantservice.com",
- "istrack.com",
- "oracle.com"
- ]
- }
- },
- {
- "Peerius": {
- "http://www.peerius.com/": [
- "peerius.com"
- ]
- }
- },
- {
- "Pinterest": {
- "http://pinterest.com/": [
- "pinimg.com",
- "pinterest.com"
- ]
- }
- },
- {
- "PunchTab": {
- "http://www.punchtab.com/": [
- "punchtab.com"
- ]
- }
- },
- {
- "RIM": {
- "http://www.rim.com/": [
- "rim.com",
- "scoreloop.com"
- ]
- }
- },
- {
- "Salesforce.com": {
- "http://www.salesforce.com/": [
- "salesforceliveagent.com"
- ]
- }
- },
- {
- "SAY": {
- "http://saymedia.com/": [
- "saymedia.com",
- "typepad.com",
- "videoegg.com"
- ]
- }
- },
- {
- "ScribeFire": {
- "http://www.scribefire.com/": [
- "scribefire.com"
- ]
- }
- },
- {
- "Six Apart": {
- "http://www.sixapart.com/": [
- "sixapart.com"
- ]
- }
- },
- {
- "Skribit": {
- "http://skribit.com/": [
- "skribit.com"
- ]
- }
- },
- {
- "SnapEngage": {
- "http://www.snapengage.com/": [
- "snapengage.com"
- ]
- }
- },
- {
- "Spring Metrics": {
- "http://www.springmetrics.com/": [
- "springmetrics.com"
- ]
- }
- },
- {
- "Synacor": {
- "http://www.synacor.com/": [
- "synacor.com"
- ]
- }
- },
- {
- "ThingLink": {
- "http://www.thinglink.com/": [
- "thinglink.com"
- ]
- }
- },
- {
- "Thismoment": {
- "http://www.thismoment.com/": [
- "thismoment.com"
- ]
- }
- },
- {
- "Thummit": {
- "http://www.thummit.com/": [
- "thummit.com"
- ]
- }
- },
- {
- "Topsy": {
- "http://topsy.com/": [
- "topsy.com"
- ]
- }
- },
- {
- "TraceMyIP.org": {
- "http://www.tracemyip.org/": [
- "tracemyip.org"
- ]
- }
- },
- {
- "Trackset": {
- "http://www.trackset.com/": [
- "trackset.com"
- ]
- }
- },
- {
- "Trovus": {
- "http://www.trovus.co.uk/": [
- "trovus.co.uk"
- ]
- }
- },
- {
- "Trumba": {
- "http://www.trumba.com/": [
- "trumba.com"
- ]
- }
- },
- {
- "TRUSTe": {
- "http://www.truste.com/": [
- "truste.com"
- ]
- }
- },
- {
- "TurnTo": {
- "http://www.turntonetworks.com/": [
- "turnto.com",
- "turntonetworks.com"
- ]
- }
- },
- {
- "Tweetboard": {
- "http://tweetboard.com/": [
- "tweetboard.com"
- ]
- }
- },
- {
- "Twitter Counter": {
- "http://twittercounter.com/": [
- "twittercounter.com"
- ]
- }
- },
- {
- "UberMedia": {
- "http://ubermedia.com/": [
- "tweetup.com",
- "ubermedia.com"
- ]
- }
- },
- {
- "UberTags": {
- "http://ubertags.com/": [
- "ubertags.com"
- ]
- }
- },
- {
- "Unbounce": {
- "http://unbounce.com/": [
- "unbounce.com"
- ]
- }
- },
- {
- "Uptrends": {
- "http://www.uptrends.com/": [
- "uptrends.com"
- ]
- }
- },
- {
- "Usability Sciences": {
- "http://www.usabilitysciences.com/": [
- "usabilitysciences.com",
- "webiqonline.com"
- ]
- }
- },
- {
- "UserVoice": {
- "http://www.uservoice.com/": [
- "uservoice.com"
- ]
- }
- },
- {
- "Vertical Acuity": {
- "http://www.verticalacuity.com/": [
- "verticalacuity.com"
- ]
- }
- },
- {
- "VG WORT": {
- "http://www.vgwort.de/": [
- "vgwort.de"
- ]
- }
- },
- {
- "Videology": {
- "http://www.videologygroup.com/": [
- "tidaltv.com",
- "videologygroup.com"
- ]
- }
- },
- {
- "Viewbix": {
- "http://www.viewbix.com/": [
- "qoof.com",
- "viewbix.com"
- ]
- }
- },
- {
- "Vimeo": {
- "http://vimeo.com/": [
- "vimeo.com",
- "vimeocdn.com"
- ]
- }
- },
- {
- "VINDICO": {
- "http://vindicogroup.com/": [
- "vindicogroup.com",
- "vindicosuite.com"
- ]
- }
- },
- {
- "Voice2Page": {
- "http://www.voice2page.com/": [
- "voice2page.com"
- ]
- }
- },
- {
- "WebsiteAlive": {
- "http://www.websitealive.com/": [
- "websitealive.com",
- "websitealive0.com",
- "websitealive1.com",
- "websitealive2.com",
- "websitealive3.com",
- "websitealive4.com",
- "websitealive5.com",
- "websitealive6.com",
- "websitealive7.com",
- "websitealive8.com",
- "websitealive9.com"
- ]
- }
- },
- {
- "Yahoo!": {
- "http://www.yahoo.com/": [
- "answers.yahoo.com",
- "apps.yahoo.com",
- "autos.yahoo.com",
- "biz.yahoo.com",
- "developer.yahoo.com",
- "everything.yahoo.com",
- "finance.yahoo.com",
- "flickr.com",
- "games.yahoo.com",
- "groups.yahoo.com",
- "help.yahoo.com",
- "hotjobs.yahoo.com",
- "info.yahoo.com",
- "local.yahoo.com",
- "luminate.com",
- "messages.yahoo.com",
- "movies.yahoo.com",
- "msg.yahoo.com",
- "news.yahoo.com",
- "omg.yahoo.com",
- "pipes.yahoo.com",
- "pixazza.com",
- "realestate.yahoo.com",
- "search.yahoo.com",
- "shine.yahoo.com",
- "smallbusiness.yahoo.com",
- "sports.yahoo.com",
- "staticflickr.com",
- "suggestions.yahoo.com",
- "travel.yahoo.com",
- "tumblr.com",
- "upcoming.yahoo.com",
- "webhosting.yahoo.com",
- "widgets.yahoo.com",
- "www.yahoo.com",
- "yahooapis.com",
- "yahoofs.com",
- "yimg.com",
- "ypolicyblog.com",
- "yuilibrary.com",
- "zenfs.com"
- ]
- }
- },
- {
- "Yandex": {
- "http://www.yandex.com/": [
- "kinopoisk.ru",
- "yandex.by",
- "yandex.com",
- "yandex.com.tr",
- "yandex.ru",
- "yandex.st",
- "yandex.ua"
- ]
- }
- },
- {
- "Zendesk": {
- "http://www.zendesk.com/": [
- "zendesk.com"
- ]
- }
- },
- {
- "Zopim": {
- "https://www.zopim.com/": [
- "zopim.com"
- ]
- }
- }
- ],
- "Analytics": [
- {
- "63 Squares": {
- "http://63squares.com/": [
- "63squares.com",
- "i-stats.com"
- ]
- }
- },
- {
- "Acxiom": {
- "http://www.acxiom.com/": [
- "acxiom.com",
- "acxiomapac.com",
- "mm7.net",
- "pippio.com"
- ]
- }
- },
- {
- "AddFreeStats": {
- "http://www.addfreestats.com/": [
- "3dstats.com",
- "addfreestats.com"
- ]
- }
- },
- {
- "Adloox": {
- "http://www.adloox.com/": [
- "adloox.com",
- "adlooxtracking.com"
- ]
- }
- },
- {
- "Adventori": {
- "https://adventori.com": [
- "adventori.com"
- ]
- }
- },
- {
- "AIData": {
- "http://www.aidata.me/": [
- "advombat.ru",
- "aidata.me"
- ]
- }
- },
- {
- "AivaLabs": {
- "https://aivalabs.com": [
- "aivalabs.com"
- ]
- }
- },
- {
- "Akamai": {
- "http://www.akamai.com/": [
- "go-mpulse.net"
- ]
- }
- },
- {
- "Amadesa": {
- "http://www.amadesa.com/": [
- "amadesa.com"
- ]
- }
- },
- {
- "Amazing Counters": {
- "http://amazingcounters.com/": [
- "amazingcounters.com"
- ]
- }
- },
- {
- "Amazon.com": {
- "http://www.amazon.com/": [
- "alexametrics.com"
- ]
- }
- },
- {
- "Amplitude": {
- "https://amplitude.com/": [
- "amplitude.com"
- ]
- }
- },
- {
- "anormal-media.de": {
- "http://anormal-media.de/": [
- "anormal-media.de",
- "anormal-tracker.de"
- ]
- }
- },
- {
- "AT Internet": {
- "http://www.atinternet.com/": [
- "at-o.net",
- "atinternet.com",
- "xiti.com"
- ]
- }
- },
- {
- "Attracta": {
- "https://www.attracta.com/": [
- "attracta.com"
- ]
- }
- },
- {
- "Automattic": {
- "http://automattic.com/": [
- "polldaddy.com"
- ]
- }
- },
- {
- "AvantLink": {
- "http://www.avantlink.com/": [
- "avmws.com"
- ]
- }
- },
- {
- "Awio": {
- "http://www.awio.com/": [
- "awio.com",
- "w3counter.com",
- "w3roi.com"
- ]
- }
- },
- {
- "Belstat": {
- "http://www.belstat.com/": [
- "belstat.be",
- "belstat.com",
- "belstat.de",
- "belstat.fr",
- "belstat.nl"
- ]
- }
- },
- {
- "BetssonPalantir": {
- "https://betssonpalantir.com/": [
- "betssonpalantir.com"
- ]
- }
- },
- {
- "BlogCounter.com": {
- "http://www.blogcounter.de/": [
- "blogcounter.de"
- ]
- }
- },
- {
- "BloomReach": {
- "http://www.bloomreach.com/": [
- "p.brsrvr.com"
- ]
- }
- },
- {
- "BlueCava": {
- "http://www.bluecava.com/": [
- "bluecava.com"
- ]
- }
- },
- {
- "Bluemetrix": {
- "http://www.bluemetrix.com/": [
- "bluemetrix.com",
- "bmmetrix.com"
- ]
- }
- },
- {
- "Bombora": {
- "https://bombora.com/": [
- "ml314.com"
- ]
- }
- },
- {
- "Branch": {
- "https://branch.io/": [
- "branch.io"
- ]
- }
- },
- {
- "Branica": {
- "http://www.branica.com/": [
- "branica.com"
- ]
- }
- },
- {
- "BrightEdge": {
- "http://www.brightedge.com/": [
- "b0e8.com",
- "brightedge.com"
- ]
- }
- },
- {
- "Bubblestat": {
- "http://www.bubblestat.com/": [
- "bubblestat.com"
- ]
- }
- },
- {
- "Cardlytics": {
- "http://www.cardlytics.com/": [
- "cardlytics.com"
- ]
- }
- },
- {
- "Chartbeat": {
- "http://chartbeat.com/": [
- "chartbeat.com",
- "chartbeat.net"
- ]
- }
- },
- {
- "Clickdensity": {
- "http://www.clickdensity.com/": [
- "clickdensity.com"
- ]
- }
- },
- {
- "ClickGuard": {
- "https://www.clickguard.com/": [
- "clickguard.com"
- ]
- }
- },
- {
- "ClickTale": {
- "http://www.clicktale.com/": [
- "clicktale.com",
- "clicktale.net",
- "pantherssl.com"
- ],
- "session-replay": "true"
- }
- },
- {
- "ClixMetrix": {
- "http://www.clixmetrix.com/": [
- "clixmetrix.com"
- ]
- }
- },
- {
- "Clixpy": {
- "http://clixpy.com/": [
- "clixpy.com"
- ]
- }
- },
- {
- "ClustrMaps": {
- "http://www.clustrmaps.com/": [
- "clustrmaps.com"
- ]
- }
- },
- {
- "CNZZ": {
- "http://www.cnzz.com/": [
- "cnzz.com"
- ]
- }
- },
- {
- "Compuware": {
- "http://www.compuware.com/": [
- "axf8.net",
- "compuware.com",
- "gomez.com"
- ]
- }
- },
- {
- "comScore": {
- "http://www.comscore.com/": [
- "certifica.com",
- "comscore.com",
- "mdotlabs.com",
- "scorecardresearch.com",
- "sitestat.com",
- "voicefive.com"
- ]
- }
- },
- {
- "Connexity": {
- "http://www.connexity.com/": [
- "connexity.com",
- "connexity.net"
- ]
- }
- },
- {
- "Convert Insights": {
- "http://www.convert.com/": [
- "convert.com",
- "reedge.com"
- ]
- }
- },
- {
- "Convertro": {
- "http://www.convertro.com/": [
- "convertro.com"
- ]
- }
- },
- {
- "Crazy Egg": {
- "http://www.crazyegg.com/": [
- "cetrk.com",
- "crazyegg.com"
- ]
- }
- },
- {
- "Crowd Science": {
- "http://crowdscience.com/": [
- "crowdscience.com"
- ]
- }
- },
- {
- "Cya2": {
- "http://cya2.net/": [
- "cya2.net"
- ]
- }
- },
- {
- "Dataium": {
- "http://www.dataium.com/": [
- "collserve.com",
- "dataium.com"
- ]
- }
- },
- {
- "Deep Intent": {
- "https://www.deepintent.com/": [
- "deepintent.com"
- ]
- }
- },
- {
- "Demandbase": {
- "http://www.demandbase.com/": [
- "company-target.com",
- "demandbase.com"
- ]
- }
- },
- {
- "DirectCORP": {
- "http://www.directcorp.de/": [
- "ipcounter.de"
- ]
- }
- },
- {
- "DistilNetworks": {
- "https://www.distilnetworks.com/": [
- "distiltag.com"
- ]
- }
- },
- {
- "DoubleVerify": {
- "http://www.doubleverify.com/": [
- "doubleverify.com"
- ]
- }
- },
- {
- "dwstat.com": {
- "http://www.dwstat.cn/": [
- "dwstat.cn"
- ]
- }
- },
- {
- "ECSAnalytics": {
- "https://www.theecsinc.com/": [
- "ecsanalytics.com"
- ]
- }
- },
- {
- "EFF": {
- "https://www.eff.org/": [
- "do-not-tracker.org",
- "eviltracker.net",
- "trackersimulator.org"
- ]
- }
- },
- {
- "eProof.com": {
- "http://www.eproof.com/": [
- "eproof.com"
- ]
- }
- },
- {
- "etracker": {
- "http://www.etracker.com/": [
- "etracker.com",
- "etracker.de",
- "sedotracker.com",
- "sedotracker.de"
- ]
- }
- },
- {
- "Eulerian Technologies": {
- "http://www.eulerian.com/": [
- "eulerian.com",
- "eulerian.net"
- ]
- }
- },
- {
- "eXTReMe digital": {
- "http://extremetracking.com/": [
- "extreme-dm.com",
- "extremetracking.com"
- ]
- }
- },
- {
- "Eyeota": {
- "http://eyeota.net/": [
- "eyeota.net"
- ]
- }
- },
- {
- "Feedjit": {
- "http://feedjit.com/": [
- "feedjit.com"
- ]
- }
- },
- {
- "Flashtalking": {
- "http://www.flashtalking.com/": [
- "encoremetrics.com",
- "sitecompass.com"
- ]
- }
- },
- {
- "Footprint": {
- "http://www.footprintlive.com/": [
- "footprintlive.com"
- ]
- }
- },
- {
- "Free Online Users": {
- "http://www.freeonlineusers.com/": [
- "freeonlineusers.com"
- ]
- }
- },
- {
- "Free-PageRank.com": {
- "http://www.free-pagerank.com/": [
- "free-pagerank.com"
- ]
- }
- },
- {
- "Friends2Follow": {
- "https://friends2follow.com/": [
- "antifraudjs.friends2follow.com"
- ]
- }
- },
- {
- "Fullstory": {
- "https://www.fullstory.com/": [
- "fullstory.com"
- ],
- "session-replay": "true"
- }
- },
- {
- "GetSiteControl": {
- "https://getsitecontrol.com/": [
- "getsitecontrol.com"
- ]
- }
- },
- {
- "GfK Group": {
- "http://www.gfk.com/": [
- "daphnecm.com",
- "gfk.com",
- "gfkdaphne.com"
- ]
- }
- },
- {
- "GitHub": {
- "https://github.com/": [
- "gaug.es"
- ]
- }
- },
- {
- "Go Daddy": {
- "http://www.godaddy.com/": [
- "godaddy.com",
- "trafficfacts.com"
- ]
- }
- },
- {
- "Google": {
- "http://www.google.com/": [
- "google-analytics.com",
- "postrank.com"
- ]
- }
- },
- {
- "GoSquared": {
- "https://www.gosquared.com/": [
- "gosquared.com"
- ]
- }
- },
- {
- "GoStats": {
- "http://gostats.com/": [
- "gostats.com"
- ]
- }
- },
- {
- "GrapheneMedia": {
- "http://graphenemedia.in/": [
- "graphenedigitalanalytics.in"
- ]
- }
- },
- {
- "GTop": {
- "http://www.gtop.ro/": [
- "gtop.ro",
- "gtopstats.com"
- ]
- }
- },
- {
- "Hearst": {
- "http://www.hearst.com/": [
- "raasnet.com",
- "redaril.com"
- ]
- }
- },
- {
- "Histats": {
- "http://www.histats.com/": [
- "histats.com"
- ]
- }
- },
- {
- "HitsLink": {
- "http://www.hitslink.com/": [
- "hitslink.com"
- ]
- }
- },
- {
- "Hit Sniffer": {
- "http://www.hitsniffer.com/": [
- "hitsniffer.com"
- ]
- }
- },
- {
- "Hotjar": {
- "https://www.hotjar.com": [
- "hotjar.com"
- ]
- }
- },
- {
- "HubSpot": {
- "http://www.hubspot.com/": [
- "hs-analytics.net"
- ]
- }
- },
- {
- "IBM": {
- "http://www.ibm.com/": [
- "cmcore.com",
- "coremetrics.com",
- "ibm.com"
- ]
- }
- },
- {
- "InboundWriter": {
- "http://www.inboundwriter.com/": [
- "enquisite.com",
- "inboundwriter.com"
- ]
- }
- },
- {
- "Infernotions": {
- "https://infernotions.com/": [
- "infernotions.com"
- ]
- }
- },
- {
- "INFOnline": {
- "https://www.infonline.de/": [
- "infonline.de",
- "ioam.de",
- "ivwbox.de"
- ]
- }
- },
- {
- "InfoStars": {
- "http://infostars.ru/": [
- "hotlog.ru",
- "infostars.ru"
- ]
- }
- },
- {
- "Inspectlet": {
- "http://www.inspectlet.com/": [
- "inspectlet.com"
- ]
- }
- },
- {
- "IntelligenceFocus": {
- "http://www.intelligencefocus.com/": [
- "domodomain.com",
- "intelligencefocus.com"
- ]
- }
- },
- {
- "iPerceptions": {
- "http://www.iperceptions.com/": [
- "iperceptions.com"
- ]
- }
- },
- {
- "IslayTech": {
- "http://islay.tech": [
- "islay.tech"
- ]
- }
- },
- {
- "ItIsATracker": {
- "https://itisatracker.com/": [
- "itisatracker.com"
- ],
- "dnt": "eff"
- }
- },
- {
- "KeyMetric": {
- "http://www.keymetric.net/": [
- "keymetric.net"
- ]
- }
- },
- {
- "KISSmetrics": {
- "http://kissmetrics.com/": [
- "kissmetrics.com"
- ]
- }
- },
- {
- "Kitcode": {
- "http://src.kitcode.net/": [
- "src.kitcode.net"
- ]
- }
- },
- {
- "LeadForensics": {
- "https://www.leadforensics.com": [
- "leadforensics.com"
- ]
- }
- },
- {
- "LineZing": {
- "http://www.linezing.com/": [
- "linezing.com"
- ]
- }
- },
- {
- "LivePerson": {
- "http://www.liveperson.net/": [
- "liveperson.com",
- "nuconomy.com"
- ]
- }
- },
- {
- "Logdy": {
- "http://logdy.com/": [
- "logdy.com"
- ]
- }
- },
- {
- "Lotame": {
- "http://www.lotame.com/": [
- "crwdcntrl.net",
- "lotame.com"
- ]
- }
- },
- {
- "LuckyOrange": {
- "https://www.luckyorange.com": [
- "luckyorange.com",
- "luckyorange.net"
- ],
- "session-replay": "true"
- }
- },
- {
- "Lynchpin": {
- "http://www.lynchpin.com/": [
- "lynchpin.com",
- "lypn.com"
- ]
- }
- },
- {
- "Lyris": {
- "http://www.lyris.com/": [
- "clicktracks.com",
- "lyris.com"
- ]
- }
- },
- {
- "Lytiks": {
- "http://www.lytiks.com/": [
- "lytiks.com"
- ]
- }
- },
- {
- "MarkMonitor": {
- "https://www.markmonitor.com": [
- "9c9media.ca",
- "markmonitor.com"
- ]
- }
- },
- {
- "Marktest": {
- "http://www.marktest.com/": [
- "marktest.com",
- "marktest.pt"
- ]
- }
- },
- {
- "MaxMind": {
- "https://www.maxmind.com/en/home": [
- "maxmind.com",
- "mmapiws.com"
- ]
- }
- },
- {
- "Médiamétrie-eStat": {
- "http://www.mediametrie-estat.com/": [
- "estat.com",
- "mediametrie-estat.com"
- ]
- }
- },
- {
- "Merkle": {
- "https://www.merkleinc.com/": [
- "merkleinc.com",
- "rkdms.com"
- ]
- }
- },
- {
- "Mixpanel": {
- "https://mixpanel.com/": [
- "mixpanel.com",
- "mxpnl.com"
- ]
- }
- },
- {
- "Mongoose Metrics": {
- "http://www.mongoosemetrics.com/": [
- "mongoosemetrics.com"
- ]
- }
- },
- {
- "Monitus": {
- "http://www.monitus.net/": [
- "monitus.net"
- ]
- }
- },
- {
- "motigo": {
- "http://motigo.com/": [
- "motigo.com",
- "nedstatbasic.net"
- ]
- }
- },
- {
- "Mouseflow": {
- "http://mouseflow.com/": [
- "mouseflow.com"
- ]
- }
- },
- {
- "MyPagerank.Net": {
- "http://www.mypagerank.net/": [
- "mypagerank.net"
- ]
- }
- },
- {
- "Mystighty": {
- "http://mystighty.info/": [
- "mystighty.info",
- "sweeterge.info"
- ]
- }
- },
- {
- "Narrative": {
- "http://narrative.io/2/": [
- "narrative.io"
- ]
- }
- },
- {
- "Net Applications": {
- "http://www.netapplications.com/": [
- "hitsprocessor.com",
- "netapplications.com"
- ]
- }
- },
- {
- "New Relic": {
- "http://newrelic.com/": [
- "newrelic.com",
- "nr-data.net"
- ]
- }
- },
- {
- "NewsRight": {
- "http://www.newsright.com/": [
- "apnewsregistry.com"
- ]
- }
- },
- {
- "NextSTAT": {
- "http://www.nextstat.com/": [
- "nextstat.com"
- ]
- }
- },
- {
- "Nielsen": {
- "http://www.nielsen.com/": [
- "glanceguide.com",
- "nielsen.com"
- ]
- }
- },
- {
- "NuDataSecurity": {
- "https://nudatasecurity.com/": [
- "nudatasecurity.com"
- ]
- }
- },
- {
- "nurago": {
- "http://www.nurago.com/": [
- "nurago.com",
- "nurago.de",
- "sensic.net"
- ]
- }
- },
- {
- "Observer": {
- "http://observerapp.com/": [
- "observerapp.com"
- ]
- }
- },
- {
- "OnAudience": {
- "http://www.onaudience.com/": [
- "behavioralengine.com",
- "onaudience.com"
- ]
- }
- },
- {
- "OneStat": {
- "http://www.onestat.com/": [
- "onestat.com"
- ]
- }
- },
- {
- "Openstat": {
- "https://www.openstat.ru/": [
- "openstat.ru",
- "spylog.com"
- ]
- }
- },
- {
- "Opentracker": {
- "http://www.opentracker.net/": [
- "opentracker.net"
- ]
- }
- },
- {
- "Opolen": {
- "https://opolen.com.br": [
- "opolen.com.br"
- ]
- }
- },
- {
- "Optimizely": {
- "https://www.optimizely.com/": [
- "optimizely.com"
- ]
- }
- },
- {
- "Oracle": {
- "http://www.oracle.com/": [
- "eloqua.com",
- "maxymiser.com"
- ]
- }
- },
- {
- "ÖWA": {
- "http://www.oewa.at/": [
- "oewa.at",
- "oewabox.at"
- ]
- }
- },
- {
- "Parse.ly": {
- "http://parsely.com/": [
- "parsely.com"
- ]
- }
- },
- {
- "PersianStat.com": {
- "http://www.persianstat.com/": [
- "persianstat.com"
- ]
- }
- },
- {
- "Phonalytics": {
- "http://www.phonalytics.com/": [
- "phonalytics.com"
- ]
- }
- },
- {
- "phpMyVisites": {
- "http://www.phpmyvisites.us/": [
- "phpmyvisites.us"
- ]
- }
- },
- {
- "Piwik": {
- "http://piwik.org/": [
- "piwik.org"
- ]
- }
- },
- {
- "PixAnalytics": {
- "https://pixanalytics.com/": [
- "pixanalytics.com"
- ]
- }
- },
- {
- "Poool": {
- "http://poool.fr/": [
- "poool.fr"
- ]
- }
- },
- {
- "Pronunciator": {
- "http://www.pronunciator.com/": [
- "pronunciator.com",
- "visitorville.com"
- ]
- }
- },
- {
- "Qualaroo": {
- "http://qualaroo.com/": [
- "kissinsights.com",
- "qualaroo.com"
- ]
- }
- },
- {
- "QuinStreet": {
- "http://quinstreet.com/": [
- "thecounter.com"
- ]
- }
- },
- {
- "Quintelligence": {
- "http://www.quintelligence.com/": [
- "quintelligence.com"
- ]
- }
- },
- {
- "RadarURL": {
- "http://radarurl.com/": [
- "radarurl.com"
- ]
- }
- },
- {
- "Research Now": {
- "http://www.researchnow.com/": [
- "researchnow.com",
- "valuedopinions.co.uk"
- ]
- }
- },
- {
- "Retail Automata": {
- "https://retailautomata.com": [
- "retailautomata.com"
- ]
- }
- },
- {
- "Revtracks": {
- "http://revtrax.com/": [
- "revtrax.com"
- ]
- }
- },
- {
- "Ringier": {
- "http://ringier.cz/": [
- "ringier.cz"
- ]
- }
- },
- {
- "Rollick": {
- "https://gorollick.com": [
- "rollick.io"
- ]
- }
- },
- {
- "Roxr": {
- "http://roxr.net/": [
- "getclicky.com",
- "roxr.net",
- "staticstuff.net"
- ]
- }
- },
- {
- "Safecount": {
- "http://www.safecount.net/": [
- "dl-rms.com",
- "dlqm.net",
- "questionmarket.com",
- "safecount.net"
- ]
- }
- },
- {
- "SageMetrics": {
- "http://www.sagemetrics.com/": [
- "sageanalyst.net",
- "sagemetrics.com"
- ]
- }
- },
- {
- "Salesintelligence": {
- "https://salesintelligence.pl/": [
- "plugin.management"
- ]
- }
- },
- {
- "SeeVolution": {
- "https://www.seevolution.com/": [
- "seevolution.com",
- "svlu.net"
- ]
- }
- },
- {
- "Segment.io": {
- "https://segment.io/": [
- "segment.io"
- ]
- }
- },
- {
- "SendPulse": {
- "https://sendpulse.com/": [
- "sendpulse.com"
- ]
- }
- },
- {
- "SessionCam": {
- "https://sessioncam.com/": [
- "sessioncam.com"
- ],
- "session-replay": "true"
- }
- },
- {
- "ShinyStat": {
- "http://www.shinystat.com/": [
- "shinystat.com"
- ]
- }
- },
- {
- "Smartlook": {
- "https://www.smartlook.com/": [
- "smartlook.com"
- ],
- "session-replay": "true"
- }
- },
- {
- "Snoobi": {
- "http://www.snoobi.com/": [
- "snoobi.com"
- ]
- }
- },
- {
- "Sourcepoint": {
- "https://www.sourcepoint.com/": [
- "summerhamster.com"
- ]
- }
- },
- {
- "Sputnik.ru": {
- "http://sputnik.ru": [
- "sputnik.ru"
- ]
- }
- },
- {
- "StackTrack": {
- "http://stat-track.com": [
- "stat-track.com"
- ]
- }
- },
- {
- "stat4u": {
- "http://stat.4u.pl/": [
- "4u.pl"
- ]
- }
- },
- {
- "StatCounter": {
- "http://statcounter.com/": [
- "statcounter.com"
- ]
- }
- },
- {
- "Statisfy": {
- "http://statisfy.net": [
- "statisfy.net"
- ]
- }
- },
- {
- "STATSIT": {
- "http://www.statsit.com/": [
- "statsit.com"
- ]
- }
- },
- {
- "Storeland": {
- "https://storeland.ru/": [
- "storeland.ru"
- ]
- }
- },
- {
- "Stratigent": {
- "http://www.stratigent.com/": [
- "stratigent.com"
- ]
- }
- },
- {
- "Tealium": {
- "https://tealium.com": [
- "tealiumiq.com"
- ]
- }
- },
- {
- "TechSolutions": {
- "https://www.techsolutions.com.tw/": [
- "techsolutions.com.tw"
- ]
- }
- },
- {
- "TENSQUARE": {
- "http://www.tensquare.com/": [
- "tensquare.com"
- ]
- }
- },
- {
- "The Heron Partnership": {
- "http://www.heronpartners.com.au/": [
- "heronpartners.com.au",
- "marinsm.com"
- ]
- }
- },
- {
- "TNS": {
- "http://www.tnsglobal.com/": [
- "sesamestats.com",
- "statistik-gallup.net",
- "tns-counter.ru",
- "tns-cs.net",
- "tnsglobal.com"
- ]
- }
- },
- {
- "TrackingSoft": {
- "http://trackingsoft.com/": [
- "roia.biz",
- "trackingsoft.com"
- ]
- }
- },
- {
- "TrafficScore": {
- "https://trafficscore.com/": [
- "trafficscore.com"
- ]
- }
- },
- {
- "Twitter": {
- "https://twitter.com/": [
- "crashlytics.com",
- "tweetdeck.com"
- ]
- }
- },
- {
- "Umbel": {
- "https://www.umbel.com/": [
- "umbel.com"
- ]
- }
- },
- {
- "User Local": {
- "http://nakanohito.jp/": [
- "nakanohito.jp"
- ]
- }
- },
- {
- "V12 Data": {
- "https://www.v12data.com/": [
- "v12data.com",
- "v12group.com"
- ]
- }
- },
- {
- "Vertster": {
- "http://www.vertster.com/": [
- "vertster.com"
- ]
- }
- },
- {
- "VisiStat": {
- "http://www.visistat.com/": [
- "sa-as.com",
- "visistat.com"
- ]
- }
- },
- {
- "Visit Streamer": {
- "http://www.visitstreamer.com/": [
- "visitstreamer.com"
- ]
- }
- },
- {
- "vistrac": {
- "http://vistrac.com/": [
- "vistrac.com"
- ]
- }
- },
- {
- "ViziSense": {
- "http://www.vizisense.com/": [
- "vizisense.com",
- "vizisense.net"
- ]
- }
- },
- {
- "Webclicktracker": {
- "http://www.webclicktracker.com/": [
- "webclicktracker.com"
- ]
- }
- },
- {
- "Web Stats": {
- "http://www.onlinewebstats.com/": [
- "onlinewebstats.com"
- ]
- }
- },
- {
- "Web Tracking Services": {
- "http://www.webtrackingservices.com/": [
- "web-stat.com",
- "webtrackingservices.com"
- ]
- }
- },
- {
- "Web Traxs": {
- "http://www.webtraxs.com/": [
- "webtraxs.com"
- ]
- }
- },
- {
- "Webtrekk": {
- "http://www.webtrekk.com/": [
- "webtrekk.com",
- "webtrekk.net"
- ]
- }
- },
- {
- "Webtrends": {
- "http://webtrends.com/": [
- "reinvigorate.net",
- "webtrends.com",
- "webtrendslive.com"
- ]
- }
- },
- {
- "White Ops": {
- "https://www.whiteops.com/": [
- "adzmath.com",
- "whiteops.com"
- ]
- }
- },
- {
- "whos.amung.us": {
- "http://whos.amung.us/": [
- "amung.us"
- ]
- }
- },
- {
- "Wingify": {
- "http://wingify.com/": [
- "visualwebsiteoptimizer.com",
- "wingify.com"
- ]
- }
- },
- {
- "Woopra": {
- "http://www.woopra.com/": [
- "woopra-ns.com",
- "woopra.com"
- ]
- }
- },
- {
- "WOW Analytics": {
- "http://www.wowanalytics.co.uk/": [
- "wowanalytics.co.uk"
- ]
- }
- },
- {
- "WPP": {
- "http://www.wpp.com/": [
- "compete.com"
- ]
- }
- },
- {
- "Wysistat": {
- "http://www.wysistat.com/": [
- "wysistat.com"
- ]
- }
- },
- {
- "Yahoo!": {
- "http://www.yahoo.com/": [
- "analytics.yahoo.com"
- ]
- }
- },
- {
- "YellowTracker": {
- "http://www.yellowtracker.com/": [
- "yellowtracker.com"
- ]
- }
- },
- {
- "YSance": {
- "https://www.ysance.com/data-services/fr/home/": [
- "y-track.com"
- ]
- }
- }
- ],
- "Fingerprinting": [
- {
- "Adabra": {
- "https://www.adabra.com/": [
- "adabra.com"
- ]
- }
- },
- {
- "Adbot": {
- "https://adbot.tw/": [
- "adbot.tw"
- ]
- }
- },
- {
- "AdGainerSolutions": {
- "http://adgainersolutions.com/adgainer/": [
- "adgainersolutions.com"
- ]
- }
- },
- {
- "AdMaven": {
- "https://ad-maven.com/": [
- "ad-maven.com",
- "agreensdistra.info",
- "boudja.com",
- "rensovetors.info",
- "wrethicap.info"
- ]
- }
- },
- {
- "Admicro": {
- "http://www.admicro.vn/": [
- "admicro.vn",
- "vcmedia.vn"
- ]
- }
- },
- {
- "Adnium": {
- "https://adnium.com": [
- "adnium.com",
- "montwam.top"
- ]
- }
- },
- {
- "AdScore": {
- "http://www.adscoremarketing.com/": [
- "adsco.re"
- ]
- }
- },
- {
- "AdYouLike": {
- "https://www.adyoulike.com/": [
- "pulpix.com"
- ]
- }
- },
- {
- "AivaLabs": {
- "https://aivalabs.com": [
- "aivalabs.com"
- ]
- }
- },
- {
- "Albacross": {
- "https://albacross.com": [
- "albacross.com"
- ]
- }
- },
- {
- "AppCast": {
- "https://appcast.io/": [
- "appcast.io"
- ]
- }
- },
- {
- "AuditedMedia": {
- "https://auditedmedia.com/": [
- "aamapi.com",
- "aamsitecertifier.com",
- "auditedmedia.com"
- ]
- }
- },
- {
- "Augur": {
- "http://www.augur.io/": [
- "augur.io"
- ]
- }
- },
- {
- "Azet": {
- "http://mediaimpact.sk/": [
- "azetklik.sk",
- "rsz.sk"
- ]
- }
- },
- {
- "BetssonPalantir": {
- "https://betssonpalantir.com/": [
- "betssonpalantir.com"
- ]
- }
- },
- {
- "BigClick": {
- "http://bigclick.me/": [
- "bgclck.me",
- "xcvgdf.party"
- ]
- }
- },
- {
- "BitMedia": {
- "https://bitmedia.io/": [
- "bitmedia.io"
- ]
- }
- },
- {
- "BlueCava": {
- "http://www.bluecava.com/": [
- "bluecava.com"
- ]
- }
- },
- {
- "BoostBox": {
- "https://www.boostbox.com.br/": [
- "boostbox.com.br"
- ]
- }
- },
- {
- "Brandcrumb": {
- "http://www.brandcrumb.com": [
- "brandcrumb.com"
- ]
- }
- },
- {
- "BreakTime": {
- "https://www.breaktime.com.tw/": [
- "breaktime.com.tw"
- ]
- }
- },
- {
- "BrightEdge": {
- "http://www.brightedge.com/": [
- "b0e8.com"
- ]
- }
- },
- {
- "C3 Metrics": {
- "http://c3metrics.com/": [
- "attributionmodel.com",
- "c3metrics.com",
- "c3tag.com"
- ]
- }
- },
- {
- "CallSource": {
- "https://www.callsource.com/": [
- "leadtrackingdata.com"
- ]
- }
- },
- {
- "CartsGuru": {
- "https://carts.guru/": [
- "carts.guru"
- ]
- }
- },
- {
- "ClearLink": {
- "https://www.clearlink.com/": [
- "clearlink.com"
- ]
- }
- },
- {
- "Clickayab": {
- "http://www.clickyab.com": [
- "clickyab.com"
- ]
- }
- },
- {
- "ClickFrog": {
- "https://clickfrog.ru/": [
- "bashirian.biz",
- "buckridge.link",
- "franecki.net",
- "quitzon.net",
- "reichelcormier.bid",
- "wisokykulas.bid"
- ]
- }
- },
- {
- "ClickGuard": {
- "https://www.clickguard.com/": [
- "clickguard.com"
- ]
- }
- },
- {
- "Clixtell": {
- "https://www.clixtell.com/": [
- "clixtell.com"
- ]
- }
- },
- {
- "Consumable": {
- "http://consumable.com/": [
- "consumable.com"
- ]
- }
- },
- {
- "dmpxs": {
- "http://bob.dmpxs.com": [
- "dmpxs.com"
- ]
- }
- },
- {
- "ECSAnalytics": {
- "https://www.theecsinc.com/": [
- "ecsanalytics.com"
- ]
- }
- },
- {
- "EroAdvertising": {
- "http://www.ero-advertising.com/": [
- "ero-advertising.com"
- ]
- }
- },
- {
- "eyeReturn Marketing": {
- "http://www.eyereturnmarketing.com/": [
- "eyereturn.com",
- "eyereturnmarketing.com"
- ]
- }
- },
- {
- "Fanplayr": {
- "https://fanplayr.com/": [
- "fanplayr.com"
- ]
- }
- },
- {
- "Foresee": {
- "https://www.foresee.com": [
- "answerscloud.com",
- "foresee.com"
- ]
- }
- },
- {
- "Friends2Follow": {
- "https://friends2follow.com/": [
- "antifraudjs.friends2follow.com"
- ]
- }
- },
- {
- "FuelX": {
- "https://fuelx.com/": [
- "fuel451.com",
- "fuelx.com"
- ]
- }
- },
- {
- "Gleam": {
- "https://gleam.io/": [
- "fraudjs.io"
- ]
- }
- },
- {
- "GrapheneMedia": {
- "http://graphenemedia.in/": [
- "graphenedigitalanalytics.in"
- ]
- }
- },
- {
- "Gruner + Jahr": {
- "http://www.guj.de/": [
- "ligatus.com"
- ]
- }
- },
- {
- "HilltopAds": {
- "https://hilltopads.com/": [
- "hilltopads.net",
- "shoporielder.pro"
- ]
- }
- },
- {
- "HotelChamp": {
- "https://www.hotelchamp.com": [
- "hotelchamp.com"
- ]
- }
- },
- {
- "iMedia": {
- "http://www.imedia.cz": [
- "imedia.cz"
- ]
- }
- },
- {
- "IslayTech": {
- "http://islay.tech": [
- "islay.tech"
- ]
- }
- },
- {
- "ismatlab.com": {
- "http://ismatlab.com": [
- "ismatlab.com"
- ]
- }
- },
- {
- "Itch": {
- "https://itch.io/": [
- "itch.io"
- ]
- }
- },
- {
- "justuno": {
- "https://www.justuno.com/": [
- "justuno.com"
- ]
- }
- },
- {
- "Konduto": {
- "http://konduto.com": [
- "k-analytix.com",
- "konduto.com"
- ]
- }
- },
- {
- "LeadsHub": {
- "https://ztsrv.com/": [
- "ztsrv.com"
- ]
- }
- },
- {
- "lptracker": {
- "https://lptracker.io/": [
- "lptracker.io"
- ]
- }
- },
- {
- "MaxMind": {
- "https://www.maxmind.com/en/home": [
- "maxmind.com",
- "mmapiws.com"
- ]
- }
- },
- {
- "Mercadopago": {
- "https://www.mercadopago.com/": [
- "mercadopago.com"
- ]
- }
- },
- {
- "Mobials": {
- "http://mobials.com": [
- "mobials.com"
- ]
- }
- },
- {
- "Mystighty": {
- "http://mystighty.info/": [
- "mystighty.info",
- "sweeterge.info"
- ]
- }
- },
- {
- "Negishim": {
- "http://www.negishim.org": [
- "negishim.org"
- ]
- }
- },
- {
- "NuDataSecurity": {
- "https://nudatasecurity.com/": [
- "nudatasecurity.com"
- ]
- }
- },
- {
- "OneAd": {
- "https://www.onead.com.tw/": [
- "guoshipartners.com",
- "onevision.com.tw"
- ]
- }
- },
- {
- "OnlineMetrix": {
- "http://h.online-metrix.net": [
- "online-metrix.net"
- ]
- }
- },
- {
- "Opolen": {
- "https://opolen.com.br": [
- "opolen.com.br"
- ]
- }
- },
- {
- "PaymentsMB": {
- "https://paymentsmb.com": [
- "paymentsmb.com"
- ]
- }
- },
- {
- "Paypal": {
- "https://www.paypal.com": [
- "simility.com"
- ]
- }
- },
- {
- "PerimeterX": {
- "https://www.perimeterx.com": [
- "perimeterx.net"
- ]
- }
- },
- {
- "PixAnalytics": {
- "https://pixanalytics.com/": [
- "pixanalytics.com"
- ]
- }
- },
- {
- "Pixlee": {
- "https://www.pixlee.com/": [
- "pixlee.com"
- ]
- }
- },
- {
- "Poool": {
- "http://poool.fr/": [
- "poool.fr"
- ]
- }
- },
- {
- "PPCProtect": {
- "https://ppcprotect.com": [
- "ppcprotect.com"
- ]
- }
- },
- {
- "PrismApp": {
- "https://www.prismapp.io/": [
- "prismapp.io"
- ]
- }
- },
- {
- "PrometheusIntelligenceTechnology": {
- "https://prometheusintelligencetechnology.com/": [
- "prometheusintelligencetechnology.com"
- ]
- }
- },
- {
- "Provers": {
- "http://provers.pro": [
- "provers.pro"
- ]
- }
- },
- {
- "Psonstrentie": {
- "http://psonstrentie.info": [
- "psonstrentie.info"
- ]
- }
- },
- {
- "Rollick": {
- "https://gorollick.com": [
- "rollick.io"
- ]
- }
- },
- {
- "SAP": {
- "https://www.sap.com": [
- "seewhy.com"
- ]
- }
- },
- {
- "Selectable Media": {
- "http://selectablemedia.com/": [
- "nabbr.com",
- "selectablemedia.com"
- ]
- }
- },
- {
- "Semantiqo": {
- "http://semantiqo.com/": [
- "semantiqo.com"
- ]
- }
- },
- {
- "SendPulse": {
- "https://sendpulse.com/": [
- "sendpulse.com"
- ]
- }
- },
- {
- "ShaftTraffic": {
- "https://shafttraffic.com": [
- "libertystmedia.com"
- ]
- }
- },
- {
- "Shortest": {
- "http://shorte.st/": [
- "shorte.st"
- ]
- }
- },
- {
- "SiftScience": {
- "https://sift.com/": [
- "siftscience.com"
- ]
- }
- },
- {
- "Signifyd": {
- "https://www.signifyd.com/": [
- "signifyd.com"
- ]
- }
- },
- {
- "Smi": {
- "http://24smi.net": [
- "24smi.net"
- ]
- }
- },
- {
- "Socital": {
- "https://www.socital.com": [
- "socital.com"
- ]
- }
- },
- {
- "Storeland": {
- "https://storeland.ru/": [
- "storeland.ru"
- ]
- }
- },
- {
- "Stripe": {
- "https://stripe.com": [
- "stripe.network"
- ]
- }
- },
- {
- "TechSolutions": {
- "https://www.techsolutions.com.tw/": [
- "techsolutions.com.tw"
- ]
- }
- },
- {
- "tongdun.cn": {
- "https://www.tongdun.cn/?lan=EN": [
- "fraudmetrix.cn",
- "tongdun.net"
- ]
- }
- },
- {
- "Upland": {
- "https://uplandsoftware.com/": [
- "leadlander.com",
- "sf14g.com"
- ]
- }
- },
- {
- "Vendemore": {
- "https://vendemore.com/": [
- "vendemore.com"
- ]
- }
- },
- {
- "VerticalHealth": {
- "https://www.verticalhealth.com/": [
- "verticalhealth.net"
- ]
- }
- },
- {
- "Webmecanik": {
- "https://www.webmecanik.com/": [
- "webmecanik.com"
- ]
- }
- },
- {
- "WideOrbit": {
- "https://www.wideorbit.com/": [
- "dep-x.com"
- ]
- }
- },
- {
- "YSance": {
- "https://www.ysance.com/data-services/fr/home/": [
- "y-track.com"
- ]
- }
- },
- {
- "ZafulAffiliate": {
- "https://affiliate.zaful.com/": [
- "affasi.com",
- "gw-ec.com",
- "zaful.com"
- ]
- }
- },
- {
- "Zefir": {
- "https://ze-fir.com/": [
- "ze-fir.com"
- ]
- }
- }
- ],
- "Social": [
- {
- "AddThis": {
- "http://www.addthis.com/": [
- "addthis.com",
- "addthiscdn.com",
- "addthisedge.com",
- "clearspring.com",
- "connectedads.net",
- "xgraph.com",
- "xgraph.net"
- ]
- }
- },
- {
- "Causes": {
- "http://www.causes.com/": [
- "causes.com"
- ]
- }
- },
- {
- "Digg": {
- "http://digg.com/": [
- "digg.com"
- ]
- }
- },
- {
- "Facebook": {
- "http://www.facebook.com/": [
- "apps.fbsbx.com",
- "atdmt.com",
- "facebook.com",
- "facebook.de",
- "facebook.fr",
- "facebook.net",
- "fb.com",
- "fbsbx.com",
- "friendfeed.com"
- ]
- }
- },
- {
- "Google": {
- "http://www.google.com/": [
- "developers.google.com",
- "gmail.com",
- "googlemail.com",
- "inbox.google.com",
- "mail.google.com",
- "orkut.com",
- "plus.google.com",
- "plusone.google.com",
- "smartlock.google.com",
- "voice.google.com",
- "wave.google.com"
- ]
- }
- },
- {
- "LinkedIn": {
- "http://www.linkedin.com/": [
- "licdn.com",
- "linkedin.com"
- ]
- }
- },
- {
- "Lockerz": {
- "http://lockerz.com/": [
- "lockerz.com"
- ]
- }
- },
- {
- "Mail.Ru": {
- "http://mail.ru/": [
- "list.ru",
- "mail.ru"
- ]
- }
- },
- {
- "Meebo": {
- "https://www.meebo.com/": [
- "meebo.com",
- "meebocdn.net"
- ]
- }
- },
- {
- "Papaya": {
- "http://papayamobile.com/": [
- "papayamobile.com"
- ]
- }
- },
- {
- "reddit": {
- "http://www.reddit.com/": [
- "reddit.com"
- ]
- }
- },
- {
- "Shareaholic": {
- "http://www.shareaholic.com/": [
- "shareaholic.com"
- ]
- }
- },
- {
- "ShareThis": {
- "http://sharethis.com/": [
- "sharethis.com"
- ]
- }
- },
- {
- "StumbleUpon": {
- "http://www.stumbleupon.com/": [
- "stumble-upon.com",
- "stumbleupon.com"
- ]
- }
- },
- {
- "Twitter": {
- "https://twitter.com/": [
- "twimg.com",
- "twitter.com",
- "twitter.jp"
- ]
- }
- },
- {
- "VKontakte": {
- "http://vk.com/": [
- "userapi.com",
- "vk.com",
- "vkontakte.ru"
- ]
- }
- },
- {
- "Yahoo!": {
- "http://www.yahoo.com/": [
- "address.yahoo.com",
- "alerts.yahoo.com",
- "avatars.yahoo.com",
- "buzz.yahoo.com",
- "calendar.yahoo.com",
- "edit.yahoo.com",
- "legalredirect.yahoo.com",
- "login.yahoo.com",
- "mail.yahoo.com",
- "my.yahoo.com",
- "mybloglog.com",
- "notepad.yahoo.com",
- "pulse.yahoo.com",
- "rocketmail.com",
- "webmessenger.yahoo.com",
- "ymail.com"
- ]
- }
- }
- ],
- "Cryptomining": [
- {
- "a.js": {
- "http://zymerget.bid": [
- "alflying.date",
- "alflying.win",
- "anybest.site",
- "flightsy.bid",
- "flightsy.win",
- "flightzy.bid",
- "flightzy.date",
- "flightzy.win",
- "zymerget.bid",
- "zymerget.faith"
- ],
- "performance": "true"
- }
- },
- {
- "CashBeet": {
- "http://cashbeet.com": [
- "cashbeet.com",
- "serv1swork.com"
- ]
- }
- },
- {
- "CoinHive": {
- "https://coinhive.com": [
- "ad-miner.com",
- "authedmine.com",
- "bmst.pw",
- "cnhv.co",
- "coin-hive.com",
- "coinhive.com",
- "wsservices.org"
- ],
- "performance": "true"
- }
- },
- {
- "CoinPot": {
- "http://coinpot.co": [
- "coinpot.co"
- ],
- "performance": "true"
- }
- },
- {
- "CryptoLoot": {
- "https://crypto-loot.com": [
- "cryptaloot.pro",
- "crypto-loot.com",
- "cryptolootminer.com",
- "flashx.pw",
- "gitgrub.pro",
- "reauthenticator.com",
- "statdynamic.com",
- "webmine.pro"
- ],
- "performance": "true"
- }
- },
- {
- "CryptoWebMiner": {
- "https://www.crypto-webminer.com": [
- "bitcoin-pay.eu",
- "crypto-webminer.com",
- "ethpocket.de",
- "ethtrader.de"
- ]
- }
- },
- {
- "Gridcash": {
- "https://www.gridcash.net/": [
- "adless.io",
- "gridcash.net"
- ],
- "performance": "true"
- }
- },
- {
- "JSE": {
- "http://jsecoin.com": [
- "freecontent.bid",
- "freecontent.date",
- "freecontent.stream",
- "hashing.win",
- "hostingcloud.racing",
- "hostingcloud.science",
- "jsecoin.com"
- ],
- "performance": "true"
- }
- },
- {
- "MinerAlt": {
- "http://mineralt.io": [
- "1q2w3.website",
- "analytics.blue",
- "aster18cdn.nl",
- "belicimo.pw",
- "besstahete.info",
- "dinorslick.icu",
- "feesocrald.com",
- "gramombird.com",
- "istlandoll.com",
- "mepirtedic.com",
- "mineralt.io",
- "pampopholf.com",
- "tercabilis.info",
- "tulip18.com",
- "vidzi.tv",
- "yololike.space"
- ],
- "performance": "true"
- }
- },
- {
- "Minescripts": {
- "http://minescripts.info": [
- "minescripts.info",
- "sslverify.info"
- ],
- "performance": "true"
- }
- },
- {
- "MineXMR": {
- "http://minexmr.stream": [
- "minexmr.stream"
- ],
- "performance": "true"
- }
- },
- {
- "NeroHut": {
- "https://nerohut.com": [
- "nerohut.com",
- "nhsrv.cf"
- ],
- "performance": "true"
- }
- },
- {
- "Service4refresh": {
- "https://service4refresh.info": [
- "service4refresh.info"
- ]
- }
- },
- {
- "SpareChange": {
- "http://sparechange.io": [
- "sparechange.io"
- ],
- "performance": "true"
- }
- },
- {
- "SwiftMining": {
- "https://swiftmining.win/": [
- "swiftmining.win"
- ]
- }
- },
- {
- "Webmine": {
- "https://webmine.cz/": [
- "authedwebmine.cz",
- "webmine.cz"
- ]
- }
- },
- {
- "WebminePool": {
- "http://webminepool.com": [
- "webminepool.com"
- ],
- "performance": "true"
- }
- },
- {
- "Webmining": {
- "https://webmining.co/": [
- "webmining.co"
- ]
- }
- }
- ]
- }
+ "license": "Copyright 2010-2019 Disconnect, Inc. / This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. / This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. / You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>.",
+ "categories": {
+ "Advertising": [
+ {
+ "2leep.com": {
+ "http://2leep.com/": ["2leep.com"]
+ }
+ },
+ {
+ "33Across": {
+ "http://33across.com/": ["33across.com"]
+ }
+ },
+ {
+ "365Media": {
+ "http://365media.com/": ["365media.com"]
+ }
+ },
+ {
+ "4INFO": {
+ "http://www.4info.com/": ["4info.com", "adhaven.com"]
+ }
+ },
+ {
+ "4mads": {
+ "http://4mads.com/": ["4mads.com"]
+ }
+ },
+ {
+ "Abax Interactive": {
+ "http://abaxinteractive.com/": ["abaxinteractive.com"]
+ }
+ },
+ {
+ "Accelia": {
+ "http://www.accelia.net/": ["accelia.net", "durasite.net"]
+ }
+ },
+ {
+ "Accordant Media": {
+ "http://www.accordantmedia.com/": ["accordantmedia.com"]
+ }
+ },
+ {
+ "Acquisio": {
+ "http://www.acquisio.com/": ["acquisio.com", "clickequations.net"]
+ }
+ },
+ {
+ "Actisens": {
+ "http://www.actisens.com/": ["actisens.com", "gestionpub.com"]
+ }
+ },
+ {
+ "ActiveConversion": {
+ "http://www.activeconversion.com/": [
+ "activeconversion.com",
+ "activemeter.com"
+ ]
+ }
+ },
+ {
+ "Act-On": {
+ "http://www.act-on.com/": ["act-on.com", "actonsoftware.com"]
+ }
+ },
+ {
+ "Acuity": {
+ "http://www.acuity.com/": [
+ "acuity.com",
+ "acuityads.com",
+ "acuityplatform.com"
+ ]
+ }
+ },
+ {
+ "AD2ONE": {
+ "http://www.ad2onegroup.com/": ["ad2onegroup.com"]
+ }
+ },
+ {
+ "Ad4Game": {
+ "http://ad4game.com/": ["ad4game.com"]
+ }
+ },
+ {
+ "ad6media": {
+ "http://www.ad6media.fr/": ["ad6media.fr"]
+ }
+ },
+ {
+ "Adabra": {
+ "https://www.adabra.com/": ["adabra.com"]
+ }
+ },
+ {
+ "Adality": {
+ "http://adality.de/": ["adality.de", "adrtx.net"]
+ }
+ },
+ {
+ "AdaptiveAds": {
+ "http://www.adaptiveads.com/": ["adaptiveads.com"]
+ }
+ },
+ {
+ "Adaptly": {
+ "http://adaptly.com/": ["adaptly.com"]
+ }
+ },
+ {
+ "Adara Media": {
+ "http://www.adaramedia.com/": [
+ "adaramedia.com",
+ "opinmind.com",
+ "yieldoptimizer.com"
+ ]
+ }
+ },
+ {
+ "Adatus": {
+ "http://www.adatus.com/": ["adatus.com"]
+ }
+ },
+ {
+ "Adbot": {
+ "https://adbot.tw/": ["adbot.tw"]
+ }
+ },
+ {
+ "Adbrain": {
+ "http://www.adbrain.com/": ["adbrain.com", "adbrn.com"]
+ }
+ },
+ {
+ "adBrite": {
+ "http://www.adbrite.com/": ["adbrite.com"]
+ }
+ },
+ {
+ "Adbroker.de": {
+ "http://adbroker.de/": ["adbroker.de"]
+ }
+ },
+ {
+ "Adchemy": {
+ "http://www.adchemy.com/": ["adchemy.com"]
+ }
+ },
+ {
+ "AdCirrus": {
+ "http://adcirrus.com/": ["adcirrus.com"]
+ }
+ },
+ {
+ "Ad Decisive": {
+ "http://www.addecisive.com/": ["a2dfp.net", "addecisive.com"]
+ }
+ },
+ {
+ "addGloo": {
+ "http://www.addgloo.com/": ["addgloo.com"]
+ }
+ },
+ {
+ "Addvantage Media": {
+ "http://www.addvantagemedia.com/": ["addvantagemedia.com"]
+ }
+ },
+ {
+ "Ad Dynamo": {
+ "http://www.addynamo.com/": ["addynamo.com", "addynamo.net"]
+ }
+ },
+ {
+ "Adelphic": {
+ "https://adelphic.com/": ["adelphic.com", "ipredictive.com"]
+ }
+ },
+ {
+ "AdEngage": {
+ "http://adengage.com/": ["adengage.com"]
+ }
+ },
+ {
+ "AD Europe": {
+ "http://www.adeurope.com/": ["adeurope.com"]
+ }
+ },
+ {
+ "AdExtent": {
+ "http://www.adextent.com/": ["adextent.com"]
+ }
+ },
+ {
+ "AdF.ly": {
+ "http://adf.ly/": ["adf.ly"]
+ }
+ },
+ {
+ "Adfonic": {
+ "http://adfonic.com/": ["adfonic.com"]
+ }
+ },
+ {
+ "Adforge": {
+ "http://adforgeinc.com/": ["adforgeinc.com"]
+ }
+ },
+ {
+ "Adform": {
+ "http://www.adform.com/": [
+ "adform.com",
+ "adform.net",
+ "adformdsp.net"
+ ]
+ }
+ },
+ {
+ "AdFox": {
+ "http://adfox.ru/": ["adfox.ru"]
+ }
+ },
+ {
+ "AdFrontiers": {
+ "http://www.adfrontiers.com/": ["adfrontiers.com"]
+ }
+ },
+ {
+ "Adfunky": {
+ "http://www.adfunky.com/": ["adfunky.com", "adfunkyserver.com"]
+ }
+ },
+ {
+ "Adfusion": {
+ "http://www.adfusion.com/": ["adfusion.com"]
+ }
+ },
+ {
+ "AdGainerSolutions": {
+ "http://adgainersolutions.com/adgainer/": ["adgainersolutions.com"]
+ }
+ },
+ {
+ "AdGent Digital": {
+ "http://www.adgentdigital.com/": [
+ "adgentdigital.com",
+ "shorttailmedia.com"
+ ]
+ }
+ },
+ {
+ "AdGibbon": {
+ "http://www.adgibbon.com/": ["adgibbon.com"]
+ }
+ },
+ {
+ "Adglare": {
+ "https://www.adglare.com/": ["adglare.com", "adglare.net"]
+ }
+ },
+ {
+ "adhood": {
+ "http://www.adhood.com/": ["adhood.com"]
+ }
+ },
+ {
+ "Adiant": {
+ "http://www.adiant.com/": ["adblade.com", "adiant.com"]
+ }
+ },
+ {
+ "AdInsight": {
+ "http://www.adinsight.com/": ["adinsight.com", "adinsight.eu"]
+ }
+ },
+ {
+ "AdIQuity": {
+ "http://adiquity.com/": ["adiquity.com"]
+ }
+ },
+ {
+ "ADITION": {
+ "http://www.adition.com/": ["adition.com"]
+ }
+ },
+ {
+ "AdJug": {
+ "http://www.adjug.com/": ["adjug.com"]
+ }
+ },
+ {
+ "AdJuggler": {
+ "http://www.adjuggler.com/": ["adjuggler.com", "adjuggler.net"]
+ }
+ },
+ {
+ "Adjust": {
+ "https://adjust.com": ["adjust.com"]
+ }
+ },
+ {
+ "AdKeeper": {
+ "http://www.adkeeper.com/": ["adkeeper.com", "akncdn.com"]
+ }
+ },
+ {
+ "AdKernel": {
+ "http://adkernel.com": ["adkernel.com"]
+ }
+ },
+ {
+ "Ad Knife": {
+ "http://static.adknife.com/": ["adknife.com"]
+ }
+ },
+ {
+ "Adknowledge": {
+ "http://www.adknowledge.com/": [
+ "adknowledge.com",
+ "adparlor.com",
+ "bidsystem.com",
+ "cubics.com",
+ "lookery.com"
+ ]
+ }
+ },
+ {
+ "AdLantis": {
+ "http://www.adlantis.jp/": ["adimg.net", "adlantis.jp"]
+ }
+ },
+ {
+ "AdLeave": {
+ "http://www.adleave.com/": ["adleave.com"]
+ }
+ },
+ {
+ "Adlibrium": {
+ "http://www.adlibrium.com/": ["adlibrium.com"]
+ }
+ },
+ {
+ "Adlucent": {
+ "http://adlucent.com": ["adlucent.com"]
+ }
+ },
+ {
+ "Ad Magnet": {
+ "http://www.admagnet.com/": ["admagnet.com", "admagnet.net"]
+ }
+ },
+ {
+ "Admarketplace": {
+ "http://www.admarketplace.com/": [
+ "admarketplace.com",
+ "admarketplace.net",
+ "ampxchange.com"
+ ]
+ }
+ },
+ {
+ "AdMarvel": {
+ "http://www.admarvel.com/": ["admarvel.com"]
+ }
+ },
+ {
+ "AdMatrix": {
+ "http://www.admatrix.jp/": ["admatrix.jp"]
+ }
+ },
+ {
+ "AdMaven": {
+ "https://ad-maven.com/": [
+ "ad-maven.com",
+ "agreensdistra.info",
+ "boudja.com",
+ "rensovetors.info",
+ "wrethicap.info"
+ ]
+ }
+ },
+ {
+ "AdMaximizer Network": {
+ "http://admaximizer.com/": ["admaximizer.com"]
+ }
+ },
+ {
+ "AdMedia": {
+ "http://www.admedia.com/": ["admedia.com"]
+ }
+ },
+ {
+ "Admeta": {
+ "http://www.admeta.com/": ["admeta.com", "atemda.com"]
+ }
+ },
+ {
+ "Admicro": {
+ "http://www.admicro.vn/": ["admicro.vn", "vcmedia.vn"]
+ }
+ },
+ {
+ "Admixer": {
+ "https://admixer.co.kr/main": ["admixer.co.kr"]
+ }
+ },
+ {
+ "Admized": {
+ "http://www.admized.com/": ["admized.com"]
+ }
+ },
+ {
+ "Admobile": {
+ "http://admobile.com/": ["admobile.com"]
+ }
+ },
+ {
+ "Admotion": {
+ "http://www.admotion.com/": ["admotion.com", "nspmotion.com"]
+ }
+ },
+ {
+ "Adnetik": {
+ "http://adnetik.com/": ["adnetik.com", "wtp101.com"]
+ }
+ },
+ {
+ "AdNetwork.net": {
+ "http://www.adnetwork.net/": ["adnetwork.net"]
+ }
+ },
+ {
+ "Adnium": {
+ "https://adnium.com": ["adnium.com"]
+ }
+ },
+ {
+ "adnologies": {
+ "http://www.adnologies.com/": ["adnologies.com", "heias.com"]
+ }
+ },
+ {
+ "Adobe": {
+ "http://www.adobe.com/": [
+ "2o7.net",
+ "auditude.com",
+ "demdex.com",
+ "demdex.net",
+ "dmtracker.com",
+ "efrontier.com",
+ "everestads.net",
+ "everestjs.net",
+ "everesttech.net",
+ "hitbox.com",
+ "omniture.com",
+ "omtrdc.net",
+ "touchclarity.com"
+ ]
+ }
+ },
+ {
+ "AdOcean": {
+ "http://www.adocean-global.com/": ["adocean-global.com", "adocean.pl"]
+ }
+ },
+ {
+ "Adometry": {
+ "http://www.adometry.com/": ["adometry.com", "dmtry.com"]
+ }
+ },
+ {
+ "Adomik": {
+ "http://www.adomik.com/": ["adomik.com"]
+ }
+ },
+ {
+ "AdOnion": {
+ "http://www.adonion.com/": ["adonion.com"]
+ }
+ },
+ {
+ "Adorika": {
+ "http://www.clickotmedia.com/": ["clickotmedia.com"]
+ }
+ },
+ {
+ "Adotmob": {
+ "https://adotmob.com/": ["adotmob.com"]
+ }
+ },
+ {
+ "ADP Dealer Services": {
+ "http://www.adpdealerservices.com/": [
+ "admission.net",
+ "adpdealerservices.com",
+ "cobalt.com"
+ ]
+ }
+ },
+ {
+ "ad pepper media": {
+ "http://www.adpepper.us/": ["adpepper.com", "adpepper.us"]
+ }
+ },
+ {
+ "AdPerfect": {
+ "http://www.adperfect.com/": ["adperfect.com"]
+ }
+ },
+ {
+ "Adperium": {
+ "http://www.adperium.com/": ["adperium.com"]
+ }
+ },
+ {
+ "Adpersia": {
+ "http://www.adpersia.com/": ["adpersia.com"]
+ }
+ },
+ {
+ "adPrecision": {
+ "http://adprecision.net/": ["adprs.net", "aprecision.net"]
+ }
+ },
+ {
+ "AdPredictive": {
+ "http://www.adpredictive.com/": ["adpredictive.com"]
+ }
+ },
+ {
+ "AdReactor": {
+ "http://www.adreactor.com/": ["adreactor.com"]
+ }
+ },
+ {
+ "AdReady": {
+ "http://www.adready.com/": ["adready.com", "adreadytractions.com"]
+ }
+ },
+ {
+ "AdRevolution": {
+ "http://adrevolution.com/": ["adrevolution.com"]
+ }
+ },
+ {
+ "AdRiver": {
+ "http://adriver.ru/": ["adriver.ru"]
+ }
+ },
+ {
+ "adrolays": {
+ "http://adrolays.com/": ["adrolays.com", "adrolays.de"]
+ }
+ },
+ {
+ "AdRoll": {
+ "http://www.adroll.com/": ["adroll.com"]
+ }
+ },
+ {
+ "adscale": {
+ "http://www.adscale.de/": ["adscale.de"]
+ }
+ },
+ {
+ "Adscience": {
+ "https://www.adscience.nl/": ["adscience.nl"]
+ }
+ },
+ {
+ "AdServerPub": {
+ "http://www.adserverpub.com/": ["adserverpub.com"]
+ }
+ },
+ {
+ "AdShuffle": {
+ "http://www.adshuffle.com/": ["adshuffle.com"]
+ }
+ },
+ {
+ "AdSide": {
+ "http://www.adside.com/": ["adside.com", "doclix.com"]
+ }
+ },
+ {
+ "AdSpeed": {
+ "http://www.adspeed.com/": ["adspeed.com", "adspeed.net"]
+ }
+ },
+ {
+ "Adsperity": {
+ "https://www.adsperity.com/": ["adsperity.com"]
+ }
+ },
+ {
+ "AdSpirit": {
+ "http://www.adspirit.de/": [
+ "adspirit.com",
+ "adspirit.de",
+ "adspirit.net"
+ ]
+ }
+ },
+ {
+ "Adsrevenue.net": {
+ "http://adsrevenue.net/": ["adsrevenue.net"]
+ }
+ },
+ {
+ "AdStir": {
+ "https://en.ad-stir.com/": ["ad-stir.com"]
+ }
+ },
+ {
+ "AdsTours": {
+ "http://www.adstours.com/": ["adstours.com", "clickintext.net"]
+ }
+ },
+ {
+ "Adsty": {
+ "http://adsty.com/": ["adsty.com", "adx1.com"]
+ }
+ },
+ {
+ "Adsupply": {
+ "http://www.adsupply.com/": ["4dsply.com", "adsupply.com"]
+ }
+ },
+ {
+ "Adswizz": {
+ "http://adswizz.com": ["adswizz.com"]
+ }
+ },
+ {
+ "ADTECH": {
+ "http://www.adtech.com/": ["adtech.com", "adtech.de", "adtechus.com"]
+ }
+ },
+ {
+ "Adtegrity.com": {
+ "http://www.adtegrity.com/": ["adtegrity.com", "adtegrity.net"]
+ }
+ },
+ {
+ "ADTELLIGENCE": {
+ "http://www.adtelligence.de/": ["adtelligence.de"]
+ }
+ },
+ {
+ "Adthink": {
+ "https://adthink.com/": ["adthink.com", "audienceinsights.net"]
+ }
+ },
+ {
+ "AdTiger": {
+ "http://www.adtiger.de/": ["adtiger.de"]
+ }
+ },
+ {
+ "AdTruth": {
+ "http://adtruth.com/": ["adtruth.com"]
+ }
+ },
+ {
+ "Adult AdWorld": {
+ "http://adultadworld.com/": ["adultadworld.com"]
+ }
+ },
+ {
+ "Adultmoda": {
+ "http://www.adultmoda.com/": ["adultmoda.com"]
+ }
+ },
+ {
+ "Adventive": {
+ "http://adventive.com/": ["adventive.com"]
+ }
+ },
+ {
+ "Adverline": {
+ "http://www.adverline.com/": ["adnext.fr", "adverline.com"]
+ }
+ },
+ {
+ "Adversal.com": {
+ "http://www.adversal.com/": ["adv-adserver.com", "adversal.com"]
+ }
+ },
+ {
+ "Adverticum": {
+ "http://www.adverticum.com/": [
+ "adsmart.com",
+ "adverticum.com",
+ "adverticum.net"
+ ]
+ }
+ },
+ {
+ "Advertise.com": {
+ "http://www.advertise.com/": ["advertise.com"]
+ }
+ },
+ {
+ "AdvertiseSpace": {
+ "http://www.advertisespace.com/": ["advertisespace.com"]
+ }
+ },
+ {
+ "Advert Stream": {
+ "http://www.advertstream.com/": ["advertstream.com"]
+ }
+ },
+ {
+ "Advisor Media": {
+ "http://advisormedia.cz/": ["advisormedia.cz"]
+ }
+ },
+ {
+ "Adworx": {
+ "http://adworx.at/": ["adworx.at", "adworx.be", "adworx.nl"]
+ }
+ },
+ {
+ "AdXpansion": {
+ "http://www.adxpansion.com/": ["adxpansion.com"]
+ }
+ },
+ {
+ "Adxvalue": {
+ "http://adxvalue.com/": ["adxvalue.com", "adxvalue.de"]
+ }
+ },
+ {
+ "adyard": {
+ "http://adyard.de/": ["adyard.de"]
+ }
+ },
+ {
+ "AdYield": {
+ "http://www.adyield.com/": ["adxyield.com", "adyield.com"]
+ }
+ },
+ {
+ "AdYouLike": {
+ "https://www.adyoulike.com/": [
+ "adyoulike.com",
+ "omnitagjs.com",
+ "pulpix.com"
+ ]
+ }
+ },
+ {
+ "ADZ": {
+ "http://www.adzcentral.com/": ["adzcentral.com"]
+ }
+ },
+ {
+ "Adzerk": {
+ "http://www.adzerk.com/": ["adzerk.com", "adzerk.net"]
+ }
+ },
+ {
+ "adzly": {
+ "http://www.adzly.com/": ["adzly.com"]
+ }
+ },
+ {
+ "Aegis Group": {
+ "http://www.aemedia.com/": ["aemedia.com", "bluestreak.com"]
+ }
+ },
+ {
+ "AERIFY MEDIA": {
+ "http://aerifymedia.com/": ["aerifymedia.com", "anonymous-media.com"]
+ }
+ },
+ {
+ "Affectv": {
+ "http://affectv.co.uk/": ["affectv.co.uk"]
+ }
+ },
+ {
+ "affilinet": {
+ "http://www.affili.net/": [
+ "affili.net",
+ "affilinet-inside.de",
+ "banner-rotation.com",
+ "successfultogether.co.uk"
+ ]
+ }
+ },
+ {
+ "Affine": {
+ "http://www.affine.tv/": ["affine.tv", "affinesystems.com"]
+ }
+ },
+ {
+ "Affinity": {
+ "http://www.affinity.com/": ["affinity.com"]
+ }
+ },
+ {
+ "AfterDownload": {
+ "http://www.afterdownload.com/": ["afdads.com", "afterdownload.com"]
+ }
+ },
+ {
+ "Aim4Media": {
+ "http://aim4media.com/": ["aim4media.com"]
+ }
+ },
+ {
+ "Airpush": {
+ "http://www.airpush.com/": ["airpush.com"]
+ }
+ },
+ {
+ "AK": {
+ "http://www.aggregateknowledge.com/": [
+ "aggregateknowledge.com",
+ "agkn.com"
+ ]
+ }
+ },
+ {
+ "Akamai": {
+ "http://www.akamai.com/": ["imiclk.com"]
+ }
+ },
+ {
+ "Albacross": {
+ "https://albacross.com": ["albacross.com"]
+ }
+ },
+ {
+ "AllStarMediaGroup": {
+ "http://allstarmediagroup.com/": ["allstarmediagroup.com"]
+ }
+ },
+ {
+ "Aloodo": {
+ "https://aloodo.com/": ["aloodo.com"]
+ }
+ },
+ {
+ "AlterGeo": {
+ "http://altergeo.ru/": ["altergeo.ru"]
+ }
+ },
+ {
+ "Amazon.com": {
+ "http://www.amazon.com/": [
+ "amazon-adsystem.com",
+ "amazon.ca",
+ "amazon.co.jp",
+ "amazon.co.uk",
+ "amazon.de",
+ "amazon.es",
+ "amazon.fr",
+ "amazon.it",
+ "assoc-amazon.com"
+ ]
+ }
+ },
+ {
+ "Ambient Digital": {
+ "http://ambientdigital.com.vn/": [
+ "adnetwork.vn",
+ "ambientdigital.com.vn"
+ ]
+ }
+ },
+ {
+ "Amobee": {
+ "http://amobee.com/": [
+ "adconion.com",
+ "amgdgt.com",
+ "amobee.com",
+ "euroclick.com",
+ "smartclip.com",
+ "turn.com"
+ ]
+ }
+ },
+ {
+ "AndBeyond": {
+ "http://andbeyond.media/": ["andbeyond.media"]
+ }
+ },
+ {
+ "Answers.com": {
+ "http://www.answers.com/": ["dsply.com"]
+ }
+ },
+ {
+ "AOL": {
+ "http://www.aol.com/": [
+ "adsonar.com",
+ "adtechjp.com",
+ "advertising.com",
+ "aolcloud.net",
+ "atwola.com",
+ "leadback.com",
+ "tacoda.net",
+ "vidible.tv"
+ ]
+ }
+ },
+ {
+ "AppCast": {
+ "https://appcast.io/": ["appcast.io"]
+ }
+ },
+ {
+ "Appenda": {
+ "http://www.appenda.com/": ["appenda.com"]
+ }
+ },
+ {
+ "AppFlood": {
+ "http://appflood.com/": ["appflood.com"]
+ }
+ },
+ {
+ "Appier": {
+ "http://appier.com/": ["appier.com"]
+ }
+ },
+ {
+ "Applifier": {
+ "http://www.applifier.com/": ["applifier.com"]
+ }
+ },
+ {
+ "Applovin": {
+ "http://www.applovin.com/": ["applovin.com"]
+ }
+ },
+ {
+ "AppNexus": {
+ "http://www.appnexus.com/": [
+ "adlantic.nl",
+ "adnxs.com",
+ "adrdgt.com",
+ "alenty.com",
+ "appnexus.com"
+ ]
+ }
+ },
+ {
+ "AppsFlyer": {
+ "http://appsflyer.com/": ["appsflyer.com"]
+ }
+ },
+ {
+ "appssavvy": {
+ "http://appssavvy.com/": ["appssavvy.com"]
+ }
+ },
+ {
+ "Arkwrights Homebrew": {
+ "http://www.arkwrightshomebrew.com/": [
+ "arkwrightshomebrew.com",
+ "ctasnet.com"
+ ]
+ }
+ },
+ {
+ "AT Internet": {
+ "http://www.atinternet.com/": ["hit-parade.com"]
+ }
+ },
+ {
+ "ATN": {
+ "http://affiliatetracking.com/": ["affiliatetracking.com"]
+ }
+ },
+ {
+ "Atoomic.com": {
+ "http://www.atoomic.com/": ["atoomic.com"]
+ }
+ },
+ {
+ "Atrinsic": {
+ "http://atrinsic.com/": ["atrinsic.com"]
+ }
+ },
+ {
+ "AT&T": {
+ "http://www.att.com/": ["att.com", "yp.com"]
+ }
+ },
+ {
+ "Audience2Media": {
+ "http://www.audience2media.com/": ["audience2media.com"]
+ }
+ },
+ {
+ "Audience Ad Network": {
+ "http://audienceadnetwork.com/": ["audienceadnetwork.com"]
+ }
+ },
+ {
+ "AudienceScience": {
+ "http://www.audiencescience.com/": [
+ "audiencescience.com",
+ "revsci.net",
+ "targetingmarketplace.com",
+ "wunderloop.net"
+ ]
+ }
+ },
+ {
+ "Augme": {
+ "http://www.augme.com/": ["augme.com", "hipcricket.com"]
+ }
+ },
+ {
+ "Augur": {
+ "http://www.augur.io/": ["augur.io"]
+ }
+ },
+ {
+ "AUTOCENTRE.UA": {
+ "http://www.autocentre.ua/": ["am.ua", "autocentre.ua"]
+ }
+ },
+ {
+ "Automattic": {
+ "http://automattic.com/": ["pubmine.com"]
+ }
+ },
+ {
+ "Avalanchers": {
+ "http://www.avalanchers.com/": ["avalanchers.com"]
+ }
+ },
+ {
+ "AvantLink": {
+ "http://www.avantlink.com/": ["avantlink.com"]
+ }
+ },
+ {
+ "Avocet": {
+ "https://avocet.io/": ["avocet.io"]
+ }
+ },
+ {
+ "Avsads": {
+ "http://avsads.com/": ["avsads.com"]
+ }
+ },
+ {
+ "AWeber": {
+ "http://www.aweber.com/": ["aweber.com"]
+ }
+ },
+ {
+ "Awin": {
+ "http://www.awin.com/": [
+ "digitalwindow.com",
+ "dwin1.com",
+ "perfiliate.com"
+ ]
+ }
+ },
+ {
+ "Azet": {
+ "http://mediaimpact.sk/": ["azetklik.sk", "rsz.sk"]
+ }
+ },
+ {
+ "BackBeat Media": {
+ "http://www.backbeatmedia.com/": ["backbeatmedia.com"]
+ }
+ },
+ {
+ "Bannerconnect": {
+ "http://www.bannerconnect.net/": ["bannerconnect.net"]
+ }
+ },
+ {
+ "Barilliance": {
+ "http://www.barilliance.com/": ["barilliance.com"]
+ }
+ },
+ {
+ "BaronsNetworks": {
+ "http://baronsoffers.com/": ["baronsoffers.com"]
+ }
+ },
+ {
+ "Batanga Network": {
+ "http://www.batanganetwork.com/": [
+ "batanga.com",
+ "batanganetwork.com"
+ ]
+ }
+ },
+ {
+ "BeachFront": {
+ "http://beachfront.com/": ["beachfront.com"]
+ }
+ },
+ {
+ "Beanstock Media": {
+ "http://www.beanstockmedia.com/": ["beanstockmedia.com"]
+ }
+ },
+ {
+ "beencounter": {
+ "http://www.beencounter.com/": ["beencounter.com"]
+ }
+ },
+ {
+ "Begun": {
+ "http://www.begun.ru/": ["begun.ru"]
+ }
+ },
+ {
+ "belboon": {
+ "http://www.belboon.com/": ["adbutler.de", "belboon.com"]
+ }
+ },
+ {
+ "Betgenius": {
+ "http://www.betgenius.com/": ["betgenius.com", "connextra.com"]
+ }
+ },
+ {
+ "BetweenDigital": {
+ "http://betweendigital.com": ["betweendigital.com"]
+ }
+ },
+ {
+ "Bidfluence": {
+ "https://www.bidfluence.com/": ["bidfluence.com"]
+ }
+ },
+ {
+ "Bidr": {
+ "http://bidr.io": ["bidr.io"]
+ }
+ },
+ {
+ "BidSwitch": {
+ "https://www.bidswitch.com/": ["bidswitch.net", "mfadsrvr.com"]
+ }
+ },
+ {
+ "Bidtellect": {
+ "https://www.bidtellect.com/": ["bidtellect.com", "bttrack.com"]
+ }
+ },
+ {
+ "BidVertiser": {
+ "http://www.bidvertiser.com/": ["bidvertiser.com"]
+ }
+ },
+ {
+ "BigClick": {
+ "http://bigclick.me/": ["bgclck.me", "xcvgdf.party"]
+ }
+ },
+ {
+ "bigmirnet": {
+ "http://www.bigmir.net/": ["bigmir.net"]
+ }
+ },
+ {
+ "BinLayer": {
+ "http://binlayer.com/": ["binlayer.com"]
+ }
+ },
+ {
+ "Bitcoin Plus": {
+ "http://www.bitcoinplus.com/": ["bitcoinplus.com"]
+ }
+ },
+ {
+ "BitMedia": {
+ "https://bitmedia.io/": ["bitmedia.io"]
+ }
+ },
+ {
+ "BittAds": {
+ "http://www.bittads.com/": ["bittads.com"]
+ }
+ },
+ {
+ "Bizo": {
+ "http://www.bizo.com/": ["bizo.com", "bizographics.com"]
+ }
+ },
+ {
+ "Black Label Ads": {
+ "http://www.blacklabelads.com/": ["blacklabelads.com"]
+ }
+ },
+ {
+ "BlogCatalog": {
+ "http://www.blogcatalog.com/": ["blogcatalog.com"]
+ }
+ },
+ {
+ "BlogFrog": {
+ "http://theblogfrog.com/": ["theblogfrog.com"]
+ }
+ },
+ {
+ "BlogHer": {
+ "http://www.blogher.com/": ["blogher.com", "blogherads.com"]
+ }
+ },
+ {
+ "BlogRollr": {
+ "http://blogrollr.com/": ["blogrollr.com"]
+ }
+ },
+ {
+ "BLOOM Digital Platforms": {
+ "http://bloom-hq.com/": ["adgear.com", "adgrx.com", "bloom-hq.com"]
+ }
+ },
+ {
+ "BlueKai": {
+ "http://www.bluekai.com/": [
+ "bkrtx.com",
+ "bluekai.com",
+ "tracksimple.com"
+ ]
+ }
+ },
+ {
+ "Blu Trumpet": {
+ "http://www.blutrumpet.com/": ["blutrumpet.com"]
+ }
+ },
+ {
+ "Boo-Box": {
+ "http://boo-box.com/": ["boo-box.com"]
+ }
+ },
+ {
+ "BoostBox": {
+ "https://www.boostbox.com.br/": ["boostbox.com.br"]
+ }
+ },
+ {
+ "Bouncex": {
+ "https://www.bouncex.com/": [
+ "bounceexchange.com",
+ "bouncex.com",
+ "bouncex.net"
+ ]
+ }
+ },
+ {
+ "Brainient": {
+ "http://brainient.com/": ["brainient.com"]
+ }
+ },
+ {
+ "Brand Affinity Technologies": {
+ "http://www.brandaffinity.net/": ["brandaffinity.net"]
+ }
+ },
+ {
+ "Brandcrumb": {
+ "http://www.brandcrumb.com": ["brandcrumb.com"]
+ }
+ },
+ {
+ "Brand.net": {
+ "http://www.brand.net/": ["brand.net"]
+ }
+ },
+ {
+ "Brandscreen": {
+ "http://www.brandscreen.com/": ["brandscreen.com", "rtbidder.net"]
+ }
+ },
+ {
+ "BreakTime": {
+ "https://www.breaktime.com.tw/": ["breaktime.com.tw"]
+ }
+ },
+ {
+ "BrightRoll": {
+ "http://www.brightroll.com/": ["brightroll.com", "btrll.com"]
+ }
+ },
+ {
+ "BrightTag": {
+ "http://www.brighttag.com/": [
+ "brighttag.com",
+ "btstatic.com",
+ "thebrighttag.com"
+ ]
+ }
+ },
+ {
+ "Brilig": {
+ "http://www.brilig.com/": ["brilig.com"]
+ }
+ },
+ {
+ "BuckSense": {
+ "http://www.bucksense.com": ["bucksense.com"]
+ }
+ },
+ {
+ "Burstly": {
+ "http://www.burstly.com/": ["burstly.com"]
+ }
+ },
+ {
+ "Burst Media": {
+ "http://www.burstmedia.com/": [
+ "burstbeacon.com",
+ "burstdirectads.com",
+ "burstmedia.com",
+ "burstnet.com",
+ "giantrealm.com"
+ ]
+ }
+ },
+ {
+ "BusinessOnline": {
+ "http://www.businessol.com/": ["businessol.com"]
+ }
+ },
+ {
+ "Button": {
+ "https://www.usebutton.com": ["usebutton.com"]
+ }
+ },
+ {
+ "BuySellAds": {
+ "http://buysellads.com/": ["beaconads.com", "buysellads.com"]
+ }
+ },
+ {
+ "Buysight": {
+ "http://www.buysight.com/": [
+ "buysight.com",
+ "permuto.com",
+ "pulsemgr.com"
+ ]
+ }
+ },
+ {
+ "BuzzParadise": {
+ "http://www.buzzparadise.com/": ["buzzparadise.com"]
+ }
+ },
+ {
+ "BV! MEDIA": {
+ "http://www.bvmedia.ca/": [
+ "bvmedia.ca",
+ "networldmedia.com",
+ "networldmedia.net"
+ ]
+ }
+ },
+ {
+ "c1exchange": {
+ "https://c1exchange.com/": ["c1exchange.com"]
+ }
+ },
+ {
+ "C3 Metrics": {
+ "http://c3metrics.com/": [
+ "attributionmodel.com",
+ "c3metrics.com",
+ "c3tag.com"
+ ]
+ }
+ },
+ {
+ "Cadreon": {
+ "http://www.cadreon.com/": ["cadreon.com"]
+ }
+ },
+ {
+ "CampaignGrid": {
+ "http://www.campaigngrid.com/": ["campaigngrid.com"]
+ }
+ },
+ {
+ "CAPITALDATA": {
+ "http://www.capitaldata.fr/": ["capitaldata.fr"]
+ }
+ },
+ {
+ "Carambola": {
+ "https://www.carambola.com/": ["carambo.la"]
+ }
+ },
+ {
+ "Caraytech": {
+ "http://www.caraytech.com.ar/": ["caraytech.com.ar", "e-planning.net"]
+ }
+ },
+ {
+ "Cart.ro": {
+ "http://www.cart.ro/": ["cart.ro", "statistics.ro"]
+ }
+ },
+ {
+ "CartsGuru": {
+ "https://carts.guru/": ["carts.guru"]
+ }
+ },
+ {
+ "Casale Media": {
+ "http://www.casalemedia.com/": ["casalemedia.com", "medianet.com"]
+ }
+ },
+ {
+ "CBproADS": {
+ "http://www.cbproads.com/": ["cbproads.com"]
+ }
+ },
+ {
+ "Cedato": {
+ "https://www.cedato.com/": ["cedato.com"]
+ }
+ },
+ {
+ "Chango": {
+ "http://www.chango.com/": ["chango.ca", "chango.com"]
+ }
+ },
+ {
+ "ChannelAdvisor": {
+ "http://www.channeladvisor.com/": [
+ "channeladvisor.com",
+ "searchmarketing.com"
+ ]
+ }
+ },
+ {
+ "Channel Intelligence": {
+ "http://www.channelintelligence.com/": ["channelintelligence.com"]
+ }
+ },
+ {
+ "Chartboost": {
+ "https://www.chartboost.com/": ["chartboost.com"]
+ }
+ },
+ {
+ "CheckM8": {
+ "http://www.checkm8.com/": ["checkm8.com"]
+ }
+ },
+ {
+ "Chitika": {
+ "http://chitika.com/": ["chitika.com", "chitika.net"]
+ }
+ },
+ {
+ "ChoiceStream": {
+ "http://www.choicestream.com/": ["choicestream.com"]
+ }
+ },
+ {
+ "ClearLink": {
+ "https://www.clearlink.com/": ["clearlink.com"]
+ }
+ },
+ {
+ "ClearSaleing": {
+ "http://www.clearsaleing.com/": [
+ "clearsaleing.com",
+ "csdata1.com",
+ "csdata2.com",
+ "csdata3.com"
+ ]
+ }
+ },
+ {
+ "Clearsearch Media": {
+ "http://www.clearsearchmedia.com/": [
+ "clearsearchmedia.com",
+ "csm-secure.com"
+ ]
+ }
+ },
+ {
+ "ClearSight Interactive": {
+ "http://www.clearsightinteractive.com/": [
+ "clearsightinteractive.com",
+ "csi-tracking.com"
+ ]
+ }
+ },
+ {
+ "ClickAider": {
+ "http://clickaider.com/": ["clickaider.com"]
+ }
+ },
+ {
+ "Clickayab": {
+ "http://www.clickyab.com": ["clickyab.com"]
+ }
+ },
+ {
+ "Clickbooth": {
+ "http://www.clickbooth.com/": ["adtoll.com", "clickbooth.com"]
+ }
+ },
+ {
+ "ClickDimensions": {
+ "http://www.clickdimensions.com/": ["clickdimensions.com"]
+ }
+ },
+ {
+ "ClickDistrict": {
+ "http://www.clickdistrict.com/": [
+ "clickdistrict.com",
+ "creative-serving.com"
+ ]
+ }
+ },
+ {
+ "ClickFrog": {
+ "https://clickfrog.ru/": [
+ "bashirian.biz",
+ "buckridge.link",
+ "clickfrog.ru",
+ "franecki.net",
+ "quitzon.net",
+ "reichelcormier.bid",
+ "wisokykulas.bid"
+ ]
+ }
+ },
+ {
+ "ClickFuel": {
+ "http://clickfuel.com/": ["conversiondashboard.com"]
+ }
+ },
+ {
+ "ClickInc": {
+ "http://www.clickinc.com/": ["clickinc.com"]
+ }
+ },
+ {
+ "Clicksor": {
+ "http://www.clicksor.com/": ["clicksor.com", "clicksor.net"]
+ }
+ },
+ {
+ "Clickwinks": {
+ "http://www.clickwinks.com/": ["clickwinks.com"]
+ }
+ },
+ {
+ "ClicManager": {
+ "http://www.clicmanager.fr/": ["clicmanager.fr"]
+ }
+ },
+ {
+ "Clixtell": {
+ "https://www.clixtell.com/": ["clixtell.com"]
+ }
+ },
+ {
+ "Clove Network": {
+ "http://www.clovenetwork.com/": ["clovenetwork.com"]
+ }
+ },
+ {
+ "Cognitive Match": {
+ "http://www.cognitivematch.com/": [
+ "cmads.com.tw",
+ "cmadsasia.com",
+ "cmadseu.com",
+ "cmmeglobal.com",
+ "cognitivematch.com"
+ ]
+ }
+ },
+ {
+ "Collective": {
+ "http://collective.com/": [
+ "collective-media.net",
+ "collective.com",
+ "oggifinogi.com",
+ "tumri.com",
+ "tumri.net",
+ "yt1187.net"
+ ]
+ }
+ },
+ {
+ "Commission Junction": {
+ "http://www.cj.com/": [
+ "apmebf.com",
+ "awltovhc.com",
+ "cj.com",
+ "ftjcfx.com",
+ "kcdwa.com",
+ "qksz.com",
+ "qksz.net",
+ "tqlkg.com",
+ "yceml.net"
+ ]
+ }
+ },
+ {
+ "Communicator Corp": {
+ "http://www.communicatorcorp.com/": ["communicatorcorp.com"]
+ }
+ },
+ {
+ "Compass Labs": {
+ "http://compasslabs.com/": ["compasslabs.com"]
+ }
+ },
+ {
+ "Complex Media": {
+ "http://www.complexmedianetwork.com/": [
+ "complex.com",
+ "complexmedianetwork.com"
+ ]
+ }
+ },
+ {
+ "comScore": {
+ "http://www.comscore.com/": [
+ "adxpose.com",
+ "proxilinks.com",
+ "proximic.com",
+ "proximic.net"
+ ]
+ }
+ },
+ {
+ "Connatix.com": {
+ "https://connatix.com/": ["connatix.com"]
+ }
+ },
+ {
+ "Connexity": {
+ "http://www.connexity.com/": ["pricegrabber.com"]
+ }
+ },
+ {
+ "Consilium Media": {
+ "http://www.consiliummedia.com/": ["consiliummedia.com"]
+ }
+ },
+ {
+ "Consumable": {
+ "http://consumable.com/": ["consumable.com"]
+ }
+ },
+ {
+ "CONTAXE": {
+ "http://www.contaxe.com/": ["contaxe.com"]
+ }
+ },
+ {
+ "ContentABC": {
+ "http://contentabc.com/": ["contentabc.com"]
+ }
+ },
+ {
+ "CONTEXTin": {
+ "http://www.contextin.com/": ["admailtiser.com", "contextin.com"]
+ }
+ },
+ {
+ "ContextuAds": {
+ "http://www.contextuads.com/": [
+ "agencytradingdesk.net",
+ "contextuads.com"
+ ]
+ }
+ },
+ {
+ "CONTEXTWEB": {
+ "http://www.contextweb.com/": ["contextweb.com"]
+ }
+ },
+ {
+ "ConvergeDirect": {
+ "http://www.convergedirect.com/": [
+ "convergedirect.com",
+ "convergetrack.com"
+ ]
+ }
+ },
+ {
+ "ConversantMedia": {
+ "http://conversantmedia.com": [
+ "adserver.com",
+ "conversantmedia.com",
+ "dotomi.com",
+ "dtmpub.com",
+ "emjcd.com",
+ "fastclick.com",
+ "fastclick.net",
+ "greystripe.com",
+ "lduhtrp.net",
+ "mediaplex.com",
+ "valueclick.com",
+ "valueclick.net",
+ "valueclickmedia.com"
+ ]
+ }
+ },
+ {
+ "ConversionRuler": {
+ "http://www.conversionruler.com/": ["conversionruler.com"]
+ }
+ },
+ {
+ "Conversive": {
+ "http://www.conversive.nl/": ["conversive.nl"]
+ }
+ },
+ {
+ "CoreMotives": {
+ "http://coremotives.com/": ["coremotives.com"]
+ }
+ },
+ {
+ "Cox Digital Solutions": {
+ "http://www.coxdigitalsolutions.com/": [
+ "adify.com",
+ "afy11.net",
+ "coxdigitalsolutions.com"
+ ]
+ }
+ },
+ {
+ "CPMStar": {
+ "http://www.cpmstar.com/": ["cpmstar.com"]
+ }
+ },
+ {
+ "CPX Interactive": {
+ "http://www.cpxinteractive.com/": [
+ "adreadypixels.com",
+ "cpxadroit.com",
+ "cpxinteractive.com"
+ ]
+ }
+ },
+ {
+ "Creafi": {
+ "http://www.creafi.com/": ["creafi.com"]
+ }
+ },
+ {
+ "Crimtan": {
+ "http://www.crimtan.com/": ["crimtan.com"]
+ }
+ },
+ {
+ "Crisp Media": {
+ "http://www.crispmedia.com/": ["crispmedia.com"]
+ }
+ },
+ {
+ "Criteo": {
+ "http://www.criteo.com/": [
+ "criteo.com",
+ "criteo.net",
+ "hlserve.com",
+ "hooklogic.com",
+ "storetail.io"
+ ]
+ }
+ },
+ {
+ "Cross Pixel": {
+ "http://crosspixel.net/": [
+ "crosspixel.net",
+ "crosspixelmedia.com",
+ "crsspxl.com"
+ ]
+ }
+ },
+ {
+ "cXense": {
+ "http://www.cxense.com/": [
+ "cxense.com",
+ "emediate.biz",
+ "emediate.com",
+ "emediate.dk",
+ "emediate.eu"
+ ]
+ }
+ },
+ {
+ "Cyberplex": {
+ "http://www.cyberplex.com/": ["cyberplex.com"]
+ }
+ },
+ {
+ "Dada": {
+ "http://dada.pro/": ["dada.pro", "simply.com"]
+ }
+ },
+ {
+ "Datalogix": {
+ "http://www.datalogix.com/": ["nexac.com", "nextaction.net"]
+ }
+ },
+ {
+ "DataXu": {
+ "http://www.dataxu.com/": [
+ "dataxu.com",
+ "dataxu.net",
+ "mexad.com",
+ "w55c.net"
+ ]
+ }
+ },
+ {
+ "Datonics": {
+ "http://datonics.com/": ["datonics.com", "pro-market.net"]
+ }
+ },
+ {
+ "Datran Media": {
+ "http://www.datranmedia.com/": [
+ "datranmedia.com",
+ "displaymarketplace.com"
+ ]
+ }
+ },
+ {
+ "Datvantage": {
+ "http://datvantage.com/": ["datvantage.com"]
+ }
+ },
+ {
+ "DC Storm": {
+ "http://www.dc-storm.com/": ["dc-storm.com", "stormiq.com"]
+ }
+ },
+ {
+ "Dedicated Media": {
+ "http://www.dedicatedmedia.com/": [
+ "dedicatedmedia.com",
+ "dedicatednetworks.com"
+ ]
+ }
+ },
+ {
+ "Delivr": {
+ "http://delivr.com/": ["delivr.com", "percentmobile.com"]
+ }
+ },
+ {
+ "Delta Projects": {
+ "http://www.deltaprojects.se/": [
+ "adaction.se",
+ "de17a.com",
+ "deltaprojects.se"
+ ]
+ }
+ },
+ {
+ "Demand Media": {
+ "http://www.demandmedia.com/": ["demandmedia.com", "indieclick.com"]
+ }
+ },
+ {
+ "Deutsche Post DHL": {
+ "http://www.dp-dhl.com/": ["adcloud.com", "adcloud.net", "dp-dhl.com"]
+ }
+ },
+ {
+ "Developer Media": {
+ "http://developermedia.com/": ["developermedia.com", "lqcdn.com"]
+ }
+ },
+ {
+ "DG": {
+ "http://www.dgit.com/": [
+ "dgit.com",
+ "eyeblaster.com",
+ "eyewonder.com",
+ "mdadx.com",
+ "serving-sys.com",
+ "unicast.com"
+ ]
+ }
+ },
+ {
+ "dianomi": {
+ "http://www.dianomi.com/": ["dianomi.com"]
+ }
+ },
+ {
+ "Didit": {
+ "http://www.didit.com/": ["did-it.com", "didit.com"]
+ }
+ },
+ {
+ "DigitalAdConsortium": {
+ "https://www.dac.co.jp/": ["impact-ad.jp"]
+ }
+ },
+ {
+ "Digital River": {
+ "http://www.digitalriver.com/": [
+ "digitalriver.com",
+ "keywordmax.com",
+ "netflame.cc"
+ ]
+ }
+ },
+ {
+ "Digital Target": {
+ "http://digitaltarget.ru": ["digitaltarget.ru"]
+ }
+ },
+ {
+ "Digitize": {
+ "http://www.digitize.ie/": ["digitize.ie"]
+ }
+ },
+ {
+ "DirectAdvert": {
+ "http://www.directadvert.ru/": ["directadvert.ru"]
+ }
+ },
+ {
+ "Direct Response Group": {
+ "http://www.directresponsegroup.com/": [
+ "directresponsegroup.com",
+ "ppctracking.net"
+ ]
+ }
+ },
+ {
+ "Directtrack": {
+ "http://directtrack.com/": ["directtrack.com"]
+ }
+ },
+ {
+ "Disqus": {
+ "http://disqus.com/": ["disqusads.com"]
+ }
+ },
+ {
+ "DistrictM": {
+ "https://districtm.net": ["districtm.io"]
+ }
+ },
+ {
+ "dmpxs": {
+ "http://bob.dmpxs.com": ["dmpxs.com"]
+ }
+ },
+ {
+ "DoublePimp": {
+ "http://doublepimp.com/": ["doublepimp.com"]
+ }
+ },
+ {
+ "DoublePositive": {
+ "http://www.doublepositive.com/": [
+ "bid-tag.com",
+ "doublepositive.com"
+ ]
+ }
+ },
+ {
+ "Drawbridge": {
+ "http://drawbrid.ge/": ["adsymptotic.com", "drawbrid.ge"]
+ }
+ },
+ {
+ "DS-IQ": {
+ "http://www.ds-iq.com/": ["ds-iq.com"]
+ }
+ },
+ {
+ "DSNR Group": {
+ "http://www.dsnrmg.com/": [
+ "dsnrgroup.com",
+ "dsnrmg.com",
+ "traffiliate.com",
+ "z5x.com",
+ "z5x.net"
+ ]
+ }
+ },
+ {
+ "DynAdmic": {
+ "https://dynadmic.com/": ["dynadmic.com", "dyntrk.com"]
+ }
+ },
+ {
+ "DynamicOxygen": {
+ "http://www.dynamicoxygen.com/": [
+ "dynamicoxygen.com",
+ "exitjunction.com"
+ ]
+ }
+ },
+ {
+ "DynamicYield": {
+ "https://www.dynamicyield.com/": [
+ "px-eu.dynamicyield.com",
+ "px.dynamicyield.com"
+ ]
+ }
+ },
+ {
+ "Earnify": {
+ "http://earnify.com/": ["earnify.com"]
+ }
+ },
+ {
+ "eBay": {
+ "http://www.ebay.com/": ["ebay.com"]
+ }
+ },
+ {
+ "Effective Measure": {
+ "http://www.effectivemeasure.com/": [
+ "effectivemeasure.com",
+ "effectivemeasure.net"
+ ]
+ }
+ },
+ {
+ "ekolay": {
+ "http://www.ekolay.net/": ["e-kolay.net", "ekolay.net"]
+ }
+ },
+ {
+ "Eleavers": {
+ "http://eleavers.com/": ["eleavers.com"]
+ }
+ },
+ {
+ "Emego": {
+ "http://www.usemax.de/": ["usemax.de"]
+ }
+ },
+ {
+ "Emerse": {
+ "https://www.emerse.com": ["emerse.com"]
+ }
+ },
+ {
+ "EMX": {
+ "https://emxdigital.com/": [
+ "brealtime.com",
+ "clearstream.tv",
+ "emxdgt.com",
+ "emxdigital.com"
+ ]
+ }
+ },
+ {
+ "Enecto": {
+ "http://www.enecto.com/": ["enecto.com"]
+ }
+ },
+ {
+ "engage:BDR": {
+ "http://engagebdr.com/": ["bnmla.com", "engagebdr.com"]
+ }
+ },
+ {
+ "Engago Technology": {
+ "http://www.engago.com/": ["appmetrx.com", "engago.com"]
+ }
+ },
+ {
+ "Engine Network": {
+ "http://enginenetwork.com/": ["enginenetwork.com"]
+ }
+ },
+ {
+ "Ensighten": {
+ "http://www.ensighten.com/": ["ensighten.com"]
+ }
+ },
+ {
+ "Entireweb": {
+ "http://www.entireweb.com/": ["entireweb.com"]
+ }
+ },
+ {
+ "Epic Media Group": {
+ "http://www.theepicmediagroup.com/": [
+ "epicadvertising.com",
+ "epicmarketplace.com",
+ "epicmobileads.com",
+ "theepicmediagroup.com",
+ "trafficmp.com"
+ ]
+ }
+ },
+ {
+ "Epsilon": {
+ "http://www.epsilon.com/": ["epsilon.com"]
+ }
+ },
+ {
+ "EQ Ads": {
+ "http://www.eqads.com/": ["eqads.com"]
+ }
+ },
+ {
+ "EroAdvertising": {
+ "http://www.ero-advertising.com/": ["ero-advertising.com"]
+ }
+ },
+ {
+ "Etarget": {
+ "http://etargetnet.com/": ["etarget.eu", "etargetnet.com"]
+ }
+ },
+ {
+ "Etineria": {
+ "http://www.etineria.com/": ["adwitserver.com", "etineria.com"]
+ }
+ },
+ {
+ "eTrigue": {
+ "http://www.etrigue.com/": ["etrigue.com"]
+ }
+ },
+ {
+ "Evergage": {
+ "http://www.evergage.com": ["mybuys.com", "veruta.com"]
+ }
+ },
+ {
+ "Everyday Health": {
+ "http://www.everydayhealth.com/": [
+ "everydayhealth.com",
+ "waterfrontmedia.com"
+ ]
+ }
+ },
+ {
+ "Evisions Marketing": {
+ "http://www.evisionsmarketing.com/": [
+ "engineseeker.com",
+ "evisionsmarketing.com"
+ ]
+ }
+ },
+ {
+ "Evolve": {
+ "http://www.evolvemediacorp.com/": [
+ "evolvemediacorp.com",
+ "evolvemediametrics.com",
+ "gorillanation.com"
+ ]
+ }
+ },
+ {
+ "eWayDirect": {
+ "http://www.ewaydirect.com/": ["ewaydirect.com", "ixs1.net"]
+ }
+ },
+ {
+ "ewebse": {
+ "http://ewebse.com/": ["777seo.com", "ewebse.com"]
+ }
+ },
+ {
+ "excitad": {
+ "http://excitad.com/": ["excitad.com"]
+ }
+ },
+ {
+ "eXelate": {
+ "http://exelate.com/": ["exelate.com", "exelator.com"]
+ }
+ },
+ {
+ "ExoClick": {
+ "http://www.exoclick.com/": ["exoclick.com"]
+ }
+ },
+ {
+ "Exosrv": {
+ "http://main.exosrv.com/": ["exosrv.com"]
+ }
+ },
+ {
+ "Experian": {
+ "http://www.experian.com/": ["audienceiq.com", "experian.com"]
+ }
+ },
+ {
+ "expo-MAX": {
+ "http://expo-max.com/": ["expo-max.com"]
+ }
+ },
+ {
+ "Exponential Interactive": {
+ "http://www.exponential.com/": [
+ "adotube.com",
+ "exponential.com",
+ "fulltango.com",
+ "tribalfusion.com"
+ ]
+ }
+ },
+ {
+ "Extension Factory": {
+ "http://www.extensionfactory.com/": ["extensionfactory.com"]
+ }
+ },
+ {
+ "EXTENSIONS.RU": {
+ "http://extensions.ru/": ["extensions.ru"]
+ }
+ },
+ {
+ "Eyeconomy": {
+ "http://www.eyeconomy.co.uk/": [
+ "eyeconomy.co.uk",
+ "eyeconomy.com",
+ "sublimemedia.net"
+ ]
+ }
+ },
+ {
+ "EyeNewton": {
+ "http://eyenewton.ru/": ["eyenewton.ru"]
+ }
+ },
+ {
+ "eyeReturn Marketing": {
+ "http://www.eyereturnmarketing.com/": [
+ "eyereturn.com",
+ "eyereturnmarketing.com"
+ ]
+ }
+ },
+ {
+ "Eyeviewdigital": {
+ "http://www.eyeviewdigital.com/": ["eyeviewdigital.com"]
+ }
+ },
+ {
+ "Facebook": {
+ "http://www.facebook.com/": ["atlassolutions.com"]
+ }
+ },
+ {
+ "Facilitate Digital": {
+ "http://www.facilitatedigital.com/": [
+ "adsfac.eu",
+ "adsfac.info",
+ "adsfac.net",
+ "adsfac.sg",
+ "adsfac.us",
+ "facilitatedigital.com"
+ ]
+ }
+ },
+ {
+ "Fairfax Media": {
+ "http://www.fxj.com.au/": ["fairfax.com.au", "fxj.com.au"]
+ }
+ },
+ {
+ "faithadnet": {
+ "http://www.faithadnet.com/": ["faithadnet.com"]
+ }
+ },
+ {
+ "Fanplayr": {
+ "https://fanplayr.com/": ["fanplayr.com"]
+ }
+ },
+ {
+ "Fathom": {
+ "http://www.fathomdelivers.com/": [
+ "fathomdelivers.com",
+ "fathomseo.com"
+ ]
+ }
+ },
+ {
+ "Federated Media": {
+ "http://www.federatedmedia.net/": [
+ "federatedmedia.net",
+ "fmpub.net",
+ "lijit.com"
+ ]
+ }
+ },
+ {
+ "FetchBack": {
+ "http://www.fetchback.com/": ["fetchback.com"]
+ }
+ },
+ {
+ "Fiksu": {
+ "http://www.fiksu.com/": ["fiksu.com"]
+ }
+ },
+ {
+ "FinancialContent": {
+ "http://www.financialcontent.com/": ["financialcontent.com"]
+ }
+ },
+ {
+ "Fizz-Buzz Media": {
+ "http://www.fizzbuzzmedia.com/": [
+ "fizzbuzzmedia.com",
+ "fizzbuzzmedia.net"
+ ]
+ }
+ },
+ {
+ "Flashtalking": {
+ "http://www.flashtalking.com/": ["flashtalking.com"]
+ }
+ },
+ {
+ "Flite": {
+ "http://www.flite.com/": ["flite.com", "widgetserver.com"]
+ }
+ },
+ {
+ "Fluct": {
+ "https://corp.fluct.jp/": ["adingo.jp", "fluct.jp"]
+ }
+ },
+ {
+ "Flytxt": {
+ "http://www.flytxt.com/": ["flytxt.com"]
+ }
+ },
+ {
+ "Forbes": {
+ "http://www.forbes.com/": ["brandsideplatform.com", "forbes.com"]
+ }
+ },
+ {
+ "Fox One Stop Media": {
+ "http://www.foxonestop.com/": [
+ "fimserve.com",
+ "foxnetworks.com",
+ "foxonestop.com",
+ "mobsmith.com",
+ "myads.com",
+ "othersonline.com"
+ ]
+ }
+ },
+ {
+ "FreakOut": {
+ "http://fout.jp/": ["fout.jp"]
+ }
+ },
+ {
+ "Freedom Communications": {
+ "http://www.freedom.com/": ["freedom.com"]
+ }
+ },
+ {
+ "FreeWheel": {
+ "http://www.freewheel.tv/": ["stickyadstv.com"]
+ }
+ },
+ {
+ "FriendFinder Networks": {
+ "http://ffn.com/": ["adultfriendfinder.com", "ffn.com", "pop6.com"]
+ }
+ },
+ {
+ "Friends2Follow": {
+ "https://friends2follow.com/": ["tracking.friends2follow.com"]
+ }
+ },
+ {
+ "Frog Sex": {
+ "http://www.frogsex.com/": ["double-check.com", "frogsex.com"]
+ }
+ },
+ {
+ "FuelX": {
+ "https://fuelx.com/": ["fuel451.com", "fuelx.com"]
+ }
+ },
+ {
+ "Future Ads": {
+ "https://www.futureads.com/": ["futureads.com", "resultlinks.com"]
+ }
+ },
+ {
+ "Fyber": {
+ "https://www.fyber.com/": ["fyber.com"]
+ }
+ },
+ {
+ "Game Advertising Online": {
+ "http://www.game-advertising-online.com/": [
+ "game-advertising-online.com"
+ ]
+ }
+ },
+ {
+ "Games2win": {
+ "http://www.games2win.com/": ["games2win.com", "inviziads.com"]
+ }
+ },
+ {
+ "Gamned": {
+ "http://www.gamned.com/": ["gamned.com"]
+ }
+ },
+ {
+ "Gannett": {
+ "http://www.gannett.com/": ["gannett.com", "pointroll.com"]
+ }
+ },
+ {
+ "GB-World": {
+ "http://www.gb-world.net/": ["gb-world.net"]
+ }
+ },
+ {
+ "Gemius": {
+ "http://www.gemius.com/": ["gemius.com", "gemius.pl"]
+ }
+ },
+ {
+ "Genesis Media": {
+ "http://www.genesismedia.com/": [
+ "genesismedia.com",
+ "genesismediaus.com"
+ ]
+ }
+ },
+ {
+ "GENIEE": {
+ "https://geniee.co.jp/": ["geniee.co.jp", "gssprt.jp"]
+ }
+ },
+ {
+ "GENIE GROUP": {
+ "http://www.geniegroupltd.co.uk/": ["geniegroupltd.co.uk"]
+ }
+ },
+ {
+ "GeoAds": {
+ "http://www.geoads.com/": ["geoads.com"]
+ }
+ },
+ {
+ "GetGlue": {
+ "http://getglue.com/": ["getglue.com", "smrtlnks.com"]
+ }
+ },
+ {
+ "GetIntent": {
+ "http://getintent.com/": ["adhigh.net", "getintent.com"]
+ }
+ },
+ {
+ "GISMAds": {
+ "http://www.gismads.jp/": ["gismads.jp"]
+ }
+ },
+ {
+ "Glam Media": {
+ "http://www.glammedia.com/": ["glam.com", "glammedia.com"]
+ }
+ },
+ {
+ "Gleam": {
+ "https://gleam.io/": ["fraudjs.io", "gleam.io"]
+ }
+ },
+ {
+ "Globe7": {
+ "http://www.globe7.com/": ["globe7.com"]
+ }
+ },
+ {
+ "GoDataFeed": {
+ "http://godatafeed.com/": ["godatafeed.com"]
+ }
+ },
+ {
+ "Goldbach": {
+ "http://www.goldbachgroup.com/": ["goldbach.com", "goldbachgroup.com"]
+ }
+ },
+ {
+ "GoldSpot Media": {
+ "http://www.goldspotmedia.com/": ["goldspotmedia.com"]
+ }
+ },
+ {
+ "Google": {
+ "http://www.google.com/": [
+ "2mdn.net",
+ "admeld.com",
+ "admob.com",
+ "adservice.google.ca",
+ "adservice.google.com",
+ "adwords.google.com",
+ "cc-dt.com",
+ "destinationurl.com",
+ "doubleclick.net",
+ "googleadservices.com",
+ "googlesyndication.com",
+ "googletagservices.com",
+ "invitemedia.com",
+ "smtad.net",
+ "teracent.com",
+ "teracent.net",
+ "ytsa.net"
+ ]
+ }
+ },
+ {
+ "Grapeshot": {
+ "http://www.grapeshot.co.uk/": ["grapeshot.co.uk"]
+ }
+ },
+ {
+ "Graphnium": {
+ "https://www.graphinium.com/": ["crm4d.com"]
+ }
+ },
+ {
+ "Grocery Shopping Network": {
+ "http://www.groceryshopping.net/": ["groceryshopping.net"]
+ }
+ },
+ {
+ "GroovinAds": {
+ "http://www.groovinads.com/": ["groovinads.com"]
+ }
+ },
+ {
+ "Gruner + Jahr": {
+ "http://www.guj.de/": ["guj.de", "ligatus.com"]
+ }
+ },
+ {
+ "GumGum": {
+ "http://gumgum.com/": ["gumgum.com"]
+ }
+ },
+ {
+ "Gunggo": {
+ "http://www.gunggo.com/": ["gunggo.com"]
+ }
+ },
+ {
+ "Hands Mobile": {
+ "http://www.hands.com.br/": ["hands.com.br"]
+ }
+ },
+ {
+ "Harrenmedia": {
+ "http://www.harrenmedia.com/": [
+ "harrenmedia.com",
+ "harrenmedianetwork.com"
+ ]
+ }
+ },
+ {
+ "HealthPricer": {
+ "http://www.healthpricer.com/": ["adacado.com", "healthpricer.com"]
+ }
+ },
+ {
+ "Hearst": {
+ "http://www.hearst.com/": [
+ "hearst.com",
+ "ic-live.com",
+ "iclive.com",
+ "icrossing.com",
+ "sptag.com",
+ "sptag1.com",
+ "sptag2.com",
+ "sptag3.com"
+ ]
+ }
+ },
+ {
+ "HilltopAds": {
+ "https://hilltopads.com/": [
+ "hilltopads.com",
+ "hilltopads.net",
+ "shoporielder.pro"
+ ]
+ }
+ },
+ {
+ "Hi-media": {
+ "http://www.hi-media.com/": ["comclick.com", "hi-media.com"]
+ }
+ },
+ {
+ "Horyzon Media": {
+ "http://www.horyzon-media.com/": ["horyzon-media.com"]
+ }
+ },
+ {
+ "HotMart": {
+ "https://www.hotmart.com/en/": ["hotmart.com"]
+ }
+ },
+ {
+ "HOTWords": {
+ "http://www.hotwords.com/": ["hotwords.com", "hotwords.es"]
+ }
+ },
+ {
+ "HP": {
+ "http://www.hp.com/": ["hp.com", "optimost.com"]
+ }
+ },
+ {
+ "Httpool": {
+ "http://www.httpool.com/": ["httpool.com"]
+ }
+ },
+ {
+ "HUNT Mobile Ads": {
+ "http://www.huntmads.com/": ["huntmads.com"]
+ }
+ },
+ {
+ "Hurra.com": {
+ "http://www.hurra.com/": ["hurra.com"]
+ }
+ },
+ {
+ "IAB": {
+ "https://iabtechlab.com/": ["digitru.st"]
+ }
+ },
+ {
+ "IAC": {
+ "http://www.iac.com/": ["iac.com", "iacadvertising.com"]
+ }
+ },
+ {
+ "iBehavior": {
+ "http://www.i-behavior.com/": ["i-behavior.com", "ib-ibi.com"]
+ }
+ },
+ {
+ "IBM": {
+ "http://www.ibm.com/": ["unica.com"]
+ }
+ },
+ {
+ "ID5": {
+ "http://id5.io/": ["id5-sync.com"]
+ }
+ },
+ {
+ "IDG": {
+ "http://www.idg.com/": ["idg.com", "idgtechnetwork.com"]
+ }
+ },
+ {
+ "iEntry": {
+ "http://www.ientry.com/": ["600z.com", "ientry.com"]
+ }
+ },
+ {
+ "IgnitAd": {
+ "http://www.ignitad.com/": ["ignitad.com"]
+ }
+ },
+ {
+ "IgnitionOne": {
+ "http://www.ignitionone.com/": [
+ "ignitionone.com",
+ "ignitionone.net",
+ "searchignite.com"
+ ]
+ }
+ },
+ {
+ "Improve Digital": {
+ "www.improvedigital.com/": ["360yield.com", "improvedigital.com"]
+ }
+ },
+ {
+ "Inadco": {
+ "http://www.inadco.com/": [
+ "anadcoads.com",
+ "inadco.com",
+ "inadcoads.com"
+ ]
+ }
+ },
+ {
+ "IndexExchange": {
+ "https://www.indexexchange.com": ["indexexchange.com"]
+ }
+ },
+ {
+ "Infectious Media": {
+ "http://www.infectiousmedia.com/": [
+ "impressiondesk.com",
+ "infectiousmedia.com"
+ ]
+ }
+ },
+ {
+ "Inflection Point Media": {
+ "http://www.inflectionpointmedia.com/": ["inflectionpointmedia.com"]
+ }
+ },
+ {
+ "Infogroup": {
+ "http://www.infogroup.com/": ["infogroup.com"]
+ }
+ },
+ {
+ "Infolinks": {
+ "http://www.infolinks.com/": ["infolinks.com"]
+ }
+ },
+ {
+ "Infra-Ad": {
+ "http://www.infra-ad.com/": ["infra-ad.com"]
+ }
+ },
+ {
+ "InMobi": {
+ "http://www.inmobi.com/": [
+ "aerserv.com",
+ "inmobi.com",
+ "sproutinc.com"
+ ]
+ }
+ },
+ {
+ "inneractive": {
+ "http://inner-active.com/": ["inner-active.com"]
+ }
+ },
+ {
+ "Innity": {
+ "http://innity.com/": ["innity.com"]
+ }
+ },
+ {
+ "InsightExpress": {
+ "http://www.insightexpress.com/": [
+ "insightexpress.com",
+ "insightexpressai.com"
+ ]
+ }
+ },
+ {
+ "InSkin Media": {
+ "http://inskinmedia.com/": ["inskinmedia.com"]
+ }
+ },
+ {
+ "Instinctive": {
+ "https://instinctive.io/": ["instinctive.io", "instinctiveads.com"]
+ }
+ },
+ {
+ "Integral Ad Science": {
+ "https://integralads.com/": [
+ "adsafemedia.com",
+ "adsafeprotected.com",
+ "iasds01.com",
+ "integralads.com"
+ ]
+ }
+ },
+ {
+ "Intent Media": {
+ "http://www.intentmedia.com/": ["intentmedia.com", "intentmedia.net"]
+ }
+ },
+ {
+ "Intergi": {
+ "http://intergi.com/": ["intergi.com"]
+ }
+ },
+ {
+ "Intermarkets": {
+ "http://www.intermarkets.net/": ["intermarkets.net"]
+ }
+ },
+ {
+ "Intermundo Media": {
+ "http://intermundomedia.com/": ["intermundomedia.com"]
+ }
+ },
+ {
+ "Internet Brands": {
+ "http://www.internetbrands.com/": ["ibpxl.com", "internetbrands.com"]
+ }
+ },
+ {
+ "Interpolls": {
+ "http://www.interpolls.com/": ["interpolls.com"]
+ }
+ },
+ {
+ "Inuvo": {
+ "http://inuvo.com/": ["inuvo.com"]
+ }
+ },
+ {
+ "InvestingChannel": {
+ "http://investingchannel.com/": ["investingchannel.com"]
+ }
+ },
+ {
+ "IponWeb": {
+ "https://www.iponweb.com/": ["iponweb.com", "iponweb.net"]
+ }
+ },
+ {
+ "iPROM": {
+ "http://www.iprom.si/": [
+ "centraliprom.com",
+ "iprom.net",
+ "iprom.si",
+ "mediaiprom.com"
+ ]
+ }
+ },
+ {
+ "iPromote": {
+ "http://www.ipromote.com/": ["ipromote.com"]
+ }
+ },
+ {
+ "iProspect": {
+ "http://www.iprospect.com/": ["clickmanage.com", "iprospect.com"]
+ }
+ },
+ {
+ "ISI Technologies": {
+ "http://digbro.com/": ["adversalservers.com", "digbro.com"]
+ }
+ },
+ {
+ "ismatlab.com": {
+ "http://ismatlab.com": ["ismatlab.com"]
+ }
+ },
+ {
+ "I.UA": {
+ "http://www.i.ua/": ["i.ua"]
+ }
+ },
+ {
+ "Jaroop": {
+ "http://www.jaroop.com/": ["jaroop.com"]
+ }
+ },
+ {
+ "JasperLabs": {
+ "http://www.jasperlabs.com/": ["jasperlabs.com"]
+ }
+ },
+ {
+ "Jemm": {
+ "http://jemmgroup.com/": ["jemmgroup.com"]
+ }
+ },
+ {
+ "Jink": {
+ "http://www.jink.de/": ["jink.de", "jinkads.com"]
+ }
+ },
+ {
+ "Jirbo": {
+ "http://jirbo.com/": ["adcolony.com", "jirbo.com"]
+ }
+ },
+ {
+ "Jivox": {
+ "http://www.jivox.com/": ["jivox.com"]
+ }
+ },
+ {
+ "JobThread": {
+ "http://www.jobthread.com/": ["jobthread.com"]
+ }
+ },
+ {
+ "JuicyAds": {
+ "http://www.juicyads.com/": ["juicyads.com"]
+ }
+ },
+ {
+ "Jumptap": {
+ "http://www.jumptap.com/": ["jumptap.com"]
+ }
+ },
+ {
+ "justuno": {
+ "https://www.justuno.com/": ["justuno.com"]
+ }
+ },
+ {
+ "Kargo": {
+ "https://kargo.com/": ["kargo.com"]
+ }
+ },
+ {
+ "Kenshoo": {
+ "http://www.kenshoo.com/": ["kenshoo.com", "xg4ken.com"]
+ }
+ },
+ {
+ "Keyade": {
+ "http://www.keyade.com/": ["keyade.com"]
+ }
+ },
+ {
+ "Keywee": {
+ "https://keywee.co": ["keywee.co"]
+ }
+ },
+ {
+ "KissMyAds": {
+ "http://kissmyads.com/": ["kissmyads.com"]
+ }
+ },
+ {
+ "Kitara Media": {
+ "http://www.kitaramedia.com/": ["103092804.com", "kitaramedia.com"]
+ }
+ },
+ {
+ "KIT digital": {
+ "http://kitd.com/": ["keewurd.com", "kitd.com", "peerset.com"]
+ }
+ },
+ {
+ "Kokteyl": {
+ "http://www.kokteyl.com/": ["admost.com", "kokteyl.com"]
+ }
+ },
+ {
+ "Komli": {
+ "http://www.komli.com/": ["komli.com"]
+ }
+ },
+ {
+ "Kontera": {
+ "http://www.kontera.com/": ["kontera.com"]
+ }
+ },
+ {
+ "Korrelate": {
+ "http://korrelate.com/": [
+ "adsummos.com",
+ "adsummos.net",
+ "korrelate.com"
+ ]
+ }
+ },
+ {
+ "Krux": {
+ "http://www.krux.com/": ["krux.com", "kruxdigital.com", "krxd.net"]
+ }
+ },
+ {
+ "Lakana": {
+ "http://www.lakana.com/": ["ibsys.com", "lakana.com"]
+ }
+ },
+ {
+ "Layer-Ad.org": {
+ "http://layer-ad.org/": ["layer-ad.org"]
+ }
+ },
+ {
+ "Layer Ads": {
+ "http://layer-ads.net/": ["layer-ads.net"]
+ }
+ },
+ {
+ "LeadBolt": {
+ "http://www.leadbolt.com/": ["leadbolt.com"]
+ }
+ },
+ {
+ "LeadFormix": {
+ "http://www.leadformix.com/": ["leadforce1.com", "leadformix.com"]
+ }
+ },
+ {
+ "LeanPlum": {
+ "https://www.leanplum.com/": ["leanplum.com"]
+ }
+ },
+ {
+ "Legolas Media": {
+ "http://www.legolas-media.com/": ["legolas-media.com"]
+ }
+ },
+ {
+ "Levexis": {
+ "http://www.levexis.com/": ["levexis.com"]
+ }
+ },
+ {
+ "Lexos Media": {
+ "http://www.lexosmedia.com/": ["adbull.com", "lexosmedia.com"]
+ }
+ },
+ {
+ "LifeStreet": {
+ "http://lifestreetmedia.com/": [
+ "lfstmedia.com",
+ "lifestreetmedia.com"
+ ]
+ }
+ },
+ {
+ "LinkConnector": {
+ "http://www.linkconnector.com/": ["linkconnector.com"]
+ }
+ },
+ {
+ "LinkShare": {
+ "http://www.linkshare.com/": ["linkshare.com", "linksynergy.com"]
+ }
+ },
+ {
+ "Linkz": {
+ "http://www.linkz.net/": ["linkz.net"]
+ }
+ },
+ {
+ "Listrak": {
+ "http://www.listrak.com/": ["listrak.com", "listrakbi.com"]
+ }
+ },
+ {
+ "LiveIntent": {
+ "http://www.liveintent.com/": ["liadm.com", "liveintent.com"]
+ }
+ },
+ {
+ "LiveInternet": {
+ "http://www.liveinternet.ru": ["liveinternet.ru", "yadro.ru"]
+ }
+ },
+ {
+ "LiveRamp": {
+ "https://liveramp.com/": ["liveramp.com", "tvpixel.com"]
+ }
+ },
+ {
+ "LKQD": {
+ "http://lkqd.com": ["lkqd.com", "lkqd.net"]
+ }
+ },
+ {
+ "Local Yokel Media": {
+ "http://www.localyokelmedia.com/": ["localyokelmedia.com"]
+ }
+ },
+ {
+ "Localytics": {
+ "https://www.localytics.com/": ["localytics.com"]
+ }
+ },
+ {
+ "LockerDome": {
+ "https://lockerdome.com/": ["lockerdome.com"]
+ }
+ },
+ {
+ "Longboard Media": {
+ "http://longboardmedia.com/": ["longboardmedia.com"]
+ }
+ },
+ {
+ "Loomia": {
+ "http://www.loomia.com/": ["loomia.com"]
+ }
+ },
+ {
+ "LoopFuse": {
+ "https://www.loopfuse.net/": ["lfov.net", "loopfuse.net"]
+ }
+ },
+ {
+ "LoopMe": {
+ "https://loopme.com/": ["loopme.com"]
+ }
+ },
+ {
+ "LotLinx": {
+ "https://www.lotlinx.com": ["lotlinx.com"]
+ }
+ },
+ {
+ "Lower My Bills": {
+ "http://lowermybills.com": ["lowermybills.com"]
+ }
+ },
+ {
+ "lptracker": {
+ "https://lptracker.io/": ["lptracker.io"]
+ }
+ },
+ {
+ "LucidMedia": {
+ "http://www.lucidmedia.com/": ["lucidmedia.com"]
+ }
+ },
+ {
+ "m6d": {
+ "http://m6d.com/": ["m6d.com", "media6degrees.com"]
+ }
+ },
+ {
+ "Madhouse": {
+ "http://www.madhouse.cn/": ["madhouse.cn"]
+ }
+ },
+ {
+ "Madison Logic": {
+ "http://www.madisonlogic.com/": ["dinclinx.com", "madisonlogic.com"]
+ }
+ },
+ {
+ "madvertise": {
+ "http://madvertise.com/": ["madvertise.com"]
+ }
+ },
+ {
+ "Magnetic": {
+ "http://www.magnetic.com/": [
+ "domdex.com",
+ "domdex.net",
+ "magnetic.com",
+ "qjex.net"
+ ]
+ }
+ },
+ {
+ "Magnify360": {
+ "http://www.magnify360.com/": ["dialogmgr.com", "magnify360.com"]
+ }
+ },
+ {
+ "MailChimp": {
+ "http://mailchimp.com/": [
+ "campaign-archive1.com",
+ "list-manage.com",
+ "mailchimp.com"
+ ]
+ }
+ },
+ {
+ "Manifest": {
+ "http://www.manifest.ru/": ["bannerbank.ru", "manifest.ru"]
+ }
+ },
+ {
+ "Marchex": {
+ "http://www.marchex.com/": ["industrybrains.com", "marchex.com"]
+ }
+ },
+ {
+ "Marimedia": {
+ "http://www.marimedia.net/": ["marimedia.net"]
+ }
+ },
+ {
+ "MarketGid": {
+ "http://www.marketgid.com/": ["dt00.net", "dt07.net", "marketgid.com"]
+ }
+ },
+ {
+ "Marketo": {
+ "http://www.marketo.com/": ["marketo.com", "marketo.net"]
+ }
+ },
+ {
+ "Martini Media": {
+ "http://martinimedianetwork.com/": [
+ "martiniadnetwork.com",
+ "martinimedianetwork.com"
+ ]
+ }
+ },
+ {
+ "mashero": {
+ "http://www.mashero.com/": ["mashero.com"]
+ }
+ },
+ {
+ "Match.com": {
+ "http://www.match.com/": [
+ "chemistry.com",
+ "match.com",
+ "meetic-partners.com"
+ ]
+ }
+ },
+ {
+ "Matomy": {
+ "http://www.matomy.com/": [
+ "adnetinteractive.com",
+ "adsmarket.com",
+ "matomy.com",
+ "matomymarket.com",
+ "matomymedia.com",
+ "mediawhiz.com",
+ "optimatic.com",
+ "xtendmedia.com"
+ ]
+ }
+ },
+ {
+ "MaxBounty": {
+ "http://www.maxbounty.com/": ["maxbounty.com", "mb01.com"]
+ }
+ },
+ {
+ "MaxPoint": {
+ "http://maxpointinteractive.com/": [
+ "maxpointinteractive.com",
+ "maxusglobal.com",
+ "mxptint.net"
+ ]
+ }
+ },
+ {
+ "MdotM": {
+ "http://mdotm.com/": ["mdotm.com"]
+ }
+ },
+ {
+ "MediaBrix": {
+ "http://www.mediabrix.com/": ["mediabrix.com"]
+ }
+ },
+ {
+ "MediaCom": {
+ "http://www.mediacom.com/": ["mediacom.com"]
+ }
+ },
+ {
+ "mediaFORGE": {
+ "http://www.mediaforge.com/": ["mediaforge.com"]
+ }
+ },
+ {
+ "Medialets": {
+ "http://www.medialets.com/": ["medialets.com"]
+ }
+ },
+ {
+ "MediaMath": {
+ "http://www.mediamath.com/": [
+ "adroitinteractive.com",
+ "designbloxlive.com",
+ "mathtag.com",
+ "mediamath.com"
+ ]
+ }
+ },
+ {
+ "media.net": {
+ "http://www.media.net/": ["media.net"]
+ }
+ },
+ {
+ "Mediaocean": {
+ "http://www.mediaocean.com/": ["adbuyer.com", "mediaocean.com"]
+ }
+ },
+ {
+ "MediaShakers": {
+ "http://www.mediashakers.com/": [
+ "media-servers.net",
+ "mediashakers.com"
+ ]
+ }
+ },
+ {
+ "MediaTrust": {
+ "http://www.mediatrust.com/": ["mediatrust.com"]
+ }
+ },
+ {
+ "Medicx Media Solutions": {
+ "http://www.medicxmedia.com/": ["medicxmedia.com"]
+ }
+ },
+ {
+ "MegaIndex": {
+ "http://www.megaindex.ru/": ["megaindex.ru"]
+ }
+ },
+ {
+ "Mercent": {
+ "http://www.mercent.com/": ["mercent.com"]
+ }
+ },
+ {
+ "MerchantAdvantage": {
+ "http://www.merchantadvantage.com/": ["merchantadvantage.com"]
+ }
+ },
+ {
+ "Merchenta": {
+ "http://www.merchenta.com/": ["merchenta.com"]
+ }
+ },
+ {
+ "Merkle": {
+ "https://www.merkleinc.com/": ["rimmkaufman.com", "rkdms.com"]
+ }
+ },
+ {
+ "Meta Network": {
+ "http://www.metanetwork.com/": ["metanetwork.com"]
+ }
+ },
+ {
+ "Meteor": {
+ "http://www.meteorsolutions.com/": ["meteorsolutions.com"]
+ }
+ },
+ {
+ "MetrixLab": {
+ "https://www.metrixlab.com": [
+ "adoftheyear.com",
+ "crm-metrix.com",
+ "customerconversio.com",
+ "metrixlab.com",
+ "opinionbar.com"
+ ]
+ }
+ },
+ {
+ "MicroAd": {
+ "http://www.microad.jp/": ["microad.jp"]
+ }
+ },
+ {
+ "Microsoft": {
+ "http://www.microsoft.com/": [
+ "adbureau.net",
+ "adecn.com",
+ "aquantive.com",
+ "msads.net",
+ "netconversions.com",
+ "roiservice.com"
+ ]
+ }
+ },
+ {
+ "Millennial Media": {
+ "http://www.millennialmedia.com/": [
+ "decktrade.com",
+ "millennialmedia.com",
+ "mydas.mobi"
+ ]
+ }
+ },
+ {
+ "Mindset Media": {
+ "http://www.mindset-media.com/": ["mindset-media.com", "mmismm.com"]
+ }
+ },
+ {
+ "Mirando": {
+ "http://www.mirando.de/": ["mirando.de"]
+ }
+ },
+ {
+ "Mixpo": {
+ "http://www.mixpo.com/": ["mixpo.com"]
+ }
+ },
+ {
+ "Moat": {
+ "http://www.moat.com/": ["moat.com", "moatads.com"]
+ }
+ },
+ {
+ "MobFox": {
+ "http://www.mobfox.com/": ["mobfox.com"]
+ }
+ },
+ {
+ "Mobials": {
+ "http://mobials.com": ["mobials.com"]
+ }
+ },
+ {
+ "MobileAdTrading": {
+ "https://mobileadtrading.com/": ["mobileadtrading.com"]
+ }
+ },
+ {
+ "Mobile Meteor": {
+ "http://mobilemeteor.com/": ["mobilemeteor.com", "showmeinn.com"]
+ }
+ },
+ {
+ "Mobile Storm": {
+ "http://mobilestorm.com/": ["mobilestorm.com"]
+ }
+ },
+ {
+ "MobVision": {
+ "http://www.mobvision.com/": ["admoda.com", "mobvision.com"]
+ }
+ },
+ {
+ "Mocean Mobile": {
+ "http://www.moceanmobile.com/": ["moceanmobile.com"]
+ }
+ },
+ {
+ "Mochila": {
+ "http://www.mochila.com/": ["mochila.com"]
+ }
+ },
+ {
+ "Mojiva": {
+ "http://www.mojiva.com/": ["mojiva.com"]
+ }
+ },
+ {
+ "Monetate": {
+ "http://monetate.com/": ["monetate.com", "monetate.net"]
+ }
+ },
+ {
+ "MONETIZEdigital": {
+ "https://www.cpalead.com/": ["cpalead.com"]
+ }
+ },
+ {
+ "Monetize More": {
+ "http://monetizemore.com/": ["monetizemore.com"]
+ }
+ },
+ {
+ "Monoloop": {
+ "http://www.monoloop.com/": ["monoloop.com"]
+ }
+ },
+ {
+ "Monster": {
+ "http://www.monster.com/": ["monster.com"]
+ }
+ },
+ {
+ "Moolah Media": {
+ "http://www.moolahmedia.com/": ["moolah-media.com", "moolahmedia.com"]
+ }
+ },
+ {
+ "MoPub": {
+ "http://www.mopub.com/": ["mopub.com"]
+ }
+ },
+ {
+ "MovieLush.com": {
+ "https://www.movielush.com/": ["affbuzzads.com", "movielush.com"]
+ }
+ },
+ {
+ "Multiple Stream Media": {
+ "http://www.multiplestreammktg.com/": [
+ "adclickmedia.com",
+ "multiplestreammktg.com"
+ ]
+ }
+ },
+ {
+ "MUNDO Media": {
+ "http://www.mundomedia.com/": ["mundomedia.com", "silver-path.com"]
+ }
+ },
+ {
+ "MyCounter": {
+ "http://mycounter.com.ua/": ["mycounter.com.ua"]
+ }
+ },
+ {
+ "MyPressPlus": {
+ "http://www.mypressplus.com/": ["mypressplus.com", "ppjol.net"]
+ }
+ },
+ {
+ "myThings": {
+ "http://www.mythings.com/": ["mythings.com", "mythingsmedia.com"]
+ }
+ },
+ {
+ "MyWebGrocer": {
+ "http://www.mywebgrocer.com/": ["mywebgrocer.com"]
+ }
+ },
+ {
+ "Nanigans": {
+ "http://www.nanigans.com/": ["nanigans.com"]
+ }
+ },
+ {
+ "NativeAds": {
+ "https://nativeads.com/": ["nativeads.com"]
+ }
+ },
+ {
+ "Nativo": {
+ "http://www.nativo.net/": ["postrelease.com"]
+ }
+ },
+ {
+ "Navegg": {
+ "http://www.navegg.com/": ["navdmp.com", "navegg.com"]
+ }
+ },
+ {
+ "NetAffiliation": {
+ "http://www.netaffiliation.com/": ["netaffiliation.com"]
+ }
+ },
+ {
+ "NetBina": {
+ "http://www.netbina.com/": ["netbina.com"]
+ }
+ },
+ {
+ "NetElixir": {
+ "http://www.netelixir.com/": ["adelixir.com", "netelixir.com"]
+ }
+ },
+ {
+ "Netmining": {
+ "http://www.netmining.com/": ["netmining.com", "netmng.com"]
+ }
+ },
+ {
+ "Net-Results": {
+ "http://www.net-results.com/": [
+ "cdnma.com",
+ "net-results.com",
+ "nr7.us"
+ ]
+ }
+ },
+ {
+ "NetSeer": {
+ "http://www.netseer.com/": ["netseer.com"]
+ }
+ },
+ {
+ "NetShelter": {
+ "http://netshelter.com/": ["netshelter.com", "netshelter.net"]
+ }
+ },
+ {
+ "Neustar": {
+ "http://www.neustar.biz/": ["adadvisor.net", "neustar.biz"]
+ }
+ },
+ {
+ "newtention": {
+ "http://newtention.de/": [
+ "newtention.de",
+ "newtention.net",
+ "newtentionassets.net"
+ ]
+ }
+ },
+ {
+ "Nexage": {
+ "http://nexage.com/": ["nexage.com"]
+ }
+ },
+ {
+ "Nextag": {
+ "http://www.nextag.com/": ["nextag.com"]
+ }
+ },
+ {
+ "NextPerformance": {
+ "http://www.nextperformance.com/": [
+ "nextperformance.com",
+ "nxtck.com"
+ ]
+ }
+ },
+ {
+ "Nielsen": {
+ "http://www.nielsen.com/": ["imrworldwide.com", "imrworldwide.net"]
+ }
+ },
+ {
+ "Ninua": {
+ "http://www.ninua.com/": ["networkedblogs.com", "ninua.com"]
+ }
+ },
+ {
+ "Nokta": {
+ "http://www.noktamedya.com/": ["noktamedya.com", "virgul.com"]
+ }
+ },
+ {
+ "NowSpots": {
+ "http://nowspots.com/": ["nowspots.com"]
+ }
+ },
+ {
+ "nrelate": {
+ "http://nrelate.com/": ["nrelate.com"]
+ }
+ },
+ {
+ "Nuffnang": {
+ "http://www.nuffnang.com.my/": ["nuffnang.com", "nuffnang.com.my"]
+ }
+ },
+ {
+ "nugg.ad": {
+ "http://www.nugg.ad/": ["nugg.ad", "nuggad.net"]
+ }
+ },
+ {
+ "Ohana Media": {
+ "http://www.ohana-media.com/": [
+ "adohana.com",
+ "ohana-media.com",
+ "ohanaqb.com"
+ ]
+ }
+ },
+ {
+ "Omnicom Group": {
+ "http://www.omnicomgroup.com/": [
+ "accuenmedia.com",
+ "omnicomgroup.com",
+ "p-td.com"
+ ]
+ }
+ },
+ {
+ "onAd": {
+ "http://www.onad.eu/": ["onad.eu"]
+ }
+ },
+ {
+ "Onclusive": {
+ "https://onclusive.com/": ["airpr.com"]
+ }
+ },
+ {
+ "OneAd": {
+ "https://www.onead.com.tw/": [
+ "guoshipartners.com",
+ "onevision.com.tw"
+ ]
+ }
+ },
+ {
+ "One iota": {
+ "http://www.itsoneiota.com/": ["itsoneiota.com", "oneiota.co.uk"]
+ }
+ },
+ {
+ "Oneupweb": {
+ "http://www.oneupweb.com/": ["oneupweb.com", "sodoit.com"]
+ }
+ },
+ {
+ "OnlineMetrix": {
+ "http://h.online-metrix.net": ["online-metrix.net"]
+ }
+ },
+ {
+ "Open New Media": {
+ "http://www.onm.de/": ["onm.de"]
+ }
+ },
+ {
+ "OpenX": {
+ "http://openx.com/": [
+ "liftdna.com",
+ "openx.com",
+ "openx.net",
+ "openx.org",
+ "openxenterprise.com",
+ "servedbyopenx.com"
+ ]
+ }
+ },
+ {
+ "Opera": {
+ "http://www.opera.com/": [
+ "mobiletheory.com",
+ "opera.com",
+ "operamediaworks.com",
+ "operasoftware.com"
+ ]
+ }
+ },
+ {
+ "OPT": {
+ "http://www.opt.ne.jp/": ["advg.jp", "opt.ne.jp", "p-advg.com"]
+ }
+ },
+ {
+ "Optify": {
+ "http://www.optify.net/": ["optify.net"]
+ }
+ },
+ {
+ "Optimal": {
+ "http://optim.al/": [
+ "cpmadvisors.com",
+ "cpmatic.com",
+ "nprove.com",
+ "optim.al",
+ "orbengine.com",
+ "xa.net"
+ ]
+ }
+ },
+ {
+ "OptimumResponse": {
+ "http://www.optimumresponse.com/": ["optimumresponse.com"]
+ }
+ },
+ {
+ "OptinMonster": {
+ "https://optinmonster.com/": ["optinmonster.com", "optnmstr.com"]
+ }
+ },
+ {
+ "OptMD": {
+ "http://optmd.com/": ["optmd.com"]
+ }
+ },
+ {
+ "Oracle": {
+ "http://www.oracle.com/": ["estara.com"]
+ }
+ },
+ {
+ "OrangeSoda": {
+ "http://www.orangesoda.com/": ["orangesoda.com", "otracking.com"]
+ }
+ },
+ {
+ "Outbrain": {
+ "http://www.outbrain.com/": [
+ "outbrain.com",
+ "sphere.com",
+ "visualrevenue.com"
+ ]
+ }
+ },
+ {
+ "Out There Media": {
+ "http://www.out-there-media.com/": ["out-there-media.com"]
+ }
+ },
+ {
+ "Oversee.net": {
+ "http://www.oversee.net/": ["dsnextgen.com", "oversee.net"]
+ }
+ },
+ {
+ "OwnerIQ": {
+ "http://www.owneriq.com/": ["owneriq.com", "owneriq.net"]
+ }
+ },
+ {
+ "OxaMedia": {
+ "http://www.oxamedia.com/": [
+ "adconnexa.com",
+ "adsbwm.com",
+ "oxamedia.com"
+ ]
+ }
+ },
+ {
+ "PageFair": {
+ "https://pagefair.com/": ["pagefair.com", "pagefair.net"]
+ }
+ },
+ {
+ "Paid-To-Promote.net": {
+ "http://www.paid-to-promote.net/": ["paid-to-promote.net"]
+ }
+ },
+ {
+ "Pardot": {
+ "http://www.pardot.com/": ["pardot.com"]
+ }
+ },
+ {
+ "PayHit": {
+ "http://www.payhit.com/": ["payhit.com"]
+ }
+ },
+ {
+ "Paypopup.com": {
+ "http://www.paypopup.com/": ["lzjl.com", "paypopup.com"]
+ }
+ },
+ {
+ "PebblePost": {
+ "https://www.pebblepost.com/": ["pbbl.co"]
+ }
+ },
+ {
+ "Peer39": {
+ "http://www.peer39.com/": ["peer39.com", "peer39.net"]
+ }
+ },
+ {
+ "PeerFly": {
+ "http://peerfly.com/": ["peerfly.com"]
+ }
+ },
+ {
+ "Performancing": {
+ "http://performancing.com/": ["performancing.com"]
+ }
+ },
+ {
+ "PerimeterX": {
+ "https://www.perimeterx.com": ["perimeterx.net"]
+ }
+ },
+ {
+ "Pheedo": {
+ "http://site.pheedo.com/": ["pheedo.com"]
+ }
+ },
+ {
+ "Pictela": {
+ "http://www.pictela.com/": ["pictela.com", "pictela.net"]
+ }
+ },
+ {
+ "PinPoll": {
+ "https://pinpoll.com/": ["pinpoll.com"]
+ }
+ },
+ {
+ "Pixel.sg": {
+ "http://www.pixel.sg/": ["pixel.sg"]
+ }
+ },
+ {
+ "Piximedia": {
+ "http://www.piximedia.com/": ["piximedia.com"]
+ }
+ },
+ {
+ "Pixlee": {
+ "https://www.pixlee.com/": ["pixlee.com"]
+ }
+ },
+ {
+ "PLATFORM ONE": {
+ "http://www.platform-one.co.jp/": ["platform-one.co.jp"]
+ }
+ },
+ {
+ "plista": {
+ "http://www.plista.com/": ["plista.com"]
+ }
+ },
+ {
+ "PocketCents": {
+ "http://pocketcents.com/": ["pocketcents.com"]
+ }
+ },
+ {
+ "Polar Mobile": {
+ "http://polarmobile.com": ["mediavoice.com", "polarmobile.com"]
+ }
+ },
+ {
+ "Politads": {
+ "http://politads.com/": ["politads.com"]
+ }
+ },
+ {
+ "Polymorph": {
+ "http://getpolymorph.com/": ["adsnative.com", "getpolymorph.com"]
+ }
+ },
+ {
+ "Pontiflex": {
+ "http://www.pontiflex.com/": ["pontiflex.com"]
+ }
+ },
+ {
+ "PopAds": {
+ "https://www.popads.net/": ["popads.net", "popadscdn.net"]
+ }
+ },
+ {
+ "PopRule": {
+ "http://poprule.com/": ["gocampaignlive.com", "poprule.com"]
+ }
+ },
+ {
+ "Popunder.ru": {
+ "http://popunder.ru/": ["popunder.ru"]
+ }
+ },
+ {
+ "Po.st": {
+ "http://www.po.st/": ["po.st"]
+ }
+ },
+ {
+ "Powerlinks": {
+ "https://www.powerlinks.com/": ["powerlinks.com"]
+ }
+ },
+ {
+ "PPCProtect": {
+ "https://ppcprotect.com": ["ppcprotect.com"]
+ }
+ },
+ {
+ "PrecisionClick": {
+ "http://www.precisionclick.com/": ["precisionclick.com"]
+ }
+ },
+ {
+ "PredictAd": {
+ "http://www.predictad.com/": ["predictad.com"]
+ }
+ },
+ {
+ "Pressflex": {
+ "http://www.pressflex.com/": ["blogads.com", "pressflex.com"]
+ }
+ },
+ {
+ "Prime Visibility": {
+ "http://www.primevisibility.com/": [
+ "adcde.com",
+ "addlvr.com",
+ "adonnetwork.com",
+ "adonnetwork.net",
+ "adtrgt.com",
+ "bannertgt.com",
+ "cptgt.com",
+ "cpvfeed.com",
+ "cpvtgt.com",
+ "dashboardad.net",
+ "popcde.com",
+ "primevisibility.com",
+ "sdfje.com",
+ "urtbk.com"
+ ]
+ }
+ },
+ {
+ "Primis": {
+ "https://www.primis.tech": ["sekindo.com"]
+ }
+ },
+ {
+ "PrismApp": {
+ "https://www.prismapp.io/": ["prismapp.io"]
+ }
+ },
+ {
+ "Proclivity": {
+ "http://www.proclivitymedia.com/": [
+ "proclivitymedia.com",
+ "proclivitysystems.com",
+ "pswec.com"
+ ]
+ }
+ },
+ {
+ "Project Wonderful": {
+ "http://www.projectwonderful.com/": ["projectwonderful.com"]
+ }
+ },
+ {
+ "PrometheusIntelligenceTechnology": {
+ "https://prometheusintelligencetechnology.com/": [
+ "prometheusintelligencetechnology.com"
+ ]
+ }
+ },
+ {
+ "Propeller Ads": {
+ "http://propellerads.com/": ["propellerads.com"]
+ }
+ },
+ {
+ "Prosperent": {
+ "http://prosperent.com/": ["prosperent.com"]
+ }
+ },
+ {
+ "Protected Media": {
+ "http://www.protected.media/": ["ad-score.com", "protected.media"]
+ }
+ },
+ {
+ "Provers": {
+ "http://provers.pro": ["provers.pro"]
+ }
+ },
+ {
+ "Psonstrentie": {
+ "http://psonstrentie.info": ["psonstrentie.info"]
+ }
+ },
+ {
+ "Public-Idées": {
+ "http://www.publicidees.com/": ["publicidees.com"]
+ }
+ },
+ {
+ "Publishers Clearing House": {
+ "http://www.pch.com/": ["pch.com"]
+ }
+ },
+ {
+ "PubMatic": {
+ "http://www.pubmatic.com/": ["pubmatic.com", "revinet.com"]
+ }
+ },
+ {
+ "PulsePoint": {
+ "https://www.pulsepoint.com/": ["pulsepoint.com"]
+ }
+ },
+ {
+ "quadrantOne": {
+ "http://www.quadrantone.com/": ["quadrantone.com"]
+ }
+ },
+ {
+ "Quake Marketing": {
+ "http://quakemarketing.com/": ["quakemarketing.com"]
+ }
+ },
+ {
+ "Quantcast": {
+ "http://www.quantcast.com/": [
+ "quantcast.com",
+ "quantcount.com",
+ "quantserve.com"
+ ]
+ }
+ },
+ {
+ "QuantumAdvertising": {
+ "http://quantum-advertising.com": ["quantum-advertising.com"]
+ }
+ },
+ {
+ "QuinStreet": {
+ "http://quinstreet.com/": [
+ "qnsr.com",
+ "qsstats.com",
+ "quinstreet.com"
+ ]
+ }
+ },
+ {
+ "QUISMA": {
+ "https://quisma.com/": [
+ "iaded.com",
+ "quisma.com",
+ "quismatch.com",
+ "xaded.com",
+ "xmladed.com"
+ ]
+ }
+ },
+ {
+ "Radial": {
+ "https://www.radial.com": ["gsicommerce.com", "gsimedia.net"]
+ }
+ },
+ {
+ "Radiate Media": {
+ "http://www.radiatemedia.com/": ["matchbin.com", "radiatemedia.com"]
+ }
+ },
+ {
+ "RadiumOne": {
+ "http://www.radiumone.com/": ["gwallet.com", "radiumone.com"]
+ }
+ },
+ {
+ "Radius Marketing": {
+ "http://www.radiusmarketing.com/": ["radiusmarketing.com"]
+ }
+ },
+ {
+ "Rambler": {
+ "http://www.rambler.ru/": ["rambler.ru"]
+ }
+ },
+ {
+ "Rapleaf": {
+ "http://www.rapleaf.com/": ["rapleaf.com", "rlcdn.com"]
+ }
+ },
+ {
+ "ReachLocal": {
+ "http://www.reachlocal.com/": ["reachlocal.com", "rlcdn.net"]
+ }
+ },
+ {
+ "React2Media": {
+ "http://www.react2media.com/": ["react2media.com"]
+ }
+ },
+ {
+ "Redux Media": {
+ "http://reduxmedia.com/": ["reduxmedia.com"]
+ }
+ },
+ {
+ "Rekko": {
+ "http://rekko.com/": ["convertglobal.com", "rekko.com"]
+ }
+ },
+ {
+ "Reklamport": {
+ "http://www.reklamport.com/": ["reklamport.com"]
+ }
+ },
+ {
+ "Reklam Store": {
+ "http://reklamstore.com/": ["reklamstore.com"]
+ }
+ },
+ {
+ "Reklamz": {
+ "http://www.reklamz.com/": ["reklamz.com"]
+ }
+ },
+ {
+ "Relevad": {
+ "http://www.relevad.com/": ["relestar.com", "relevad.com"]
+ }
+ },
+ {
+ "Renegade Internet": {
+ "http://www.renegadeinternet.com/": [
+ "advertserve.com",
+ "renegadeinternet.com"
+ ]
+ }
+ },
+ {
+ "Reporo": {
+ "http://www.reporo.com/": ["buzzcity.com"]
+ }
+ },
+ {
+ "ResolutionMedia": {
+ "https://nonstoppartner.net/": ["nonstoppartner.net"]
+ }
+ },
+ {
+ "Resolution Media": {
+ "http://resolutionmedia.com/": ["resolutionmedia.com"]
+ }
+ },
+ {
+ "Resonate": {
+ "http://www.resonateinsights.com/": [
+ "reson8.com",
+ "resonateinsights.com",
+ "resonatenetworks.com"
+ ]
+ }
+ },
+ {
+ "Responsys": {
+ "http://www.responsys.com/": ["responsys.com"]
+ }
+ },
+ {
+ "ReTargeter": {
+ "http://www.retargeter.com/": ["retargeter.com"]
+ }
+ },
+ {
+ "Retirement Living": {
+ "www.retirement-living.com/": [
+ "blvdstatus.com",
+ "retirement-living.com"
+ ]
+ }
+ },
+ {
+ "RevContent": {
+ "http://revcontent.com/": ["revcontent.com"]
+ }
+ },
+ {
+ "RevenueMax": {
+ "http://revenuemax.de/": ["revenuemax.de"]
+ }
+ },
+ {
+ "Rhythm": {
+ "http://rhythmnewmedia.com/": [
+ "1rx.io",
+ "rhythmnewmedia.com",
+ "rhythmone.com",
+ "rhythmxchange.com",
+ "rnmd.net"
+ ]
+ }
+ },
+ {
+ "RichAudience": {
+ "https://richaudience.com/": ["richaudience.com"]
+ }
+ },
+ {
+ "RichRelevance": {
+ "http://www.richrelevance.com/": ["richrelevance.com"]
+ }
+ },
+ {
+ "RightAction": {
+ "http://rightaction.com/": ["rightaction.com"]
+ }
+ },
+ {
+ "RMBN": {
+ "http://rmbn.net/": ["rmbn.net", "rmbn.ru"]
+ }
+ },
+ {
+ "RMM": {
+ "http://www.rmmonline.com/": ["rmmonline.com"]
+ }
+ },
+ {
+ "Rocket Fuel": {
+ "http://rocketfuel.com/": [
+ "rfihub.com",
+ "rfihub.net",
+ "rocketfuel.com",
+ "ru4.com",
+ "xplusone.com"
+ ]
+ }
+ },
+ {
+ "Rovion": {
+ "http://www.rovion.com/": ["rovion.com"]
+ }
+ },
+ {
+ "rtk": {
+ "http://rtk.io/": ["rtk.io"]
+ }
+ },
+ {
+ "RubiconProject": {
+ "http://rubiconproject.com/": [
+ "adsbyisocket.com",
+ "isocket.com",
+ "rubiconproject.com"
+ ]
+ }
+ },
+ {
+ "RunAds": {
+ "http://www.runads.com/": ["runads.com", "rundsp.com"]
+ }
+ },
+ {
+ "RuTarget": {
+ "http://www.rutarget.ru/": ["rutarget.ru"]
+ }
+ },
+ {
+ "Sabavision": {
+ "http://www.sabavision.com": ["sabavision.com"]
+ }
+ },
+ {
+ "Sabre": {
+ "http://www.sabre.com/": [
+ "reztrack.com",
+ "sabre.com",
+ "sabrehospitality.com"
+ ]
+ }
+ },
+ {
+ "Salesforce.com": {
+ "http://www.salesforce.com/": ["salesforce.com"]
+ }
+ },
+ {
+ "Samurai Factory": {
+ "http://www.samurai-factory.jp/": ["samurai-factory.jp", "shinobi.jp"]
+ }
+ },
+ {
+ "SAP": {
+ "https://www.sap.com": ["seewhy.com"]
+ }
+ },
+ {
+ "Sapient": {
+ "http://www.sapient.com/": ["bridgetrack.com", "sapient.com"]
+ }
+ },
+ {
+ "SAS": {
+ "http://www.sas.com/": ["aimatch.com", "sas.com"]
+ }
+ },
+ {
+ "Scandinavian AdNetworks": {
+ "http://www.scandinavianadnetworks.com/": [
+ "scandinavianadnetworks.com"
+ ]
+ }
+ },
+ {
+ "Scribol": {
+ "http://scribol.com/": ["scribol.com"]
+ }
+ },
+ {
+ "SearchForce": {
+ "http://www.searchforce.com/": ["searchforce.com", "searchforce.net"]
+ }
+ },
+ {
+ "Seevast": {
+ "http://www.seevast.com/": [
+ "kanoodle.com",
+ "pulse360.com",
+ "seevast.com",
+ "syndigonetworks.com"
+ ]
+ }
+ },
+ {
+ "Selectable Media": {
+ "http://selectablemedia.com/": ["nabbr.com", "selectablemedia.com"]
+ }
+ },
+ {
+ "Semantiqo": {
+ "http://semantiqo.com/": ["semantiqo.com"]
+ }
+ },
+ {
+ "Semasio": {
+ "http://www.semasio.com/": ["semasio.com", "semasio.net"]
+ }
+ },
+ {
+ "SevenAds": {
+ "http://www.sevenads.net/": ["sevenads.net"]
+ }
+ },
+ {
+ "SexInYourCity": {
+ "http://www.sexinyourcity.com/": ["sexinyourcity.com"]
+ }
+ },
+ {
+ "ShaftTraffic": {
+ "https://shafttraffic.com": ["libertystmedia.com"]
+ }
+ },
+ {
+ "ShareASale": {
+ "http://www.shareasale.com/": ["shareasale.com"]
+ }
+ },
+ {
+ "Sharethrough": {
+ "http://sharethrough.com/": ["sharethrough.com"]
+ }
+ },
+ {
+ "Shopzilla": {
+ "http://www.shopzilla.com/": ["shopzilla.com"]
+ }
+ },
+ {
+ "Shortest": {
+ "http://shorte.st/": ["shorte.st"]
+ }
+ },
+ {
+ "Silverpop": {
+ "http://www.silverpop.com/": [
+ "mkt51.net",
+ "pages05.net",
+ "silverpop.com",
+ "vtrenz.net"
+ ]
+ }
+ },
+ {
+ "Simpli.fi": {
+ "http://www.simpli.fi/": ["simpli.fi"]
+ }
+ },
+ {
+ "SiteScout": {
+ "http://www.sitescout.com/": ["sitescout.com"]
+ }
+ },
+ {
+ "Skimlinks": {
+ "http://skimlinks.com/": ["skimlinks.com", "skimresources.com"]
+ }
+ },
+ {
+ "Skupe Net": {
+ "http://www.skupenet.com/": ["adcentriconline.com", "skupenet.com"]
+ }
+ },
+ {
+ "Smaato": {
+ "http://www.smaato.com/": ["smaato.com"]
+ }
+ },
+ {
+ "SmartAdServer": {
+ "http://smartadserver.com/": ["smartadserver.com"]
+ }
+ },
+ {
+ "SmartyAds": {
+ "https://smartyads.com/": ["smartyads.com"]
+ }
+ },
+ {
+ "Smiley Media": {
+ "http://www.smileymedia.com/": ["smileymedia.com"]
+ }
+ },
+ {
+ "Smowtion": {
+ "http://smowtion.com/": ["smowtion.com"]
+ }
+ },
+ {
+ "Snap": {
+ "http://www.snap.com/": ["snap.com"]
+ }
+ },
+ {
+ "SocialChorus": {
+ "http://www.socialchorus.com/": [
+ "halogenmediagroup.com",
+ "halogennetwork.com",
+ "socialchorus.com"
+ ]
+ }
+ },
+ {
+ "SocialInterface": {
+ "http://socialinterface.com/": [
+ "ratevoice.com",
+ "socialinterface.com"
+ ]
+ }
+ },
+ {
+ "SocialTwist": {
+ "http://tellafriend.socialtwist.com/": ["socialtwist.com"]
+ }
+ },
+ {
+ "sociomantic labs": {
+ "http://www.sociomantic.com/": ["sociomantic.com"]
+ }
+ },
+ {
+ "Socital": {
+ "https://www.socital.com": ["socital.com"]
+ }
+ },
+ {
+ "Sojern": {
+ "https://www.sojern.com": ["sojern.com"]
+ }
+ },
+ {
+ "SomoAudience": {
+ "https://somoaudience.com/": ["somoaudience.com"]
+ }
+ },
+ {
+ "Sonobi": {
+ "http://sonobi.com/": ["sonobi.com"]
+ }
+ },
+ {
+ "sophus3": {
+ "http://www.sophus3.com/": ["sophus3.co.uk", "sophus3.com"]
+ }
+ },
+ {
+ "Sortable": {
+ "https://www.sortable.com/": ["deployads.com"]
+ }
+ },
+ {
+ "Sovrn": {
+ "https://www.sovrn.com/": ["sovrn.com"]
+ }
+ },
+ {
+ "Space Chimp Media": {
+ "http://spacechimpmedia.com/": ["spacechimpmedia.com"]
+ }
+ },
+ {
+ "Sparklit": {
+ "http://www.sparklit.com/": ["adbutler.com", "sparklit.com"]
+ }
+ },
+ {
+ "Spark Studios": {
+ "http://www.sparkstudios.com/": ["sparkstudios.com"]
+ }
+ },
+ {
+ "Specific Media": {
+ "http://www.specificmedia.com/": [
+ "adviva.co.uk",
+ "adviva.net",
+ "sitemeter.com",
+ "specificclick.net",
+ "specificmedia.co.uk",
+ "specificmedia.com"
+ ]
+ }
+ },
+ {
+ "Spectate": {
+ "http://spectate.com/": ["spectate.com"]
+ }
+ },
+ {
+ "Sponge": {
+ "http://spongegroup.com/": ["spongegroup.com"]
+ }
+ },
+ {
+ "Spongecell": {
+ "http://www.spongecell.com/": ["spongecell.com"]
+ }
+ },
+ {
+ "SponsorAds": {
+ "http://www.sponsorads.de/": ["sponsorads.de"]
+ }
+ },
+ {
+ "Spot200": {
+ "http://spot200.com/": ["spot200.com"]
+ }
+ },
+ {
+ "SpotX": {
+ "https://www.spotx.tv": ["spotx.tv"]
+ }
+ },
+ {
+ "SpotXchange": {
+ "http://www.spotxchange.com/": ["spotxchange.com"]
+ }
+ },
+ {
+ "SpringServe": {
+ "https://springserve.com/": ["springserve.com"]
+ }
+ },
+ {
+ "StackAdapt": {
+ "https://www.stackadapt.com/": ["stackadapt.com"]
+ }
+ },
+ {
+ "StarGames": {
+ "https://www.stargames.net/": ["stargamesaffiliate.com"]
+ }
+ },
+ {
+ "SteelHouse": {
+ "http://www.steelhouse.com/": [
+ "steelhouse.com",
+ "steelhousemedia.com"
+ ]
+ }
+ },
+ {
+ "Storygize": {
+ "http://www.storygize.com/": ["storygize.com", "storygize.net"]
+ }
+ },
+ {
+ "Streamray": {
+ "http://streamray.com/": ["cams.com", "streamray.com"]
+ }
+ },
+ {
+ "StrikeAd": {
+ "http://www.strikead.com/": ["strikead.com"]
+ }
+ },
+ {
+ "StrongMail": {
+ "http://www.strongmail.com/": ["popularmedia.com"]
+ }
+ },
+ {
+ "Struq": {
+ "http://struq.com/": ["struq.com"]
+ }
+ },
+ {
+ "Sublime Skinz": {
+ "http://sublime.xyz/": ["ayads.co", "sublime.xyz"]
+ }
+ },
+ {
+ "Suite 66": {
+ "http://www.suite66.com/": ["suite66.com"]
+ }
+ },
+ {
+ "Summit": {
+ "http://www.summit.co.uk/": ["summitmedia.co.uk"]
+ }
+ },
+ {
+ "Superfish": {
+ "http://www.superfish.com/": ["superfish.com"]
+ }
+ },
+ {
+ "SupersonicAds": {
+ "http://www.supersonicads.com/": ["supersonicads.com"]
+ }
+ },
+ {
+ "Survata": {
+ "https://www.survata.com/": ["survata.com"]
+ }
+ },
+ {
+ "Switch": {
+ "http://www.switchconcepts.com/": [
+ "ethicalads.net",
+ "switchadhub.com",
+ "switchconcepts.co.uk",
+ "switchconcepts.com"
+ ]
+ }
+ },
+ {
+ "Swoop": {
+ "http://swoop.com/": ["swoop.com"]
+ }
+ },
+ {
+ "SymphonyAM": {
+ "http://www.factortg.com/": ["factortg.com"]
+ }
+ },
+ {
+ "Syncapse": {
+ "http://www.syncapse.com/": ["clickable.net", "syncapse.com"]
+ }
+ },
+ {
+ "Syrup Ad": {
+ "http://adotsolution.com/": ["adotsolution.com"]
+ }
+ },
+ {
+ "Taboola": {
+ "https://www.taboola.com/": ["perfectmarket.com", "taboola.com"]
+ }
+ },
+ {
+ "Tailsweep": {
+ "http://www.tailsweep.com/": ["tailsweep.com"]
+ }
+ },
+ {
+ "Taleria": {
+ "https://outstream.telaria.com/": ["freeskreen.com"]
+ }
+ },
+ {
+ "Tapad": {
+ "http://www.tapad.com/": ["tapad.com"]
+ }
+ },
+ {
+ "Tapgage": {
+ "http://www.tapgage.com/": ["bizmey.com", "tapgage.com"]
+ }
+ },
+ {
+ "TapIt!": {
+ "http://tapit.com/": ["tapit.com"]
+ }
+ },
+ {
+ "Tap.me": {
+ "http://tap.me/": ["tap.me"]
+ }
+ },
+ {
+ "Targetix": {
+ "http://targetix.net/": ["targetix.net"]
+ }
+ },
+ {
+ "Tatto Media": {
+ "http://tattomedia.com/": ["quicknoodles.com", "tattomedia.com"]
+ }
+ },
+ {
+ "Teadma": {
+ "http://www.teadma.com/": ["teadma.com"]
+ }
+ },
+ {
+ "Teads.tv": {
+ "http://teads.tv/": ["ebuzzing.com", "teads.tv"]
+ }
+ },
+ {
+ "Technorati": {
+ "http://technorati.com/": ["technorati.com", "technoratimedia.com"]
+ }
+ },
+ {
+ "TellApart": {
+ "http://tellapart.com/": ["tellapart.com", "tellapt.com"]
+ }
+ },
+ {
+ "Telstra": {
+ "http://www.telstra.com.au/": [
+ "sensis.com.au",
+ "sensisdata.com.au",
+ "sensisdigitalmedia.com.au",
+ "telstra.com.au"
+ ]
+ }
+ },
+ {
+ "Terra": {
+ "http://www.terra.com.br/": ["eztargetmedia.com", "terra.com.br"]
+ }
+ },
+ {
+ "The Numa Group": {
+ "http://www.thenumagroup.com/": ["hittail.com", "thenumagroup.com"]
+ }
+ },
+ {
+ "The Search Agency": {
+ "http://www.thesearchagency.com/": [
+ "thesearchagency.com",
+ "thesearchagency.net"
+ ]
+ }
+ },
+ {
+ "The Trade Desk": {
+ "http://thetradedesk.com/": ["adsrvr.org", "thetradedesk.com"]
+ }
+ },
+ {
+ "Think Realtime": {
+ "http://www.thinkrealtime.com/": [
+ "echosearch.com",
+ "esm1.net",
+ "thinkrealtime.com"
+ ]
+ }
+ },
+ {
+ "Tinder": {
+ "http://tinder.com/": ["carbonads.com", "tinder.com"]
+ }
+ },
+ {
+ "TiqIQ": {
+ "http://www.tiqiq.com/": ["tiqiq.com"]
+ }
+ },
+ {
+ "Tisoomi": {
+ "http://www.tisoomi.com/": ["adternal.com", "tisoomi.com"]
+ }
+ },
+ {
+ "TLVMedia": {
+ "http://tlvmedia.com/": ["tlvmedia.com"]
+ }
+ },
+ {
+ "Todacell": {
+ "http://www.todacell.com/": ["todacell.com"]
+ }
+ },
+ {
+ "ToneFuse": {
+ "http://tonefuse.com/": ["tonefuse.com"]
+ }
+ },
+ {
+ "ToneMedia": {
+ "http://tonemedia.com/": ["clickfuse.com", "tonemedia.com"]
+ }
+ },
+ {
+ "TouchCommerce": {
+ "http://www.touchcommerce.com/": ["inq.com", "touchcommerce.com"]
+ }
+ },
+ {
+ "TrackingSoft": {
+ "http://trackingsoft.com/": ["trackingsoft.com"]
+ }
+ },
+ {
+ "Tradedoubler": {
+ "http://www.tradedoubler.com/": ["tradedoubler.com"]
+ }
+ },
+ {
+ "TradeTracker": {
+ "http://www.tradetracker.com/": [
+ "tradetracker.com",
+ "tradetracker.net"
+ ]
+ }
+ },
+ {
+ "TrafficHaus": {
+ "http://www.traffichaus.com/": ["traffichaus.com", "traffichouse.com"]
+ }
+ },
+ {
+ "TrafficRevenue": {
+ "http://www.trafficrevenue.net/": ["trafficrevenue.net"]
+ }
+ },
+ {
+ "Traffiq": {
+ "http://www.traffiq.com/": ["traffiq.com"]
+ }
+ },
+ {
+ "Trafmag": {
+ "http://trafmag.com/": ["trafmag.com"]
+ }
+ },
+ {
+ "Traverse": {
+ "http://www.traversedata.com/": ["traversedlp.com"]
+ }
+ },
+ {
+ "Travora Media": {
+ "http://www.travoramedia.com/": [
+ "traveladnetwork.com",
+ "traveladvertising.com",
+ "travoramedia.com"
+ ]
+ }
+ },
+ {
+ "Tremor Video": {
+ "http://www.tremorvideo.com/": [
+ "scanscout.com",
+ "tmnetads.com",
+ "tremorhub.com",
+ "tremormedia.com",
+ "tremorvideo.com"
+ ]
+ }
+ },
+ {
+ "Triggit": {
+ "http://triggit.com/": ["triggit.com"]
+ }
+ },
+ {
+ "TripleLift": {
+ "http://triplelift.com/": ["3lift.com", "triplelift.com"]
+ }
+ },
+ {
+ "TruEffect": {
+ "http://www.trueffect.com/": ["adlegend.com", "trueffect.com"]
+ }
+ },
+ {
+ "TrustX": {
+ "https://trustx.org/": ["trustx.org"]
+ }
+ },
+ {
+ "TubeMogul": {
+ "http://www.tubemogul.com/": ["tmogul.com", "tubemogul.com"]
+ }
+ },
+ {
+ "Twelvefold": {
+ "http://www.twelvefold.com/": ["buzzlogic.com", "twelvefold.com"]
+ }
+ },
+ {
+ "Twitter": {
+ "https://twitter.com/": ["ads-twitter.com"]
+ }
+ },
+ {
+ "Twyn Group": {
+ "http://www.twyn.com/": ["twyn-group.com", "twyn.com"]
+ }
+ },
+ {
+ "Tyroo": {
+ "http://www.tyroo.com/": ["tyroo.com"]
+ }
+ },
+ {
+ "ucfunnel": {
+ "https://www.ucfunnel.com/": ["aralego.com", "ucfunnel.com"]
+ }
+ },
+ {
+ "uCoz": {
+ "http://www.ucoz.com/": [
+ "ucoz.ae",
+ "ucoz.br",
+ "ucoz.com",
+ "ucoz.du",
+ "ucoz.fr",
+ "ucoz.net",
+ "ucoz.ru"
+ ]
+ }
+ },
+ {
+ "Unanimis": {
+ "http://www.unanimis.co.uk/": ["unanimis.co.uk"]
+ }
+ },
+ {
+ "Underdog Media": {
+ "http://www.underdogmedia.com/": ["udmserve.net", "underdogmedia.com"]
+ }
+ },
+ {
+ "Undertone": {
+ "http://www.undertone.com/": [
+ "undertone.com",
+ "undertonenetworks.com",
+ "undertonevideo.com"
+ ]
+ }
+ },
+ {
+ "UniQlick": {
+ "http://www.uniqlick.com/": [
+ "51network.com",
+ "uniqlick.com",
+ "wanmo.com"
+ ]
+ }
+ },
+ {
+ "Unruly": {
+ "https://unruly.co/": ["unrulymedia.com"]
+ }
+ },
+ {
+ "Upland": {
+ "https://uplandsoftware.com/": ["leadlander.com", "trackalyzer.com"]
+ }
+ },
+ {
+ "up-value": {
+ "http://www.up-value.de/": ["up-value.de"]
+ }
+ },
+ {
+ "Value Ad": {
+ "http://valuead.com/": ["valuead.com"]
+ }
+ },
+ {
+ "Various": {
+ "http://www.various.com/": [
+ "amigos.com",
+ "getiton.com",
+ "medley.com",
+ "nostringsattached.com",
+ "various.com"
+ ]
+ }
+ },
+ {
+ "Vdopia": {
+ "http://www.vdopia.com/": ["ivdopia.com", "vdopia.com"]
+ }
+ },
+ {
+ "Veeseo": {
+ "http://veeseo.com": ["veeseo.com"]
+ }
+ },
+ {
+ "Velocity Media": {
+ "http://adsvelocity.com/": ["adsvelocity.com"]
+ }
+ },
+ {
+ "Velti": {
+ "http://www.velti.com/": ["mobclix.com", "velti.com"]
+ }
+ },
+ {
+ "Vemba": {
+ "https://www.vemba.com/": ["vemba.com"]
+ }
+ },
+ {
+ "Venatus Media": {
+ "http://venatusmedia.com": ["venatusmedia.com"]
+ }
+ },
+ {
+ "Vendemore": {
+ "https://vendemore.com/": ["vendemore.com"]
+ }
+ },
+ {
+ "Vendio": {
+ "http://www.vendio.com/": ["singlefeed.com", "vendio.com"]
+ }
+ },
+ {
+ "Veoxa": {
+ "http://www.veoxa.com/": ["veoxa.com"]
+ }
+ },
+ {
+ "Veremedia": {
+ "http://www.veremedia.com/": ["veremedia.com"]
+ }
+ },
+ {
+ "VerticalHealth": {
+ "https://www.verticalhealth.com/": ["verticalhealth.net"]
+ }
+ },
+ {
+ "VerticalResponse": {
+ "http://www.verticalresponse.com/": [
+ "verticalresponse.com",
+ "vresp.com"
+ ]
+ }
+ },
+ {
+ "Vibrant Media": {
+ "http://www.vibrantmedia.com/": [
+ "intellitxt.com",
+ "picadmedia.com",
+ "vibrantmedia.com"
+ ]
+ }
+ },
+ {
+ "VideoIntelligence": {
+ "https://www.vi.ai/": ["vi.ai"]
+ }
+ },
+ {
+ "VigLink": {
+ "http://www.viglink.com/": ["viglink.com"]
+ }
+ },
+ {
+ "VisibleBrands": {
+ "http://www.visbrands.com/": ["visbrands.com"]
+ }
+ },
+ {
+ "Visible Measures": {
+ "http://www.visiblemeasures.com/": [
+ "viewablemedia.net",
+ "visiblemeasures.com"
+ ]
+ }
+ },
+ {
+ "VisualDNA": {
+ "http://www.visualdna.com/": [
+ "vdna-assets.com",
+ "visualdna-stats.com",
+ "visualdna.com"
+ ]
+ }
+ },
+ {
+ "Vizu": {
+ "http://www.vizu.com/": ["vizu.com"]
+ }
+ },
+ {
+ "Vizury": {
+ "http://www.vizury.com/": ["vizury.com"]
+ }
+ },
+ {
+ "Vserv": {
+ "http://www.vserv.com/": ["vserv.com", "vserv.mobi"]
+ }
+ },
+ {
+ "Vuble": {
+ "https://vuble.tv/us/": ["mediabong.com"]
+ }
+ },
+ {
+ "Wahoha": {
+ "http://wahoha.com/": ["contentwidgets.net", "wahoha.com"]
+ }
+ },
+ {
+ "Wayfair": {
+ "https://www.wayfair.com/": ["wayfair.com"]
+ }
+ },
+ {
+ "WebAds": {
+ "http://www.webads.co.uk/": ["webads.co.uk"]
+ }
+ },
+ {
+ "Web.com": {
+ "http://www.web.com/": ["feedperfect.com", "web.com"]
+ }
+ },
+ {
+ "WebGozar.com": {
+ "http://www.webgozar.com/": ["webgozar.com", "webgozar.ir"]
+ }
+ },
+ {
+ "Webmecanik": {
+ "https://www.webmecanik.com/": ["webmecanik.com"]
+ }
+ },
+ {
+ "WebMetro": {
+ "http://www.webmetro.com/": ["dsmmadvantage.com", "webmetro.com"]
+ }
+ },
+ {
+ "Weborama": {
+ "http://weborama.com/": ["weborama.com", "weborama.fr"]
+ }
+ },
+ {
+ "Webtraffic": {
+ "http://www.webtraffic.se/": ["webtraffic.no", "webtraffic.se"]
+ }
+ },
+ {
+ "WideOrbit": {
+ "https://www.wideorbit.com/": ["dep-x.com"]
+ }
+ },
+ {
+ "WiredMinds": {
+ "http://www.wiredminds.com/": ["wiredminds.com", "wiredminds.de"]
+ }
+ },
+ {
+ "Wishabi": {
+ "http://wishabi.com": ["wishabi.com", "wishabi.net"]
+ }
+ },
+ {
+ "WordStream": {
+ "http://www.wordstream.com/": ["wordstream.com"]
+ }
+ },
+ {
+ "WPP": {
+ "http://www.wpp.com/": [
+ "247realmedia.com",
+ "accelerator-media.com",
+ "acceleratorusa.com",
+ "decdna.net",
+ "decideinteractive.com",
+ "gmads.net",
+ "groupm.com",
+ "kantarmedia.com",
+ "mecglobal.com",
+ "mindshare.nl",
+ "mookie1.com",
+ "pm14.com",
+ "realmedia.com",
+ "targ.ad",
+ "themig.com",
+ "wpp.com",
+ "xaxis.com"
+ ]
+ }
+ },
+ {
+ "xAd": {
+ "http://www.xad.com/": ["xad.com"]
+ }
+ },
+ {
+ "Xertive Media": {
+ "http://www.xertivemedia.com/": [
+ "admanager-xertive.com",
+ "xertivemedia.com"
+ ]
+ }
+ },
+ {
+ "xplosion interactive": {
+ "http://www.xplosion.de/": ["xplosion.de"]
+ }
+ },
+ {
+ "Xrost DS": {
+ "http://www.adplan-ds.com/": ["adplan-ds.com"]
+ }
+ },
+ {
+ "Yabuka": {
+ "http://www.yabuka.com/": ["yabuka.com"]
+ }
+ },
+ {
+ "Yahoo!": {
+ "http://www.yahoo.com/": [
+ "adinterax.com",
+ "adrevolver.com",
+ "ads.yahoo.com",
+ "adserver.yahoo.com",
+ "advertising.yahoo.com",
+ "bluelithium.com",
+ "dapper.net",
+ "flurry.com",
+ "interclick.com",
+ "marketingsolutions.yahoo.com",
+ "overture.com",
+ "rightmedia.com",
+ "rmxads.com",
+ "secure-adserver.com",
+ "thewheelof.com",
+ "yieldmanager.com",
+ "yieldmanager.net",
+ "yldmgrimg.net"
+ ]
+ }
+ },
+ {
+ "Yandex": {
+ "http://www.yandex.com/": [
+ "adfox.yandex.ru",
+ "an.yandex.ru",
+ "awaps.yandex.ru",
+ "mc.yandex.ru",
+ "moikrug.ru",
+ "web-visor.com",
+ "yandex.ru/clck/click",
+ "yandex.ru/clck/counter",
+ "yandex.ru/cycounter",
+ "yandex.ru/portal/set/any",
+ "yandex.ru/set/s/rsya-tag-users/data"
+ ]
+ }
+ },
+ {
+ "Ybrant Digital": {
+ "http://www.ybrantdigital.com/": [
+ "addynamix.com",
+ "adserverplus.com",
+ "oridian.com",
+ "ybrantdigital.com"
+ ]
+ }
+ },
+ {
+ "YD": {
+ "http://www.ydworld.com/": ["ydworld.com", "yieldivision.com"]
+ }
+ },
+ {
+ "YellowHammer": {
+ "http://www.yhmg.com/": [
+ "attracto.com",
+ "clickhype.com",
+ "yellowhammermg.com",
+ "yhmg.com"
+ ]
+ }
+ },
+ {
+ "Yes Ads": {
+ "http://yesads.com/": ["yesads.com"]
+ }
+ },
+ {
+ "YieldAds": {
+ "http://yieldads.com/": ["yieldads.com"]
+ }
+ },
+ {
+ "YieldBids": {
+ "http://ybx.io/": ["ybx.io"]
+ }
+ },
+ {
+ "YieldBot": {
+ "http://yieldbot.com/": ["yldbt.com"]
+ }
+ },
+ {
+ "YieldBuild": {
+ "http://yieldbuild.com/": ["yieldbuild.com"]
+ }
+ },
+ {
+ "Yieldify": {
+ "https://www.yieldify.com/": ["yieldify.com"]
+ }
+ },
+ {
+ "Yieldlab": {
+ "http://www.yieldlab.de/": ["yieldlab.de", "yieldlab.net"]
+ }
+ },
+ {
+ "Yieldmo": {
+ "https://yieldmo.com": ["yieldmo.com"]
+ }
+ },
+ {
+ "YieldNexus": {
+ "https://www.yieldnexus.com/": ["ynxs.io"]
+ }
+ },
+ {
+ "YOC": {
+ "http://group.yoc.com/": ["yoc-performance.com", "yoc.com"]
+ }
+ },
+ {
+ "Yoggrt": {
+ "http://www.yoggrt.com/": ["yoggrt.com"]
+ }
+ },
+ {
+ "youknowbest": {
+ "http://www.youknowbest.com/": ["youknowbest.com"]
+ }
+ },
+ {
+ "YuMe": {
+ "http://www.yume.com/": ["yume.com", "yumenetworks.com"]
+ }
+ },
+ {
+ "ZafulAffiliate": {
+ "https://affiliate.zaful.com/": [
+ "affasi.com",
+ "gw-ec.com",
+ "zaful.com"
+ ]
+ }
+ },
+ {
+ "Zango": {
+ "http://www.zango.com/": ["metricsdirect.com", "zango.com"]
+ }
+ },
+ {
+ "zanox": {
+ "http://www.zanox.com/": ["buy.at", "zanox-affiliate.de", "zanox.com"]
+ }
+ },
+ {
+ "zapunited": {
+ "http://www.zapunited.com/": ["zaparena.com", "zapunited.com"]
+ }
+ },
+ {
+ "ZEDO": {
+ "http://www.zedo.com/": ["zedo.com", "zincx.com"]
+ }
+ },
+ {
+ "Zefir": {
+ "https://ze-fir.com/": ["ze-fir.com"]
+ }
+ },
+ {
+ "Zemanta": {
+ "http://www.zemanta.com/": ["zemanta.com"]
+ }
+ },
+ {
+ "ZestAd": {
+ "http://www.zestad.com/": ["zestad.com"]
+ }
+ },
+ {
+ "Zeta Email Solutions": {
+ "http://www.zetaemailsolutions.com/": [
+ "insightgrit.com",
+ "zetaemailsolutions.com"
+ ]
+ }
+ },
+ {
+ "Zumobi": {
+ "http://www.zumobi.com/": ["zumobi.com"]
+ }
+ },
+ {
+ "ZypMedia": {
+ "http://www.zypmedia.com/": ["extend.tv", "zypmedia.com"]
+ }
+ }
+ ],
+ "Content": [
+ {
+ "33Across": {
+ "http://33across.com/": ["tynt.com"]
+ }
+ },
+ {
+ "ActivEngage": {
+ "http://www.activengage.com/": ["activengage.com"]
+ }
+ },
+ {
+ "Adap.tv": {
+ "http://adap.tv/": ["adap.tv"]
+ }
+ },
+ {
+ "Adobe": {
+ "http://www.adobe.com/": [
+ "adobe.com",
+ "fyre.co",
+ "livefyre.com",
+ "typekit.com"
+ ]
+ }
+ },
+ {
+ "Akamai": {
+ "http://www.akamai.com/": ["abmr.net", "akamai.com", "edgesuite.net"]
+ }
+ },
+ {
+ "AKQA": {
+ "http://www.akqa.com/": ["akqa.com", "srtk.net"]
+ }
+ },
+ {
+ "Amazon.com": {
+ "http://www.amazon.com/": [
+ "alexa.com",
+ "amazon.com",
+ "cloudfront.net"
+ ]
+ }
+ },
+ {
+ "AOL": {
+ "http://www.aol.com/": [
+ "5min.com",
+ "aim.com",
+ "aol.com",
+ "aolanswers.com",
+ "aolcdn.com",
+ "aoltechguru.com",
+ "autoblog.com",
+ "cambio.com",
+ "dailyfinance.com",
+ "editions.com",
+ "engadget.com",
+ "games.com",
+ "homesessive.com",
+ "huffingtonpost.com",
+ "joystiq.com",
+ "kitchendaily.com",
+ "makers.com",
+ "mandatory.com",
+ "mapquest.com",
+ "moviefone.com",
+ "noisecreep.com",
+ "patch.com",
+ "pawnation.com",
+ "shortcuts.com",
+ "shoutcast.com",
+ "spinner.com",
+ "stylelist.com",
+ "stylemepretty.com",
+ "surphace.com",
+ "techcrunch.com",
+ "theboombox.com",
+ "theboot.com",
+ "tuaw.com",
+ "userplane.com",
+ "winamp.com"
+ ]
+ }
+ },
+ {
+ "Automattic": {
+ "http://automattic.com/": [
+ "automattic.com",
+ "gravatar.com",
+ "intensedebate.com"
+ ]
+ }
+ },
+ {
+ "Baynote": {
+ "http://www.baynote.com/": ["baynote.com", "baynote.net"]
+ }
+ },
+ {
+ "Bazaarvoice": {
+ "http://www.bazaarvoice.com/": ["bazaarvoice.com"]
+ }
+ },
+ {
+ "BigDoor": {
+ "http://www.bigdoor.com/": ["bigdoor.com", "onetruefan.com"]
+ }
+ },
+ {
+ "Brightcove": {
+ "http://www.brightcove.com/": ["brightcove.com"]
+ }
+ },
+ {
+ "Browser-Update.org": {
+ "www.browser-update.org/": ["browser-update.org"]
+ }
+ },
+ {
+ "BTBuckets": {
+ "http://btbuckets.com/": ["btbuckets.com"]
+ }
+ },
+ {
+ "Buffer": {
+ "http://bufferapp.com/": ["bufferapp.com"]
+ }
+ },
+ {
+ "Bunchball": {
+ "http://www.bunchball.com/": ["bunchball.com"]
+ }
+ },
+ {
+ "buySAFE": {
+ "http://www.buysafe.com/": ["buysafe.com"]
+ }
+ },
+ {
+ "BuzzFeed": {
+ "http://www.buzzfeed.com/": ["buzzfed.com", "buzzfeed.com"]
+ }
+ },
+ {
+ "Cbox": {
+ "http://www.cbox.ws/": ["cbox.ws"]
+ }
+ },
+ {
+ "CBS Interactive": {
+ "http://www.cbsinteractive.com/": ["cbsinteractive.com", "com.com"]
+ }
+ },
+ {
+ "Cedexis": {
+ "http://www.cedexis.com/": ["cedexis.com", "cedexis.net"]
+ }
+ },
+ {
+ "Certona": {
+ "http://www.certona.com/": ["certona.com", "res-x.com"]
+ }
+ },
+ {
+ "ClipSyndicate": {
+ "http://www.clipsyndicate.com/": ["clipsyndicate.com"]
+ }
+ },
+ {
+ "Collarity": {
+ "http://www.collarity.com/": ["collarity.com"]
+ }
+ },
+ {
+ "Conduit": {
+ "http://www.conduit.com/": [
+ "conduit-banners.com",
+ "conduit-services.com",
+ "conduit.com",
+ "wibiya.com"
+ ]
+ }
+ },
+ {
+ "Congoo": {
+ "http://www.congoo.com/": ["congoo.com"]
+ }
+ },
+ {
+ "Contact At Once!": {
+ "http://www.contactatonce.com/": ["contactatonce.com"]
+ }
+ },
+ {
+ "Conviva": {
+ "http://www.conviva.com/": ["conviva.com"]
+ }
+ },
+ {
+ "DailyMe": {
+ "http://dailyme.com/": ["dailyme.com", "newstogram.com"]
+ }
+ },
+ {
+ "DataSift": {
+ "http://datasift.com/": ["datasift.com", "tweetmeme.com"]
+ }
+ },
+ {
+ "Disqus": {
+ "http://disqus.com/": ["disqus.com"]
+ }
+ },
+ {
+ "Echo": {
+ "http://aboutecho.com/": [
+ "aboutecho.com",
+ "haloscan.com",
+ "js-kit.com"
+ ]
+ }
+ },
+ {
+ "Facebook": {
+ "http://www.facebook.com/": [
+ "fbcdn.net",
+ "instagram.com",
+ "messenger.com"
+ ]
+ }
+ },
+ {
+ "Flattr": {
+ "http://flattr.com/": ["flattr.com"]
+ }
+ },
+ {
+ "FreeWheel": {
+ "http://www.freewheel.tv/": ["freewheel.tv", "fwmrm.net"]
+ }
+ },
+ {
+ "Genius.com": {
+ "http://www.genius.com/": ["genius.com"]
+ }
+ },
+ {
+ "Get Satisfaction": {
+ "https://getsatisfaction.com/": ["getsatisfaction.com"]
+ }
+ },
+ {
+ "Gigya": {
+ "http://www.gigya.com/": ["gigcount.com", "gigya.com"]
+ }
+ },
+ {
+ "Global Takeoff": {
+ "http://www.globaltakeoff.com/": [
+ "globaltakeoff.com",
+ "globaltakeoff.net"
+ ]
+ }
+ },
+ {
+ "GoGrid": {
+ "http://www.gogrid.com/": [
+ "formalyzer.com",
+ "gogrid.com",
+ "komli.net"
+ ]
+ }
+ },
+ {
+ "Google": {
+ "http://www.google.com/": [
+ "accounts.google.com",
+ "apis.google.com",
+ "appengine.google.com",
+ "apture.com",
+ "blogger.com",
+ "books.google.com",
+ "checkout.google.com",
+ "chrome.google.com",
+ "code.google.com",
+ "codesearch.google.com",
+ "docs.google.com",
+ "drive.google.com",
+ "earth.google.com",
+ "encrypted.google.com",
+ "feedburner.com",
+ "feedburner.google.com",
+ "feedproxy.google.com",
+ "finance.google.com",
+ "ggpht.com",
+ "gmodules.com",
+ "google-melange.com",
+ "google.ad",
+ "google.ae",
+ "google.al",
+ "google.am",
+ "google.as",
+ "google.at",
+ "google.az",
+ "google.ba",
+ "google.be",
+ "google.bf",
+ "google.bg",
+ "google.bi",
+ "google.bj",
+ "google.bs",
+ "google.bt",
+ "google.by",
+ "google.ca",
+ "google.cat",
+ "google.cd",
+ "google.cf",
+ "google.cg",
+ "google.ch",
+ "google.ci",
+ "google.cl",
+ "google.cm",
+ "google.cn",
+ "google.co.ao",
+ "google.co.bw",
+ "google.co.ck",
+ "google.co.cr",
+ "google.co.id",
+ "google.co.il",
+ "google.co.in",
+ "google.co.jp",
+ "google.co.ke",
+ "google.co.kr",
+ "google.co.ls",
+ "google.co.ma",
+ "google.co.mz",
+ "google.co.nz",
+ "google.co.th",
+ "google.co.tz",
+ "google.co.ug",
+ "google.co.uk",
+ "google.co.uz",
+ "google.co.ve",
+ "google.co.vi",
+ "google.co.za",
+ "google.co.zm",
+ "google.co.zw",
+ "google.com",
+ "google.com.af",
+ "google.com.ag",
+ "google.com.ai",
+ "google.com.ar",
+ "google.com.au",
+ "google.com.bd",
+ "google.com.bh",
+ "google.com.bn",
+ "google.com.bo",
+ "google.com.br",
+ "google.com.bz",
+ "google.com.co",
+ "google.com.cu",
+ "google.com.cy",
+ "google.com.do",
+ "google.com.ec",
+ "google.com.eg",
+ "google.com.et",
+ "google.com.fj",
+ "google.com.gh",
+ "google.com.gi",
+ "google.com.gt",
+ "google.com.hk",
+ "google.com.jm",
+ "google.com.kh",
+ "google.com.kw",
+ "google.com.lb",
+ "google.com.ly",
+ "google.com.mm",
+ "google.com.mt",
+ "google.com.mx",
+ "google.com.my",
+ "google.com.na",
+ "google.com.nf",
+ "google.com.ng",
+ "google.com.ni",
+ "google.com.np",
+ "google.com.om",
+ "google.com.pa",
+ "google.com.pe",
+ "google.com.pg",
+ "google.com.ph",
+ "google.com.pk",
+ "google.com.pr",
+ "google.com.py",
+ "google.com.qa",
+ "google.com.sa",
+ "google.com.sb",
+ "google.com.sg",
+ "google.com.sl",
+ "google.com.sv",
+ "google.com.tj",
+ "google.com.tr",
+ "google.com.tw",
+ "google.com.ua",
+ "google.com.uy",
+ "google.com.vc",
+ "google.com.vn",
+ "google.cv",
+ "google.cz",
+ "google.de",
+ "google.dj",
+ "google.dk",
+ "google.dm",
+ "google.dz",
+ "google.ee",
+ "google.es",
+ "google.fi",
+ "google.fm",
+ "google.fr",
+ "google.ga",
+ "google.ge",
+ "google.gg",
+ "google.gl",
+ "google.gm",
+ "google.gp",
+ "google.gr",
+ "google.gy",
+ "google.hn",
+ "google.hr",
+ "google.ht",
+ "google.hu",
+ "google.ie",
+ "google.im",
+ "google.iq",
+ "google.is",
+ "google.it",
+ "google.je",
+ "google.jo",
+ "google.kg",
+ "google.ki",
+ "google.kz",
+ "google.la",
+ "google.li",
+ "google.lk",
+ "google.lt",
+ "google.lu",
+ "google.lv",
+ "google.md",
+ "google.me",
+ "google.mg",
+ "google.mk",
+ "google.ml",
+ "google.mn",
+ "google.ms",
+ "google.mu",
+ "google.mv",
+ "google.mw",
+ "google.ne",
+ "google.nl",
+ "google.no",
+ "google.nr",
+ "google.nu",
+ "google.pl",
+ "google.pn",
+ "google.ps",
+ "google.pt",
+ "google.ro",
+ "google.rs",
+ "google.ru",
+ "google.rw",
+ "google.sc",
+ "google.se",
+ "google.sh",
+ "google.si",
+ "google.sk",
+ "google.sm",
+ "google.sn",
+ "google.so",
+ "google.st",
+ "google.td",
+ "google.tg",
+ "google.tk",
+ "google.tl",
+ "google.tm",
+ "google.tn",
+ "google.to",
+ "google.tt",
+ "google.vg",
+ "google.vu",
+ "google.ws",
+ "googleapis.com",
+ "googleartproject.com",
+ "googleusercontent.com",
+ "groups.google.com",
+ "gstatic.com",
+ "health.google.com",
+ "images.google.com",
+ "investor.google.com",
+ "knol.google.com",
+ "maps.google.com",
+ "music.google.com",
+ "news.google.com",
+ "panoramio.com",
+ "picasa.google.com",
+ "picasaweb.google.com",
+ "play.google.com",
+ "postini.com",
+ "recaptcha.net",
+ "script.google.com",
+ "shopping.google.com",
+ "sites.google.com",
+ "sketchup.google.com",
+ "support.google.com",
+ "talk.google.com",
+ "talkgadget.google.com",
+ "toolbar.google.com",
+ "translate.google.com",
+ "trends.google.com",
+ "video.google.com",
+ "videos.google.com",
+ "wallet.google.com",
+ "youtube.com"
+ ]
+ }
+ },
+ {
+ "Gravity": {
+ "http://www.gravity.com/": ["gravity.com", "grvcdn.com"]
+ }
+ },
+ {
+ "Heyzap": {
+ "http://www.heyzap.com/": ["heyzap.com"]
+ }
+ },
+ {
+ "HubSpot": {
+ "http://www.hubspot.com/": ["hubspot.com"]
+ }
+ },
+ {
+ "IBM": {
+ "http://www.ibm.com/": ["xtify.com"]
+ }
+ },
+ {
+ "iovation": {
+ "http://www.iovation.com/": ["iesnare.com", "iovation.com"]
+ }
+ },
+ {
+ "Kaltura": {
+ "http://corp.kaltura.com/": ["kaltura.com"]
+ }
+ },
+ {
+ "kikin": {
+ "http://www.kikin.com/": ["kikin.com"]
+ }
+ },
+ {
+ "Limelight Networks": {
+ "http://www.limelight.com/": [
+ "clickability.com",
+ "limelight.com",
+ "llnwd.net"
+ ]
+ }
+ },
+ {
+ "LivePerson": {
+ "http://www.liveperson.net/": ["liveperson.net"]
+ }
+ },
+ {
+ "LiveRail": {
+ "http://liverail.com/": ["liverail.com"]
+ }
+ },
+ {
+ "LongTail Video": {
+ "http://www.longtailvideo.com/": ["longtailvideo.com", "ltassrv.com"]
+ }
+ },
+ {
+ "Markit": {
+ "http://www.markit.com/": ["markit.com", "wsod.com"]
+ }
+ },
+ {
+ "MashLogic": {
+ "http://www.mashlogic.com/": ["mashlogic.com"]
+ }
+ },
+ {
+ "McAfee": {
+ "http://www.mcafee.com/": ["mcafee.com", "scanalert.com"]
+ }
+ },
+ {
+ "Microsoft": {
+ "http://www.microsoft.com/": [
+ "bing.com",
+ "gamesforwindows.com",
+ "getgamesmart.com",
+ "healthvault.com",
+ "ieaddons.com",
+ "iegallery.com",
+ "live.com",
+ "microsoft.com",
+ "microsoftalumni.com",
+ "microsoftalumni.org",
+ "microsoftstore.com",
+ "msn.com",
+ "msndirect.com",
+ "office.com",
+ "officelive.com",
+ "outlook.com",
+ "s-msn.com",
+ "skype.com",
+ "windowsphone.com",
+ "worldwidetelescope.org",
+ "xbox.com",
+ "zune.com",
+ "zune.net"
+ ]
+ }
+ },
+ {
+ "NDN": {
+ "http://www.newsinc.com/": ["newsinc.com"]
+ }
+ },
+ {
+ "Oberon Media": {
+ "http://www.oberon-media.com/": ["blaze.com", "oberon-media.com"]
+ }
+ },
+ {
+ "Ooyala": {
+ "http://www.ooyala.com/": ["oo4.com", "ooyala.com"]
+ }
+ },
+ {
+ "Oracle": {
+ "http://www.oracle.com/": [
+ "atgsvcs.com",
+ "instantservice.com",
+ "istrack.com",
+ "oracle.com"
+ ]
+ }
+ },
+ {
+ "Peerius": {
+ "http://www.peerius.com/": ["peerius.com"]
+ }
+ },
+ {
+ "Pinterest": {
+ "http://pinterest.com/": ["pinimg.com", "pinterest.com"]
+ }
+ },
+ {
+ "PunchTab": {
+ "http://www.punchtab.com/": ["punchtab.com"]
+ }
+ },
+ {
+ "RIM": {
+ "http://www.rim.com/": ["rim.com", "scoreloop.com"]
+ }
+ },
+ {
+ "Salesforce.com": {
+ "http://www.salesforce.com/": ["salesforceliveagent.com"]
+ }
+ },
+ {
+ "SAY": {
+ "http://saymedia.com/": [
+ "saymedia.com",
+ "typepad.com",
+ "videoegg.com"
+ ]
+ }
+ },
+ {
+ "ScribeFire": {
+ "http://www.scribefire.com/": ["scribefire.com"]
+ }
+ },
+ {
+ "Six Apart": {
+ "http://www.sixapart.com/": ["sixapart.com"]
+ }
+ },
+ {
+ "Skribit": {
+ "http://skribit.com/": ["skribit.com"]
+ }
+ },
+ {
+ "SnapEngage": {
+ "http://www.snapengage.com/": ["snapengage.com"]
+ }
+ },
+ {
+ "Spring Metrics": {
+ "http://www.springmetrics.com/": ["springmetrics.com"]
+ }
+ },
+ {
+ "Synacor": {
+ "http://www.synacor.com/": ["synacor.com"]
+ }
+ },
+ {
+ "ThingLink": {
+ "http://www.thinglink.com/": ["thinglink.com"]
+ }
+ },
+ {
+ "Thismoment": {
+ "http://www.thismoment.com/": ["thismoment.com"]
+ }
+ },
+ {
+ "Thummit": {
+ "http://www.thummit.com/": ["thummit.com"]
+ }
+ },
+ {
+ "Topsy": {
+ "http://topsy.com/": ["topsy.com"]
+ }
+ },
+ {
+ "TraceMyIP.org": {
+ "http://www.tracemyip.org/": ["tracemyip.org"]
+ }
+ },
+ {
+ "Trackset": {
+ "http://www.trackset.com/": ["trackset.com"]
+ }
+ },
+ {
+ "Trovus": {
+ "http://www.trovus.co.uk/": ["trovus.co.uk"]
+ }
+ },
+ {
+ "Trumba": {
+ "http://www.trumba.com/": ["trumba.com"]
+ }
+ },
+ {
+ "TRUSTe": {
+ "http://www.truste.com/": ["truste.com"]
+ }
+ },
+ {
+ "TurnTo": {
+ "http://www.turntonetworks.com/": ["turnto.com", "turntonetworks.com"]
+ }
+ },
+ {
+ "Tweetboard": {
+ "http://tweetboard.com/": ["tweetboard.com"]
+ }
+ },
+ {
+ "Twitter Counter": {
+ "http://twittercounter.com/": ["twittercounter.com"]
+ }
+ },
+ {
+ "UberMedia": {
+ "http://ubermedia.com/": ["tweetup.com", "ubermedia.com"]
+ }
+ },
+ {
+ "UberTags": {
+ "http://ubertags.com/": ["ubertags.com"]
+ }
+ },
+ {
+ "Unbounce": {
+ "http://unbounce.com/": ["unbounce.com"]
+ }
+ },
+ {
+ "Uptrends": {
+ "http://www.uptrends.com/": ["uptrends.com"]
+ }
+ },
+ {
+ "Usability Sciences": {
+ "http://www.usabilitysciences.com/": [
+ "usabilitysciences.com",
+ "webiqonline.com"
+ ]
+ }
+ },
+ {
+ "UserVoice": {
+ "http://www.uservoice.com/": ["uservoice.com"]
+ }
+ },
+ {
+ "Vertical Acuity": {
+ "http://www.verticalacuity.com/": ["verticalacuity.com"]
+ }
+ },
+ {
+ "VG WORT": {
+ "http://www.vgwort.de/": ["vgwort.de"]
+ }
+ },
+ {
+ "Videology": {
+ "http://www.videologygroup.com/": [
+ "tidaltv.com",
+ "videologygroup.com"
+ ]
+ }
+ },
+ {
+ "Viewbix": {
+ "http://www.viewbix.com/": ["qoof.com", "viewbix.com"]
+ }
+ },
+ {
+ "Vimeo": {
+ "http://vimeo.com/": ["vimeo.com", "vimeocdn.com"]
+ }
+ },
+ {
+ "VINDICO": {
+ "http://vindicogroup.com/": ["vindicogroup.com", "vindicosuite.com"]
+ }
+ },
+ {
+ "Voice2Page": {
+ "http://www.voice2page.com/": ["voice2page.com"]
+ }
+ },
+ {
+ "WebsiteAlive": {
+ "http://www.websitealive.com/": [
+ "websitealive.com",
+ "websitealive0.com",
+ "websitealive1.com",
+ "websitealive2.com",
+ "websitealive3.com",
+ "websitealive4.com",
+ "websitealive5.com",
+ "websitealive6.com",
+ "websitealive7.com",
+ "websitealive8.com",
+ "websitealive9.com"
+ ]
+ }
+ },
+ {
+ "Yahoo!": {
+ "http://www.yahoo.com/": [
+ "answers.yahoo.com",
+ "apps.yahoo.com",
+ "autos.yahoo.com",
+ "biz.yahoo.com",
+ "developer.yahoo.com",
+ "everything.yahoo.com",
+ "finance.yahoo.com",
+ "flickr.com",
+ "games.yahoo.com",
+ "groups.yahoo.com",
+ "help.yahoo.com",
+ "hotjobs.yahoo.com",
+ "info.yahoo.com",
+ "local.yahoo.com",
+ "luminate.com",
+ "messages.yahoo.com",
+ "movies.yahoo.com",
+ "msg.yahoo.com",
+ "news.yahoo.com",
+ "omg.yahoo.com",
+ "pipes.yahoo.com",
+ "pixazza.com",
+ "realestate.yahoo.com",
+ "search.yahoo.com",
+ "shine.yahoo.com",
+ "smallbusiness.yahoo.com",
+ "sports.yahoo.com",
+ "staticflickr.com",
+ "suggestions.yahoo.com",
+ "travel.yahoo.com",
+ "tumblr.com",
+ "upcoming.yahoo.com",
+ "webhosting.yahoo.com",
+ "widgets.yahoo.com",
+ "www.yahoo.com",
+ "yahooapis.com",
+ "yahoofs.com",
+ "yimg.com",
+ "ypolicyblog.com",
+ "yuilibrary.com",
+ "zenfs.com"
+ ]
+ }
+ },
+ {
+ "Yandex": {
+ "http://www.yandex.com/": [
+ "kinopoisk.ru",
+ "yandex.by",
+ "yandex.com",
+ "yandex.com.tr",
+ "yandex.ru",
+ "yandex.st",
+ "yandex.ua"
+ ]
+ }
+ },
+ {
+ "Zendesk": {
+ "http://www.zendesk.com/": ["zendesk.com"]
+ }
+ },
+ {
+ "Zopim": {
+ "https://www.zopim.com/": ["zopim.com"]
+ }
+ }
+ ],
+ "Analytics": [
+ {
+ "63 Squares": {
+ "http://63squares.com/": ["63squares.com", "i-stats.com"]
+ }
+ },
+ {
+ "Acxiom": {
+ "http://www.acxiom.com/": [
+ "acxiom.com",
+ "acxiomapac.com",
+ "mm7.net",
+ "pippio.com"
+ ]
+ }
+ },
+ {
+ "AddFreeStats": {
+ "http://www.addfreestats.com/": ["3dstats.com", "addfreestats.com"]
+ }
+ },
+ {
+ "Adloox": {
+ "http://www.adloox.com/": ["adloox.com", "adlooxtracking.com"]
+ }
+ },
+ {
+ "Adventori": {
+ "https://adventori.com": ["adventori.com"]
+ }
+ },
+ {
+ "AIData": {
+ "http://www.aidata.me/": ["advombat.ru", "aidata.me"]
+ }
+ },
+ {
+ "AivaLabs": {
+ "https://aivalabs.com": ["aivalabs.com"]
+ }
+ },
+ {
+ "Akamai": {
+ "http://www.akamai.com/": ["go-mpulse.net"]
+ }
+ },
+ {
+ "Amadesa": {
+ "http://www.amadesa.com/": ["amadesa.com"]
+ }
+ },
+ {
+ "Amazing Counters": {
+ "http://amazingcounters.com/": ["amazingcounters.com"]
+ }
+ },
+ {
+ "Amazon.com": {
+ "http://www.amazon.com/": ["alexametrics.com"]
+ }
+ },
+ {
+ "Amplitude": {
+ "https://amplitude.com/": ["amplitude.com"]
+ }
+ },
+ {
+ "anormal-media.de": {
+ "http://anormal-media.de/": ["anormal-media.de", "anormal-tracker.de"]
+ }
+ },
+ {
+ "AT Internet": {
+ "http://www.atinternet.com/": [
+ "at-o.net",
+ "atinternet.com",
+ "xiti.com"
+ ]
+ }
+ },
+ {
+ "Attracta": {
+ "https://www.attracta.com/": ["attracta.com"]
+ }
+ },
+ {
+ "Automattic": {
+ "http://automattic.com/": ["polldaddy.com"]
+ }
+ },
+ {
+ "AvantLink": {
+ "http://www.avantlink.com/": ["avmws.com"]
+ }
+ },
+ {
+ "Awio": {
+ "http://www.awio.com/": ["awio.com", "w3counter.com", "w3roi.com"]
+ }
+ },
+ {
+ "Belstat": {
+ "http://www.belstat.com/": [
+ "belstat.be",
+ "belstat.com",
+ "belstat.de",
+ "belstat.fr",
+ "belstat.nl"
+ ]
+ }
+ },
+ {
+ "BetssonPalantir": {
+ "https://betssonpalantir.com/": ["betssonpalantir.com"]
+ }
+ },
+ {
+ "BlogCounter.com": {
+ "http://www.blogcounter.de/": ["blogcounter.de"]
+ }
+ },
+ {
+ "BloomReach": {
+ "http://www.bloomreach.com/": ["p.brsrvr.com"]
+ }
+ },
+ {
+ "BlueCava": {
+ "http://www.bluecava.com/": ["bluecava.com"]
+ }
+ },
+ {
+ "Bluemetrix": {
+ "http://www.bluemetrix.com/": ["bluemetrix.com", "bmmetrix.com"]
+ }
+ },
+ {
+ "Bombora": {
+ "https://bombora.com/": ["ml314.com"]
+ }
+ },
+ {
+ "Branch": {
+ "https://branch.io/": ["branch.io"]
+ }
+ },
+ {
+ "Branica": {
+ "http://www.branica.com/": ["branica.com"]
+ }
+ },
+ {
+ "BrightEdge": {
+ "http://www.brightedge.com/": ["b0e8.com", "brightedge.com"]
+ }
+ },
+ {
+ "Bubblestat": {
+ "http://www.bubblestat.com/": ["bubblestat.com"]
+ }
+ },
+ {
+ "Cardlytics": {
+ "http://www.cardlytics.com/": ["cardlytics.com"]
+ }
+ },
+ {
+ "Chartbeat": {
+ "http://chartbeat.com/": ["chartbeat.com", "chartbeat.net"]
+ }
+ },
+ {
+ "Clickdensity": {
+ "http://www.clickdensity.com/": ["clickdensity.com"]
+ }
+ },
+ {
+ "ClickGuard": {
+ "https://www.clickguard.com/": ["clickguard.com"]
+ }
+ },
+ {
+ "ClickTale": {
+ "http://www.clicktale.com/": [
+ "clicktale.com",
+ "clicktale.net",
+ "pantherssl.com"
+ ],
+ "session-replay": "true"
+ }
+ },
+ {
+ "ClixMetrix": {
+ "http://www.clixmetrix.com/": ["clixmetrix.com"]
+ }
+ },
+ {
+ "Clixpy": {
+ "http://clixpy.com/": ["clixpy.com"]
+ }
+ },
+ {
+ "ClustrMaps": {
+ "http://www.clustrmaps.com/": ["clustrmaps.com"]
+ }
+ },
+ {
+ "CNZZ": {
+ "http://www.cnzz.com/": ["cnzz.com"]
+ }
+ },
+ {
+ "Compuware": {
+ "http://www.compuware.com/": [
+ "axf8.net",
+ "compuware.com",
+ "gomez.com"
+ ]
+ }
+ },
+ {
+ "comScore": {
+ "http://www.comscore.com/": [
+ "certifica.com",
+ "comscore.com",
+ "mdotlabs.com",
+ "scorecardresearch.com",
+ "sitestat.com",
+ "voicefive.com"
+ ]
+ }
+ },
+ {
+ "Connexity": {
+ "http://www.connexity.com/": ["connexity.com", "connexity.net"]
+ }
+ },
+ {
+ "Convert Insights": {
+ "http://www.convert.com/": ["convert.com", "reedge.com"]
+ }
+ },
+ {
+ "Convertro": {
+ "http://www.convertro.com/": ["convertro.com"]
+ }
+ },
+ {
+ "Crazy Egg": {
+ "http://www.crazyegg.com/": ["cetrk.com", "crazyegg.com"]
+ }
+ },
+ {
+ "Crowd Science": {
+ "http://crowdscience.com/": ["crowdscience.com"]
+ }
+ },
+ {
+ "Cya2": {
+ "http://cya2.net/": ["cya2.net"]
+ }
+ },
+ {
+ "Dataium": {
+ "http://www.dataium.com/": ["collserve.com", "dataium.com"]
+ }
+ },
+ {
+ "Deep Intent": {
+ "https://www.deepintent.com/": ["deepintent.com"]
+ }
+ },
+ {
+ "Demandbase": {
+ "http://www.demandbase.com/": ["company-target.com", "demandbase.com"]
+ }
+ },
+ {
+ "DirectCORP": {
+ "http://www.directcorp.de/": ["ipcounter.de"]
+ }
+ },
+ {
+ "DistilNetworks": {
+ "https://www.distilnetworks.com/": ["distiltag.com"]
+ }
+ },
+ {
+ "DoubleVerify": {
+ "http://www.doubleverify.com/": ["doubleverify.com"]
+ }
+ },
+ {
+ "dwstat.com": {
+ "http://www.dwstat.cn/": ["dwstat.cn"]
+ }
+ },
+ {
+ "ECSAnalytics": {
+ "https://www.theecsinc.com/": ["ecsanalytics.com"]
+ }
+ },
+ {
+ "EFF": {
+ "https://www.eff.org/": [
+ "do-not-tracker.org",
+ "eviltracker.net",
+ "trackersimulator.org"
+ ]
+ }
+ },
+ {
+ "eProof.com": {
+ "http://www.eproof.com/": ["eproof.com"]
+ }
+ },
+ {
+ "etracker": {
+ "http://www.etracker.com/": [
+ "etracker.com",
+ "etracker.de",
+ "sedotracker.com",
+ "sedotracker.de"
+ ]
+ }
+ },
+ {
+ "Eulerian Technologies": {
+ "http://www.eulerian.com/": ["eulerian.com", "eulerian.net"]
+ }
+ },
+ {
+ "eXTReMe digital": {
+ "http://extremetracking.com/": [
+ "extreme-dm.com",
+ "extremetracking.com"
+ ]
+ }
+ },
+ {
+ "Eyeota": {
+ "http://eyeota.net/": ["eyeota.net"]
+ }
+ },
+ {
+ "Feedjit": {
+ "http://feedjit.com/": ["feedjit.com"]
+ }
+ },
+ {
+ "Flashtalking": {
+ "http://www.flashtalking.com/": [
+ "encoremetrics.com",
+ "sitecompass.com"
+ ]
+ }
+ },
+ {
+ "Footprint": {
+ "http://www.footprintlive.com/": ["footprintlive.com"]
+ }
+ },
+ {
+ "Free Online Users": {
+ "http://www.freeonlineusers.com/": ["freeonlineusers.com"]
+ }
+ },
+ {
+ "Free-PageRank.com": {
+ "http://www.free-pagerank.com/": ["free-pagerank.com"]
+ }
+ },
+ {
+ "Friends2Follow": {
+ "https://friends2follow.com/": ["antifraudjs.friends2follow.com"]
+ }
+ },
+ {
+ "Fullstory": {
+ "https://www.fullstory.com/": ["fullstory.com"],
+ "session-replay": "true"
+ }
+ },
+ {
+ "GetSiteControl": {
+ "https://getsitecontrol.com/": ["getsitecontrol.com"]
+ }
+ },
+ {
+ "GfK Group": {
+ "http://www.gfk.com/": ["daphnecm.com", "gfk.com", "gfkdaphne.com"]
+ }
+ },
+ {
+ "GitHub": {
+ "https://github.com/": ["gaug.es"]
+ }
+ },
+ {
+ "Go Daddy": {
+ "http://www.godaddy.com/": ["godaddy.com", "trafficfacts.com"]
+ }
+ },
+ {
+ "Google": {
+ "http://www.google.com/": ["google-analytics.com", "postrank.com"]
+ }
+ },
+ {
+ "GoSquared": {
+ "https://www.gosquared.com/": ["gosquared.com"]
+ }
+ },
+ {
+ "GoStats": {
+ "http://gostats.com/": ["gostats.com"]
+ }
+ },
+ {
+ "GrapheneMedia": {
+ "http://graphenemedia.in/": ["graphenedigitalanalytics.in"]
+ }
+ },
+ {
+ "GTop": {
+ "http://www.gtop.ro/": ["gtop.ro", "gtopstats.com"]
+ }
+ },
+ {
+ "Hearst": {
+ "http://www.hearst.com/": ["raasnet.com", "redaril.com"]
+ }
+ },
+ {
+ "Histats": {
+ "http://www.histats.com/": ["histats.com"]
+ }
+ },
+ {
+ "HitsLink": {
+ "http://www.hitslink.com/": ["hitslink.com"]
+ }
+ },
+ {
+ "Hit Sniffer": {
+ "http://www.hitsniffer.com/": ["hitsniffer.com"]
+ }
+ },
+ {
+ "Hotjar": {
+ "https://www.hotjar.com": ["hotjar.com"]
+ }
+ },
+ {
+ "HubSpot": {
+ "http://www.hubspot.com/": ["hs-analytics.net"]
+ }
+ },
+ {
+ "IBM": {
+ "http://www.ibm.com/": ["cmcore.com", "coremetrics.com", "ibm.com"]
+ }
+ },
+ {
+ "InboundWriter": {
+ "http://www.inboundwriter.com/": [
+ "enquisite.com",
+ "inboundwriter.com"
+ ]
+ }
+ },
+ {
+ "Infernotions": {
+ "https://infernotions.com/": ["infernotions.com"]
+ }
+ },
+ {
+ "INFOnline": {
+ "https://www.infonline.de/": ["infonline.de", "ioam.de", "ivwbox.de"]
+ }
+ },
+ {
+ "InfoStars": {
+ "http://infostars.ru/": ["hotlog.ru", "infostars.ru"]
+ }
+ },
+ {
+ "Inspectlet": {
+ "http://www.inspectlet.com/": ["inspectlet.com"]
+ }
+ },
+ {
+ "IntelligenceFocus": {
+ "http://www.intelligencefocus.com/": [
+ "domodomain.com",
+ "intelligencefocus.com"
+ ]
+ }
+ },
+ {
+ "iPerceptions": {
+ "http://www.iperceptions.com/": ["iperceptions.com"]
+ }
+ },
+ {
+ "IslayTech": {
+ "http://islay.tech": ["islay.tech"]
+ }
+ },
+ {
+ "ItIsATracker": {
+ "https://itisatracker.com/": ["itisatracker.com"],
+ "dnt": "eff"
+ }
+ },
+ {
+ "KeyMetric": {
+ "http://www.keymetric.net/": ["keymetric.net"]
+ }
+ },
+ {
+ "KISSmetrics": {
+ "http://kissmetrics.com/": ["kissmetrics.com"]
+ }
+ },
+ {
+ "Kitcode": {
+ "http://src.kitcode.net/": ["src.kitcode.net"]
+ }
+ },
+ {
+ "LeadForensics": {
+ "https://www.leadforensics.com": ["leadforensics.com"]
+ }
+ },
+ {
+ "LineZing": {
+ "http://www.linezing.com/": ["linezing.com"]
+ }
+ },
+ {
+ "LivePerson": {
+ "http://www.liveperson.net/": ["liveperson.com", "nuconomy.com"]
+ }
+ },
+ {
+ "Logdy": {
+ "http://logdy.com/": ["logdy.com"]
+ }
+ },
+ {
+ "Lotame": {
+ "http://www.lotame.com/": ["crwdcntrl.net", "lotame.com"]
+ }
+ },
+ {
+ "LuckyOrange": {
+ "https://www.luckyorange.com": ["luckyorange.com", "luckyorange.net"],
+ "session-replay": "true"
+ }
+ },
+ {
+ "Lynchpin": {
+ "http://www.lynchpin.com/": ["lynchpin.com", "lypn.com"]
+ }
+ },
+ {
+ "Lyris": {
+ "http://www.lyris.com/": ["clicktracks.com", "lyris.com"]
+ }
+ },
+ {
+ "Lytiks": {
+ "http://www.lytiks.com/": ["lytiks.com"]
+ }
+ },
+ {
+ "MarkMonitor": {
+ "https://www.markmonitor.com": ["9c9media.ca", "markmonitor.com"]
+ }
+ },
+ {
+ "Marktest": {
+ "http://www.marktest.com/": ["marktest.com", "marktest.pt"]
+ }
+ },
+ {
+ "MaxMind": {
+ "https://www.maxmind.com/en/home": ["maxmind.com", "mmapiws.com"]
+ }
+ },
+ {
+ "Médiamétrie-eStat": {
+ "http://www.mediametrie-estat.com/": [
+ "estat.com",
+ "mediametrie-estat.com"
+ ]
+ }
+ },
+ {
+ "Merkle": {
+ "https://www.merkleinc.com/": ["merkleinc.com", "rkdms.com"]
+ }
+ },
+ {
+ "Mixpanel": {
+ "https://mixpanel.com/": ["mixpanel.com", "mxpnl.com"]
+ }
+ },
+ {
+ "Mongoose Metrics": {
+ "http://www.mongoosemetrics.com/": ["mongoosemetrics.com"]
+ }
+ },
+ {
+ "Monitus": {
+ "http://www.monitus.net/": ["monitus.net"]
+ }
+ },
+ {
+ "motigo": {
+ "http://motigo.com/": ["motigo.com", "nedstatbasic.net"]
+ }
+ },
+ {
+ "Mouseflow": {
+ "http://mouseflow.com/": ["mouseflow.com"]
+ }
+ },
+ {
+ "MyPagerank.Net": {
+ "http://www.mypagerank.net/": ["mypagerank.net"]
+ }
+ },
+ {
+ "Mystighty": {
+ "http://mystighty.info/": ["mystighty.info", "sweeterge.info"]
+ }
+ },
+ {
+ "Narrative": {
+ "http://narrative.io/2/": ["narrative.io"]
+ }
+ },
+ {
+ "Net Applications": {
+ "http://www.netapplications.com/": [
+ "hitsprocessor.com",
+ "netapplications.com"
+ ]
+ }
+ },
+ {
+ "New Relic": {
+ "http://newrelic.com/": ["newrelic.com", "nr-data.net"]
+ }
+ },
+ {
+ "NewsRight": {
+ "http://www.newsright.com/": ["apnewsregistry.com"]
+ }
+ },
+ {
+ "NextSTAT": {
+ "http://www.nextstat.com/": ["nextstat.com"]
+ }
+ },
+ {
+ "Nielsen": {
+ "http://www.nielsen.com/": ["glanceguide.com", "nielsen.com"]
+ }
+ },
+ {
+ "NuDataSecurity": {
+ "https://nudatasecurity.com/": ["nudatasecurity.com"]
+ }
+ },
+ {
+ "nurago": {
+ "http://www.nurago.com/": ["nurago.com", "nurago.de", "sensic.net"]
+ }
+ },
+ {
+ "Observer": {
+ "http://observerapp.com/": ["observerapp.com"]
+ }
+ },
+ {
+ "OnAudience": {
+ "http://www.onaudience.com/": [
+ "behavioralengine.com",
+ "onaudience.com"
+ ]
+ }
+ },
+ {
+ "OneStat": {
+ "http://www.onestat.com/": ["onestat.com"]
+ }
+ },
+ {
+ "Openstat": {
+ "https://www.openstat.ru/": ["openstat.ru", "spylog.com"]
+ }
+ },
+ {
+ "Opentracker": {
+ "http://www.opentracker.net/": ["opentracker.net"]
+ }
+ },
+ {
+ "Opolen": {
+ "https://opolen.com.br": ["opolen.com.br"]
+ }
+ },
+ {
+ "Optimizely": {
+ "https://www.optimizely.com/": ["optimizely.com"]
+ }
+ },
+ {
+ "Oracle": {
+ "http://www.oracle.com/": ["eloqua.com", "maxymiser.com"]
+ }
+ },
+ {
+ "ÖWA": {
+ "http://www.oewa.at/": ["oewa.at", "oewabox.at"]
+ }
+ },
+ {
+ "Parse.ly": {
+ "http://parsely.com/": ["parsely.com"]
+ }
+ },
+ {
+ "PersianStat.com": {
+ "http://www.persianstat.com/": ["persianstat.com"]
+ }
+ },
+ {
+ "Phonalytics": {
+ "http://www.phonalytics.com/": ["phonalytics.com"]
+ }
+ },
+ {
+ "phpMyVisites": {
+ "http://www.phpmyvisites.us/": ["phpmyvisites.us"]
+ }
+ },
+ {
+ "Piwik": {
+ "http://piwik.org/": ["piwik.org"]
+ }
+ },
+ {
+ "PixAnalytics": {
+ "https://pixanalytics.com/": ["pixanalytics.com"]
+ }
+ },
+ {
+ "Poool": {
+ "http://poool.fr/": ["poool.fr"]
+ }
+ },
+ {
+ "Pronunciator": {
+ "http://www.pronunciator.com/": [
+ "pronunciator.com",
+ "visitorville.com"
+ ]
+ }
+ },
+ {
+ "Qualaroo": {
+ "http://qualaroo.com/": ["kissinsights.com", "qualaroo.com"]
+ }
+ },
+ {
+ "QuinStreet": {
+ "http://quinstreet.com/": ["thecounter.com"]
+ }
+ },
+ {
+ "Quintelligence": {
+ "http://www.quintelligence.com/": ["quintelligence.com"]
+ }
+ },
+ {
+ "RadarURL": {
+ "http://radarurl.com/": ["radarurl.com"]
+ }
+ },
+ {
+ "Research Now": {
+ "http://www.researchnow.com/": [
+ "researchnow.com",
+ "valuedopinions.co.uk"
+ ]
+ }
+ },
+ {
+ "Retail Automata": {
+ "https://retailautomata.com": ["retailautomata.com"]
+ }
+ },
+ {
+ "Revtracks": {
+ "http://revtrax.com/": ["revtrax.com"]
+ }
+ },
+ {
+ "Ringier": {
+ "http://ringier.cz/": ["ringier.cz"]
+ }
+ },
+ {
+ "Rollick": {
+ "https://gorollick.com": ["rollick.io"]
+ }
+ },
+ {
+ "Roxr": {
+ "http://roxr.net/": ["getclicky.com", "roxr.net", "staticstuff.net"]
+ }
+ },
+ {
+ "Safecount": {
+ "http://www.safecount.net/": [
+ "dl-rms.com",
+ "dlqm.net",
+ "questionmarket.com",
+ "safecount.net"
+ ]
+ }
+ },
+ {
+ "SageMetrics": {
+ "http://www.sagemetrics.com/": ["sageanalyst.net", "sagemetrics.com"]
+ }
+ },
+ {
+ "Salesintelligence": {
+ "https://salesintelligence.pl/": ["plugin.management"]
+ }
+ },
+ {
+ "SeeVolution": {
+ "https://www.seevolution.com/": ["seevolution.com", "svlu.net"]
+ }
+ },
+ {
+ "Segment.io": {
+ "https://segment.io/": ["segment.io"]
+ }
+ },
+ {
+ "SendPulse": {
+ "https://sendpulse.com/": ["sendpulse.com"]
+ }
+ },
+ {
+ "SessionCam": {
+ "https://sessioncam.com/": ["sessioncam.com"],
+ "session-replay": "true"
+ }
+ },
+ {
+ "ShinyStat": {
+ "http://www.shinystat.com/": ["shinystat.com"]
+ }
+ },
+ {
+ "Smartlook": {
+ "https://www.smartlook.com/": ["smartlook.com"],
+ "session-replay": "true"
+ }
+ },
+ {
+ "Snoobi": {
+ "http://www.snoobi.com/": ["snoobi.com"]
+ }
+ },
+ {
+ "Sourcepoint": {
+ "https://www.sourcepoint.com/": ["summerhamster.com"]
+ }
+ },
+ {
+ "Sputnik.ru": {
+ "http://sputnik.ru": ["sputnik.ru"]
+ }
+ },
+ {
+ "StackTrack": {
+ "http://stat-track.com": ["stat-track.com"]
+ }
+ },
+ {
+ "stat4u": {
+ "http://stat.4u.pl/": ["4u.pl"]
+ }
+ },
+ {
+ "StatCounter": {
+ "http://statcounter.com/": ["statcounter.com"]
+ }
+ },
+ {
+ "Statisfy": {
+ "http://statisfy.net": ["statisfy.net"]
+ }
+ },
+ {
+ "STATSIT": {
+ "http://www.statsit.com/": ["statsit.com"]
+ }
+ },
+ {
+ "Storeland": {
+ "https://storeland.ru/": ["storeland.ru"]
+ }
+ },
+ {
+ "Stratigent": {
+ "http://www.stratigent.com/": ["stratigent.com"]
+ }
+ },
+ {
+ "Tealium": {
+ "https://tealium.com": ["tealiumiq.com"]
+ }
+ },
+ {
+ "TechSolutions": {
+ "https://www.techsolutions.com.tw/": ["techsolutions.com.tw"]
+ }
+ },
+ {
+ "TENSQUARE": {
+ "http://www.tensquare.com/": ["tensquare.com"]
+ }
+ },
+ {
+ "The Heron Partnership": {
+ "http://www.heronpartners.com.au/": [
+ "heronpartners.com.au",
+ "marinsm.com"
+ ]
+ }
+ },
+ {
+ "TNS": {
+ "http://www.tnsglobal.com/": [
+ "sesamestats.com",
+ "statistik-gallup.net",
+ "tns-counter.ru",
+ "tns-cs.net",
+ "tnsglobal.com"
+ ]
+ }
+ },
+ {
+ "TrackingSoft": {
+ "http://trackingsoft.com/": ["roia.biz", "trackingsoft.com"]
+ }
+ },
+ {
+ "TrafficScore": {
+ "https://trafficscore.com/": ["trafficscore.com"]
+ }
+ },
+ {
+ "Twitter": {
+ "https://twitter.com/": ["crashlytics.com", "tweetdeck.com"]
+ }
+ },
+ {
+ "Umbel": {
+ "https://www.umbel.com/": ["umbel.com"]
+ }
+ },
+ {
+ "User Local": {
+ "http://nakanohito.jp/": ["nakanohito.jp"]
+ }
+ },
+ {
+ "V12 Data": {
+ "https://www.v12data.com/": ["v12data.com", "v12group.com"]
+ }
+ },
+ {
+ "Vertster": {
+ "http://www.vertster.com/": ["vertster.com"]
+ }
+ },
+ {
+ "VisiStat": {
+ "http://www.visistat.com/": ["sa-as.com", "visistat.com"]
+ }
+ },
+ {
+ "Visit Streamer": {
+ "http://www.visitstreamer.com/": ["visitstreamer.com"]
+ }
+ },
+ {
+ "vistrac": {
+ "http://vistrac.com/": ["vistrac.com"]
+ }
+ },
+ {
+ "ViziSense": {
+ "http://www.vizisense.com/": ["vizisense.com", "vizisense.net"]
+ }
+ },
+ {
+ "Webclicktracker": {
+ "http://www.webclicktracker.com/": ["webclicktracker.com"]
+ }
+ },
+ {
+ "Web Stats": {
+ "http://www.onlinewebstats.com/": ["onlinewebstats.com"]
+ }
+ },
+ {
+ "Web Tracking Services": {
+ "http://www.webtrackingservices.com/": [
+ "web-stat.com",
+ "webtrackingservices.com"
+ ]
+ }
+ },
+ {
+ "Web Traxs": {
+ "http://www.webtraxs.com/": ["webtraxs.com"]
+ }
+ },
+ {
+ "Webtrekk": {
+ "http://www.webtrekk.com/": ["webtrekk.com", "webtrekk.net"]
+ }
+ },
+ {
+ "Webtrends": {
+ "http://webtrends.com/": [
+ "reinvigorate.net",
+ "webtrends.com",
+ "webtrendslive.com"
+ ]
+ }
+ },
+ {
+ "White Ops": {
+ "https://www.whiteops.com/": ["adzmath.com", "whiteops.com"]
+ }
+ },
+ {
+ "whos.amung.us": {
+ "http://whos.amung.us/": ["amung.us"]
+ }
+ },
+ {
+ "Wingify": {
+ "http://wingify.com/": ["visualwebsiteoptimizer.com", "wingify.com"]
+ }
+ },
+ {
+ "Woopra": {
+ "http://www.woopra.com/": ["woopra-ns.com", "woopra.com"]
+ }
+ },
+ {
+ "WOW Analytics": {
+ "http://www.wowanalytics.co.uk/": ["wowanalytics.co.uk"]
+ }
+ },
+ {
+ "WPP": {
+ "http://www.wpp.com/": ["compete.com"]
+ }
+ },
+ {
+ "Wysistat": {
+ "http://www.wysistat.com/": ["wysistat.com"]
+ }
+ },
+ {
+ "Yahoo!": {
+ "http://www.yahoo.com/": ["analytics.yahoo.com"]
+ }
+ },
+ {
+ "YellowTracker": {
+ "http://www.yellowtracker.com/": ["yellowtracker.com"]
+ }
+ },
+ {
+ "YSance": {
+ "https://www.ysance.com/data-services/fr/home/": ["y-track.com"]
+ }
+ }
+ ],
+ "Fingerprinting": [
+ {
+ "Adabra": {
+ "https://www.adabra.com/": ["adabra.com"]
+ }
+ },
+ {
+ "Adbot": {
+ "https://adbot.tw/": ["adbot.tw"]
+ }
+ },
+ {
+ "AdGainerSolutions": {
+ "http://adgainersolutions.com/adgainer/": ["adgainersolutions.com"]
+ }
+ },
+ {
+ "AdMaven": {
+ "https://ad-maven.com/": [
+ "ad-maven.com",
+ "agreensdistra.info",
+ "boudja.com",
+ "rensovetors.info",
+ "wrethicap.info"
+ ]
+ }
+ },
+ {
+ "Admicro": {
+ "http://www.admicro.vn/": ["admicro.vn", "vcmedia.vn"]
+ }
+ },
+ {
+ "Adnium": {
+ "https://adnium.com": ["adnium.com", "montwam.top"]
+ }
+ },
+ {
+ "AdScore": {
+ "http://www.adscoremarketing.com/": ["adsco.re"]
+ }
+ },
+ {
+ "AdYouLike": {
+ "https://www.adyoulike.com/": ["pulpix.com"]
+ }
+ },
+ {
+ "AivaLabs": {
+ "https://aivalabs.com": ["aivalabs.com"]
+ }
+ },
+ {
+ "Albacross": {
+ "https://albacross.com": ["albacross.com"]
+ }
+ },
+ {
+ "AppCast": {
+ "https://appcast.io/": ["appcast.io"]
+ }
+ },
+ {
+ "AuditedMedia": {
+ "https://auditedmedia.com/": [
+ "aamapi.com",
+ "aamsitecertifier.com",
+ "auditedmedia.com"
+ ]
+ }
+ },
+ {
+ "Augur": {
+ "http://www.augur.io/": ["augur.io"]
+ }
+ },
+ {
+ "Azet": {
+ "http://mediaimpact.sk/": ["azetklik.sk", "rsz.sk"]
+ }
+ },
+ {
+ "BetssonPalantir": {
+ "https://betssonpalantir.com/": ["betssonpalantir.com"]
+ }
+ },
+ {
+ "BigClick": {
+ "http://bigclick.me/": ["bgclck.me", "xcvgdf.party"]
+ }
+ },
+ {
+ "BitMedia": {
+ "https://bitmedia.io/": ["bitmedia.io"]
+ }
+ },
+ {
+ "BlueCava": {
+ "http://www.bluecava.com/": ["bluecava.com"]
+ }
+ },
+ {
+ "BoostBox": {
+ "https://www.boostbox.com.br/": ["boostbox.com.br"]
+ }
+ },
+ {
+ "Brandcrumb": {
+ "http://www.brandcrumb.com": ["brandcrumb.com"]
+ }
+ },
+ {
+ "BreakTime": {
+ "https://www.breaktime.com.tw/": ["breaktime.com.tw"]
+ }
+ },
+ {
+ "BrightEdge": {
+ "http://www.brightedge.com/": ["b0e8.com"]
+ }
+ },
+ {
+ "C3 Metrics": {
+ "http://c3metrics.com/": [
+ "attributionmodel.com",
+ "c3metrics.com",
+ "c3tag.com"
+ ]
+ }
+ },
+ {
+ "CallSource": {
+ "https://www.callsource.com/": ["leadtrackingdata.com"]
+ }
+ },
+ {
+ "CartsGuru": {
+ "https://carts.guru/": ["carts.guru"]
+ }
+ },
+ {
+ "ClearLink": {
+ "https://www.clearlink.com/": ["clearlink.com"]
+ }
+ },
+ {
+ "Clickayab": {
+ "http://www.clickyab.com": ["clickyab.com"]
+ }
+ },
+ {
+ "ClickFrog": {
+ "https://clickfrog.ru/": [
+ "bashirian.biz",
+ "buckridge.link",
+ "franecki.net",
+ "quitzon.net",
+ "reichelcormier.bid",
+ "wisokykulas.bid"
+ ]
+ }
+ },
+ {
+ "ClickGuard": {
+ "https://www.clickguard.com/": ["clickguard.com"]
+ }
+ },
+ {
+ "Clixtell": {
+ "https://www.clixtell.com/": ["clixtell.com"]
+ }
+ },
+ {
+ "Consumable": {
+ "http://consumable.com/": ["consumable.com"]
+ }
+ },
+ {
+ "dmpxs": {
+ "http://bob.dmpxs.com": ["dmpxs.com"]
+ }
+ },
+ {
+ "ECSAnalytics": {
+ "https://www.theecsinc.com/": ["ecsanalytics.com"]
+ }
+ },
+ {
+ "EroAdvertising": {
+ "http://www.ero-advertising.com/": ["ero-advertising.com"]
+ }
+ },
+ {
+ "eyeReturn Marketing": {
+ "http://www.eyereturnmarketing.com/": [
+ "eyereturn.com",
+ "eyereturnmarketing.com"
+ ]
+ }
+ },
+ {
+ "Fanplayr": {
+ "https://fanplayr.com/": ["fanplayr.com"]
+ }
+ },
+ {
+ "Foresee": {
+ "https://www.foresee.com": ["answerscloud.com", "foresee.com"]
+ }
+ },
+ {
+ "Friends2Follow": {
+ "https://friends2follow.com/": ["antifraudjs.friends2follow.com"]
+ }
+ },
+ {
+ "FuelX": {
+ "https://fuelx.com/": ["fuel451.com", "fuelx.com"]
+ }
+ },
+ {
+ "Gleam": {
+ "https://gleam.io/": ["fraudjs.io"]
+ }
+ },
+ {
+ "GrapheneMedia": {
+ "http://graphenemedia.in/": ["graphenedigitalanalytics.in"]
+ }
+ },
+ {
+ "Gruner + Jahr": {
+ "http://www.guj.de/": ["ligatus.com"]
+ }
+ },
+ {
+ "HilltopAds": {
+ "https://hilltopads.com/": ["hilltopads.net", "shoporielder.pro"]
+ }
+ },
+ {
+ "HotelChamp": {
+ "https://www.hotelchamp.com": ["hotelchamp.com"]
+ }
+ },
+ {
+ "iMedia": {
+ "http://www.imedia.cz": ["imedia.cz"]
+ }
+ },
+ {
+ "IslayTech": {
+ "http://islay.tech": ["islay.tech"]
+ }
+ },
+ {
+ "ismatlab.com": {
+ "http://ismatlab.com": ["ismatlab.com"]
+ }
+ },
+ {
+ "Itch": {
+ "https://itch.io/": ["itch.io"]
+ }
+ },
+ {
+ "justuno": {
+ "https://www.justuno.com/": ["justuno.com"]
+ }
+ },
+ {
+ "Konduto": {
+ "http://konduto.com": ["k-analytix.com", "konduto.com"]
+ }
+ },
+ {
+ "LeadsHub": {
+ "https://ztsrv.com/": ["ztsrv.com"]
+ }
+ },
+ {
+ "lptracker": {
+ "https://lptracker.io/": ["lptracker.io"]
+ }
+ },
+ {
+ "MaxMind": {
+ "https://www.maxmind.com/en/home": ["maxmind.com", "mmapiws.com"]
+ }
+ },
+ {
+ "Mercadopago": {
+ "https://www.mercadopago.com/": ["mercadopago.com"]
+ }
+ },
+ {
+ "Mobials": {
+ "http://mobials.com": ["mobials.com"]
+ }
+ },
+ {
+ "Mystighty": {
+ "http://mystighty.info/": ["mystighty.info", "sweeterge.info"]
+ }
+ },
+ {
+ "Negishim": {
+ "http://www.negishim.org": ["negishim.org"]
+ }
+ },
+ {
+ "NuDataSecurity": {
+ "https://nudatasecurity.com/": ["nudatasecurity.com"]
+ }
+ },
+ {
+ "OneAd": {
+ "https://www.onead.com.tw/": [
+ "guoshipartners.com",
+ "onevision.com.tw"
+ ]
+ }
+ },
+ {
+ "OnlineMetrix": {
+ "http://h.online-metrix.net": ["online-metrix.net"]
+ }
+ },
+ {
+ "Opolen": {
+ "https://opolen.com.br": ["opolen.com.br"]
+ }
+ },
+ {
+ "PaymentsMB": {
+ "https://paymentsmb.com": ["paymentsmb.com"]
+ }
+ },
+ {
+ "Paypal": {
+ "https://www.paypal.com": ["simility.com"]
+ }
+ },
+ {
+ "PerimeterX": {
+ "https://www.perimeterx.com": ["perimeterx.net"]
+ }
+ },
+ {
+ "PixAnalytics": {
+ "https://pixanalytics.com/": ["pixanalytics.com"]
+ }
+ },
+ {
+ "Pixlee": {
+ "https://www.pixlee.com/": ["pixlee.com"]
+ }
+ },
+ {
+ "Poool": {
+ "http://poool.fr/": ["poool.fr"]
+ }
+ },
+ {
+ "PPCProtect": {
+ "https://ppcprotect.com": ["ppcprotect.com"]
+ }
+ },
+ {
+ "PrismApp": {
+ "https://www.prismapp.io/": ["prismapp.io"]
+ }
+ },
+ {
+ "PrometheusIntelligenceTechnology": {
+ "https://prometheusintelligencetechnology.com/": [
+ "prometheusintelligencetechnology.com"
+ ]
+ }
+ },
+ {
+ "Provers": {
+ "http://provers.pro": ["provers.pro"]
+ }
+ },
+ {
+ "Psonstrentie": {
+ "http://psonstrentie.info": ["psonstrentie.info"]
+ }
+ },
+ {
+ "Rollick": {
+ "https://gorollick.com": ["rollick.io"]
+ }
+ },
+ {
+ "SAP": {
+ "https://www.sap.com": ["seewhy.com"]
+ }
+ },
+ {
+ "Selectable Media": {
+ "http://selectablemedia.com/": ["nabbr.com", "selectablemedia.com"]
+ }
+ },
+ {
+ "Semantiqo": {
+ "http://semantiqo.com/": ["semantiqo.com"]
+ }
+ },
+ {
+ "SendPulse": {
+ "https://sendpulse.com/": ["sendpulse.com"]
+ }
+ },
+ {
+ "ShaftTraffic": {
+ "https://shafttraffic.com": ["libertystmedia.com"]
+ }
+ },
+ {
+ "Shortest": {
+ "http://shorte.st/": ["shorte.st"]
+ }
+ },
+ {
+ "SiftScience": {
+ "https://sift.com/": ["siftscience.com"]
+ }
+ },
+ {
+ "Signifyd": {
+ "https://www.signifyd.com/": ["signifyd.com"]
+ }
+ },
+ {
+ "Smi": {
+ "http://24smi.net": ["24smi.net"]
+ }
+ },
+ {
+ "Socital": {
+ "https://www.socital.com": ["socital.com"]
+ }
+ },
+ {
+ "Storeland": {
+ "https://storeland.ru/": ["storeland.ru"]
+ }
+ },
+ {
+ "Stripe": {
+ "https://stripe.com": ["stripe.network"]
+ }
+ },
+ {
+ "TechSolutions": {
+ "https://www.techsolutions.com.tw/": ["techsolutions.com.tw"]
+ }
+ },
+ {
+ "tongdun.cn": {
+ "https://www.tongdun.cn/?lan=EN": ["fraudmetrix.cn", "tongdun.net"]
+ }
+ },
+ {
+ "Upland": {
+ "https://uplandsoftware.com/": ["leadlander.com", "sf14g.com"]
+ }
+ },
+ {
+ "Vendemore": {
+ "https://vendemore.com/": ["vendemore.com"]
+ }
+ },
+ {
+ "VerticalHealth": {
+ "https://www.verticalhealth.com/": ["verticalhealth.net"]
+ }
+ },
+ {
+ "Webmecanik": {
+ "https://www.webmecanik.com/": ["webmecanik.com"]
+ }
+ },
+ {
+ "WideOrbit": {
+ "https://www.wideorbit.com/": ["dep-x.com"]
+ }
+ },
+ {
+ "YSance": {
+ "https://www.ysance.com/data-services/fr/home/": ["y-track.com"]
+ }
+ },
+ {
+ "ZafulAffiliate": {
+ "https://affiliate.zaful.com/": [
+ "affasi.com",
+ "gw-ec.com",
+ "zaful.com"
+ ]
+ }
+ },
+ {
+ "Zefir": {
+ "https://ze-fir.com/": ["ze-fir.com"]
+ }
+ }
+ ],
+ "Social": [
+ {
+ "AddThis": {
+ "http://www.addthis.com/": [
+ "addthis.com",
+ "addthiscdn.com",
+ "addthisedge.com",
+ "clearspring.com",
+ "connectedads.net",
+ "xgraph.com",
+ "xgraph.net"
+ ]
+ }
+ },
+ {
+ "Causes": {
+ "http://www.causes.com/": ["causes.com"]
+ }
+ },
+ {
+ "Digg": {
+ "http://digg.com/": ["digg.com"]
+ }
+ },
+ {
+ "Facebook": {
+ "http://www.facebook.com/": [
+ "apps.fbsbx.com",
+ "atdmt.com",
+ "facebook.com",
+ "facebook.de",
+ "facebook.fr",
+ "facebook.net",
+ "fb.com",
+ "fbsbx.com",
+ "friendfeed.com"
+ ]
+ }
+ },
+ {
+ "Google": {
+ "http://www.google.com/": [
+ "developers.google.com",
+ "gmail.com",
+ "googlemail.com",
+ "inbox.google.com",
+ "mail.google.com",
+ "orkut.com",
+ "plus.google.com",
+ "plusone.google.com",
+ "smartlock.google.com",
+ "voice.google.com",
+ "wave.google.com"
+ ]
+ }
+ },
+ {
+ "LinkedIn": {
+ "http://www.linkedin.com/": ["licdn.com", "linkedin.com"]
+ }
+ },
+ {
+ "Lockerz": {
+ "http://lockerz.com/": ["lockerz.com"]
+ }
+ },
+ {
+ "Mail.Ru": {
+ "http://mail.ru/": ["list.ru", "mail.ru"]
+ }
+ },
+ {
+ "Meebo": {
+ "https://www.meebo.com/": ["meebo.com", "meebocdn.net"]
+ }
+ },
+ {
+ "Papaya": {
+ "http://papayamobile.com/": ["papayamobile.com"]
+ }
+ },
+ {
+ "reddit": {
+ "http://www.reddit.com/": ["reddit.com"]
+ }
+ },
+ {
+ "Shareaholic": {
+ "http://www.shareaholic.com/": ["shareaholic.com"]
+ }
+ },
+ {
+ "ShareThis": {
+ "http://sharethis.com/": ["sharethis.com"]
+ }
+ },
+ {
+ "StumbleUpon": {
+ "http://www.stumbleupon.com/": ["stumble-upon.com", "stumbleupon.com"]
+ }
+ },
+ {
+ "Twitter": {
+ "https://twitter.com/": ["twimg.com", "twitter.com", "twitter.jp"]
+ }
+ },
+ {
+ "VKontakte": {
+ "http://vk.com/": ["userapi.com", "vk.com", "vkontakte.ru"]
+ }
+ },
+ {
+ "Yahoo!": {
+ "http://www.yahoo.com/": [
+ "address.yahoo.com",
+ "alerts.yahoo.com",
+ "avatars.yahoo.com",
+ "buzz.yahoo.com",
+ "calendar.yahoo.com",
+ "edit.yahoo.com",
+ "legalredirect.yahoo.com",
+ "login.yahoo.com",
+ "mail.yahoo.com",
+ "my.yahoo.com",
+ "mybloglog.com",
+ "notepad.yahoo.com",
+ "pulse.yahoo.com",
+ "rocketmail.com",
+ "webmessenger.yahoo.com",
+ "ymail.com"
+ ]
+ }
+ }
+ ],
+ "Cryptomining": [
+ {
+ "a.js": {
+ "http://zymerget.bid": [
+ "alflying.date",
+ "alflying.win",
+ "anybest.site",
+ "flightsy.bid",
+ "flightsy.win",
+ "flightzy.bid",
+ "flightzy.date",
+ "flightzy.win",
+ "zymerget.bid",
+ "zymerget.faith"
+ ],
+ "performance": "true"
+ }
+ },
+ {
+ "CashBeet": {
+ "http://cashbeet.com": ["cashbeet.com", "serv1swork.com"]
+ }
+ },
+ {
+ "CoinHive": {
+ "https://coinhive.com": [
+ "ad-miner.com",
+ "authedmine.com",
+ "bmst.pw",
+ "cnhv.co",
+ "coin-hive.com",
+ "coinhive.com",
+ "wsservices.org"
+ ],
+ "performance": "true"
+ }
+ },
+ {
+ "CoinPot": {
+ "http://coinpot.co": ["coinpot.co"],
+ "performance": "true"
+ }
+ },
+ {
+ "CryptoLoot": {
+ "https://crypto-loot.com": [
+ "cryptaloot.pro",
+ "crypto-loot.com",
+ "cryptolootminer.com",
+ "flashx.pw",
+ "gitgrub.pro",
+ "reauthenticator.com",
+ "statdynamic.com",
+ "webmine.pro"
+ ],
+ "performance": "true"
+ }
+ },
+ {
+ "CryptoWebMiner": {
+ "https://www.crypto-webminer.com": [
+ "bitcoin-pay.eu",
+ "crypto-webminer.com",
+ "ethpocket.de",
+ "ethtrader.de"
+ ]
+ }
+ },
+ {
+ "Gridcash": {
+ "https://www.gridcash.net/": ["adless.io", "gridcash.net"],
+ "performance": "true"
+ }
+ },
+ {
+ "JSE": {
+ "http://jsecoin.com": [
+ "freecontent.bid",
+ "freecontent.date",
+ "freecontent.stream",
+ "hashing.win",
+ "hostingcloud.racing",
+ "hostingcloud.science",
+ "jsecoin.com"
+ ],
+ "performance": "true"
+ }
+ },
+ {
+ "MinerAlt": {
+ "http://mineralt.io": [
+ "1q2w3.website",
+ "analytics.blue",
+ "aster18cdn.nl",
+ "belicimo.pw",
+ "besstahete.info",
+ "dinorslick.icu",
+ "feesocrald.com",
+ "gramombird.com",
+ "istlandoll.com",
+ "mepirtedic.com",
+ "mineralt.io",
+ "pampopholf.com",
+ "tercabilis.info",
+ "tulip18.com",
+ "vidzi.tv",
+ "yololike.space"
+ ],
+ "performance": "true"
+ }
+ },
+ {
+ "Minescripts": {
+ "http://minescripts.info": ["minescripts.info", "sslverify.info"],
+ "performance": "true"
+ }
+ },
+ {
+ "MineXMR": {
+ "http://minexmr.stream": ["minexmr.stream"],
+ "performance": "true"
+ }
+ },
+ {
+ "NeroHut": {
+ "https://nerohut.com": ["nerohut.com", "nhsrv.cf"],
+ "performance": "true"
+ }
+ },
+ {
+ "Service4refresh": {
+ "https://service4refresh.info": ["service4refresh.info"]
+ }
+ },
+ {
+ "SpareChange": {
+ "http://sparechange.io": ["sparechange.io"],
+ "performance": "true"
+ }
+ },
+ {
+ "SwiftMining": {
+ "https://swiftmining.win/": ["swiftmining.win"]
+ }
+ },
+ {
+ "Webmine": {
+ "https://webmine.cz/": ["authedwebmine.cz", "webmine.cz"]
+ }
+ },
+ {
+ "WebminePool": {
+ "http://webminepool.com": ["webminepool.com"],
+ "performance": "true"
+ }
+ },
+ {
+ "Webmining": {
+ "https://webmining.co/": ["webmining.co"]
+ }
+ }
+ ]
+ }
}
diff --git a/mobile/android/android-components/components/browser/engine-system/src/main/res/raw/domain_safelist.json b/mobile/android/android-components/components/browser/engine-system/src/main/res/raw/domain_safelist.json
index a2c80176b6..862e7db0de 100644
--- a/mobile/android/android-components/components/browser/engine-system/src/main/res/raw/domain_safelist.json
+++ b/mobile/android/android-components/components/browser/engine-system/src/main/res/raw/domain_safelist.json
@@ -1,12347 +1,6558 @@
{
- "2leep.com": {
- "properties": [
- "2leep.com"
- ],
- "resources": [
- "2leep.com"
- ]
- },
- "33Across": {
- "properties": [
- "33across.com",
- "tynt.com"
- ],
- "resources": [
- "33across.com",
- "tynt.com"
- ]
- },
- "365Media": {
- "properties": [
- "aggregateintelligence.com"
- ],
- "resources": [
- "365media.com",
- "aggregateintelligence.com"
- ]
- },
- "4INFO": {
- "properties": [
- "4info.com",
- "adhaven.com"
- ],
- "resources": [
- "4info.com",
- "adhaven.com"
- ]
- },
- "4mads": {
- "properties": [
- "4mads.com"
- ],
- "resources": [
- "4mads.com"
- ]
- },
- "63 Squares": {
- "properties": [
- "63labs.com"
- ],
- "resources": [
- "63labs.com",
- "63squares.com",
- "i-stats.com"
- ]
- },
- "Abax Interactive": {
- "properties": [
- "abaxinteractive.com"
- ],
- "resources": [
- "abaxinteractive.com"
- ]
- },
- "Accelia": {
- "properties": [
- "accelia.net",
- "durasite.net"
- ],
- "resources": [
- "accelia.net",
- "durasite.net"
- ]
- },
- "Accordant Media": {
- "properties": [
- "accordantmedia.com"
- ],
- "resources": [
- "accordantmedia.com"
- ]
- },
- "Acquisio": {
- "properties": [
- "acquisio.com",
- "clickequations.net"
- ],
- "resources": [
- "acquisio.com",
- "clickequations.net"
- ]
- },
- "Actisens": {
- "properties": [
- "actisens.com",
- "gestionpub.com"
- ],
- "resources": [
- "actisens.com",
- "gestionpub.com"
- ]
- },
- "ActiveConversion": {
- "properties": [
- "activeconversion.com",
- "activemeter.com"
- ],
- "resources": [
- "activeconversion.com",
- "activemeter.com"
- ]
- },
- "ActivEngage": {
- "properties": [
- "activengage.com"
- ],
- "resources": [
- "activengage.com"
- ]
- },
- "Act-On": {
- "properties": [
- "act-on.com",
- "actonsoftware.com"
- ],
- "resources": [
- "act-on.com",
- "actonsoftware.com"
- ]
- },
- "Acuity": {
- "properties": [
- "acuity.com",
- "acuityads.com",
- "acuityplatform.com"
- ],
- "resources": [
- "acuity.com",
- "acuityads.com",
- "acuityplatform.com"
- ]
- },
- "Acxiom": {
- "properties": [
- "acxiom.com",
- "mm7.net"
- ],
- "resources": [
- "acxiom.com",
- "acxiomapac.com",
- "mm7.net",
- "pippio.com"
- ]
- },
- "AD2ONE": {
- "properties": [
- "ad2onegroup.com"
- ],
- "resources": [
- "ad2onegroup.com"
- ]
- },
- "Ad4Game": {
- "properties": [
- "ad4game.com"
- ],
- "resources": [
- "ad4game.com"
- ]
- },
- "ad6media": {
- "properties": [
- "ad6media.fr"
- ],
- "resources": [
- "ad6media.fr"
- ]
- },
- "Adabra": {
- "properties": [
- "adabra.com"
- ],
- "resources": [
- "adabra.com"
- ]
- },
- "Adality": {
- "properties": [
- "adality.de"
- ],
- "resources": [
- "adality.de",
- "adrtx.net"
- ]
- },
- "AdaptiveAds": {
- "properties": [
- "adaptiveads.com"
- ],
- "resources": [
- "adaptiveads.com"
- ]
- },
- "Adaptly": {
- "properties": [
- "adaptly.com"
- ],
- "resources": [
- "adaptly.com"
- ]
- },
- "Adap.tv": {
- "properties": [
- "adap.tv"
- ],
- "resources": [
- "adap.tv"
- ]
- },
- "Adara Media": {
- "properties": [
- "adaramedia.com",
- "opinmind.com",
- "yieldoptimizer.com"
- ],
- "resources": [
- "adaramedia.com",
- "opinmind.com",
- "yieldoptimizer.com"
- ]
- },
- "Adatus": {
- "properties": [
- "adatus.com"
- ],
- "resources": [
- "adatus.com"
- ]
- },
- "Adbot": {
- "properties": [
- "adbot.tw"
- ],
- "resources": [
- "adbot.tw"
- ]
- },
- "Adbrain": {
- "properties": [
- "adbrain.com"
- ],
- "resources": [
- "adbrain.com",
- "adbrn.com"
- ]
- },
- "adBrite": {
- "properties": [
- "adbrite.com"
- ],
- "resources": [
- "adbrite.com"
- ]
- },
- "Adbroker.de": {
- "properties": [
- "adbroker.de"
- ],
- "resources": [
- "adbroker.de"
- ]
- },
- "Adchemy": {
- "properties": [
- "adchemy.com"
- ],
- "resources": [
- "adchemy.com"
- ]
- },
- "AdCirrus": {
- "properties": [
- "adcirrus.com"
- ],
- "resources": [
- "adcirrus.com"
- ]
- },
- "Ad Decisive": {
- "properties": [
- "a2dfp.net",
- "addecisive.com"
- ],
- "resources": [
- "a2dfp.net",
- "addecisive.com"
- ]
- },
- "AddFreeStats": {
- "properties": [
- "3dstats.com",
- "addfreestats.com"
- ],
- "resources": [
- "3dstats.com",
- "addfreestats.com"
- ]
- },
- "addGloo": {
- "properties": [
- "addgloo.com"
- ],
- "resources": [
- "addgloo.com"
- ]
- },
- "AddThis": {
- "properties": [
- "addthis.com"
- ],
- "resources": [
- "addthis.com",
- "addthiscdn.com",
- "addthisedge.com",
- "clearspring.com",
- "connectedads.net",
- "xgraph.com",
- "xgraph.net"
- ]
- },
- "Addvantage Media": {
- "properties": [
- "addvantagemedia.com"
- ],
- "resources": [
- "addvantagemedia.com"
- ]
- },
- "Ad Dynamo": {
- "properties": [
- "addynamo.com"
- ],
- "resources": [
- "addynamo.com",
- "addynamo.net"
- ]
- },
- "Adelphic": {
- "properties": [
- "adelphic.com"
- ],
- "resources": [
- "adelphic.com",
- "ipredictive.com"
- ]
- },
- "AdEngage": {
- "properties": [
- "adengage.com"
- ],
- "resources": [
- "adengage.com"
- ]
- },
- "AD Europe": {
- "properties": [
- "adeurope.com"
- ],
- "resources": [
- "adeurope.com"
- ]
- },
- "AdExtent": {
- "properties": [
- "adextent.com"
- ],
- "resources": [
- "adextent.com"
- ]
- },
- "AdF.ly": {
- "properties": [
- "adf.ly"
- ],
- "resources": [
- "adf.ly"
- ]
- },
- "Adfonic": {
- "properties": [
- "adfonic.com"
- ],
- "resources": [
- "adfonic.com"
- ]
- },
- "Adforge": {
- "properties": [
- "adforgeinc.com"
- ],
- "resources": [
- "adforgeinc.com"
- ]
- },
- "Adform": {
- "properties": [
- "adform.com"
- ],
- "resources": [
- "adform.com",
- "adform.net",
- "adformdsp.net"
- ]
- },
- "AdFox": {
- "properties": [
- "adfox.ru"
- ],
- "resources": [
- "adfox.ru"
- ]
- },
- "AdFrontiers": {
- "properties": [
- "adfrontiers.com"
- ],
- "resources": [
- "adfrontiers.com"
- ]
- },
- "Adfunky": {
- "properties": [
- "adfunky.com",
- "adfunkyserver.com"
- ],
- "resources": [
- "adfunky.com",
- "adfunkyserver.com"
- ]
- },
- "Adfusion": {
- "properties": [
- "adfusion.com"
- ],
- "resources": [
- "adfusion.com"
- ]
- },
- "AdGainerSolutions": {
- "properties": [
- "adgainersolutions.com"
- ],
- "resources": [
- "adgainersolutions.com"
- ]
- },
- "AdGent Digital": {
- "properties": [
- "adgentdigital.com"
- ],
- "resources": [
- "adgentdigital.com",
- "shorttailmedia.com"
- ]
- },
- "AdGibbon": {
- "properties": [
- "adgibbon.com"
- ],
- "resources": [
- "adgibbon.com"
- ]
- },
- "Adglare": {
- "properties": [
- "adglare.com"
- ],
- "resources": [
- "adglare.com",
- "adglare.net"
- ]
- },
- "adhood": {
- "properties": [
- "adhood.com"
- ],
- "resources": [
- "adhood.com"
- ]
- },
- "Adiant": {
- "properties": [
- "adblade.com",
- "adiant.com"
- ],
- "resources": [
- "adblade.com",
- "adiant.com"
- ]
- },
- "AdInsight": {
- "properties": [
- "responsetap.com"
- ],
- "resources": [
- "adinsight.com",
- "adinsight.eu",
- "responsetap.com"
- ]
- },
- "AdIQuity": {
- "properties": [
- "adiquity.com"
- ],
- "resources": [
- "adiquity.com"
- ]
- },
- "ADITION": {
- "properties": [
- "adition.com"
- ],
- "resources": [
- "adition.com"
- ]
- },
- "AdJug": {
- "properties": [
- "adjug.com"
- ],
- "resources": [
- "adjug.com"
- ]
- },
- "AdJuggler": {
- "properties": [
- "adjuggler.com",
- "adjuggler.net"
- ],
- "resources": [
- "adjuggler.com",
- "adjuggler.net"
- ]
- },
- "Adjust": {
- "properties": [
- "adjust.com"
- ],
- "resources": [
- "adjust.com"
- ]
- },
- "AdKeeper": {
- "properties": [
- "keep.com"
- ],
- "resources": [
- "adkeeper.com",
- "akncdn.com",
- "keep.com"
- ]
- },
- "AdKernel": {
- "properties": [
- "adkernel.com"
- ],
- "resources": [
- "adkernel.com"
- ]
- },
- "Ad Knife": {
- "properties": [
- "adknife.com"
- ],
- "resources": [
- "adknife.com"
- ]
- },
- "Adknowledge": {
- "properties": [
- "adknowledge.com",
- "adparlor.com",
- "bidsystem.com",
- "cubics.com",
- "lookery.com"
- ],
- "resources": [
- "adknowledge.com",
- "adparlor.com",
- "bidsystem.com",
- "cubics.com",
- "lookery.com"
- ]
- },
- "AdLantis": {
- "properties": [
- "adimg.net",
- "adlantis.jp",
- "www.adlantis.jp"
- ],
- "resources": [
- "adimg.net",
- "adlantis.jp",
- "www.adlantis.jp"
- ]
- },
- "AdLeave": {
- "properties": [
- "adleave.com"
- ],
- "resources": [
- "adleave.com"
- ]
- },
- "Adlibrium": {
- "properties": [
- "adlibrium.com"
- ],
- "resources": [
- "adlibrium.com"
- ]
- },
- "Adloox": {
- "properties": [
- "adloox.com"
- ],
- "resources": [
- "adloox.com",
- "adlooxtracking.com"
- ]
- },
- "Adlucent": {
- "properties": [
- "adlucent.com"
- ],
- "resources": [
- "adlucent.com"
- ]
- },
- "Ad Magnet": {
- "properties": [
- "admagnet.com",
- "admagnet.net"
- ],
- "resources": [
- "admagnet.com",
- "admagnet.net"
- ]
- },
- "Admarketplace": {
- "properties": [
- "admarketplace.com"
- ],
- "resources": [
- "admarketplace.com",
- "admarketplace.net",
- "ampxchange.com"
- ]
- },
- "AdMarvel": {
- "properties": [
- "admarvel.com"
- ],
- "resources": [
- "admarvel.com"
- ]
- },
- "AdMatrix": {
- "properties": [
- "admatrix.jp"
- ],
- "resources": [
- "admatrix.jp"
- ]
- },
- "AdMaven": {
- "properties": [
- "ad-maven.com"
- ],
- "resources": [
- "ad-maven.com",
- "agreensdistra.info",
- "boudja.com",
- "rensovetors.info",
- "wrethicap.info"
- ]
- },
- "AdMaximizer Network": {
- "properties": [
- "admaximizer.com"
- ],
- "resources": [
- "admaximizer.com"
- ]
- },
- "AdMedia": {
- "properties": [
- "admedia.com"
- ],
- "resources": [
- "admedia.com"
- ]
- },
- "Admeta": {
- "properties": [
- "admeta.com",
- "atemda.com"
- ],
- "resources": [
- "admeta.com",
- "atemda.com"
- ]
- },
- "Admicro": {
- "properties": [
- "admicro.vn"
- ],
- "resources": [
- "admicro.vn",
- "vcmedia.vn"
- ]
- },
- "Admixer": {
- "properties": [
- "admixer.co.kr"
- ],
- "resources": [
- "admixer.co.kr"
- ]
- },
- "Admized": {
- "properties": [
- "admized.com"
- ],
- "resources": [
- "admized.com"
- ]
- },
- "Admobile": {
- "properties": [
- "admobile.com"
- ],
- "resources": [
- "admobile.com"
- ]
- },
- "Admotion": {
- "properties": [
- "admotion.com"
- ],
- "resources": [
- "admotion.com",
- "nspmotion.com"
- ]
- },
- "Adnetik": {
- "properties": [
- "wtp101.com"
- ],
- "resources": [
- "adnetik.com",
- "wtp101.com"
- ]
- },
- "AdNetwork.net": {
- "properties": [
- "adnetwork.net"
- ],
- "resources": [
- "adnetwork.net"
- ]
- },
- "Adnium": {
- "properties": [
- "adnium.com"
- ],
- "resources": [
- "adnium.com",
- "montwam.top"
- ]
- },
- "adnologies": {
- "properties": [
- "adnologies.com",
- "heias.com"
- ],
- "resources": [
- "adnologies.com",
- "heias.com"
- ]
- },
- "Adobe": {
- "properties": [
- "adobe.com",
- "livefyre.com",
- "typekit.com"
- ],
- "resources": [
- "2o7.net",
- "adobe.com",
- "auditude.com",
- "demdex.com",
- "demdex.net",
- "dmtracker.com",
- "efrontier.com",
- "everestads.net",
- "everestjs.net",
- "everesttech.net",
- "fyre.co",
- "hitbox.com",
- "livefyre.com",
- "omniture.com",
- "omtrdc.net",
- "touchclarity.com",
- "typekit.com"
- ]
- },
- "AdOcean": {
- "properties": [
- "adocean-global.com",
- "adocean.pl"
- ],
- "resources": [
- "adocean-global.com",
- "adocean.pl"
- ]
- },
- "Adometry": {
- "properties": [
- "adometry.com"
- ],
- "resources": [
- "adometry.com",
- "dmtry.com"
- ]
- },
- "Adomik": {
- "properties": [
- "adomik.com"
- ],
- "resources": [
- "adomik.com"
- ]
- },
- "AdOnion": {
- "properties": [
- "adonion.com"
- ],
- "resources": [
- "adonion.com"
- ]
- },
- "Adorika": {
- "properties": [
- "clickotmedia.com"
- ],
- "resources": [
- "clickotmedia.com"
- ]
- },
- "Adotmob": {
- "properties": [
- "adotmob.com"
- ],
- "resources": [
- "adotmob.com"
- ]
- },
- "ADP Dealer Services": {
- "properties": [
- "cdkglobal.com"
- ],
- "resources": [
- "admission.net",
- "adpdealerservices.com",
- "cdkglobal.com",
- "cobalt.com"
- ]
- },
- "ad pepper media": {
- "properties": [
- "adpepper.com",
- "adpepper.us"
- ],
- "resources": [
- "adpepper.com",
- "adpepper.us"
- ]
- },
- "AdPerfect": {
- "properties": [
- "adperfect.com"
- ],
- "resources": [
- "adperfect.com"
- ]
- },
- "Adperium": {
- "properties": [
- "adperium.com"
- ],
- "resources": [
- "adperium.com"
- ]
- },
- "Adpersia": {
- "properties": [
- "adpersia.com"
- ],
- "resources": [
- "adpersia.com"
- ]
- },
- "adPrecision": {
- "properties": [
- "adprecision.net",
- "adprs.net"
- ],
- "resources": [
- "adprecision.net",
- "adprs.net",
- "aprecision.net"
- ]
- },
- "AdPredictive": {
- "properties": [
- "adpredictive.com"
- ],
- "resources": [
- "adpredictive.com"
- ]
- },
- "AdReactor": {
- "properties": [
- "adreactor.com"
- ],
- "resources": [
- "adreactor.com"
- ]
- },
- "AdReady": {
- "properties": [
- "digitalremedy.com"
- ],
- "resources": [
- "adready.com",
- "adreadytractions.com",
- "digitalremedy"
- ]
- },
- "AdRevolution": {
- "properties": [
- "adrevolution.com"
- ],
- "resources": [
- "adrevolution.com"
- ]
- },
- "AdRiver": {
- "properties": [
- "adriver.ru"
- ],
- "resources": [
- "adriver.ru"
- ]
- },
- "adrolays": {
- "properties": [
- "contactimpact.de"
- ],
- "resources": [
- "adrolays.com",
- "adrolays.de",
- "contactimpact.de"
- ]
- },
- "AdRoll": {
- "properties": [
- "adroll.com"
- ],
- "resources": [
- "adroll.com"
- ]
- },
- "adscale": {
- "properties": [
- "stroeer.de"
- ],
- "resources": [
- "adscale.de",
- "stroeer.de"
- ]
- },
- "Adscience": {
- "properties": [
- "adscience.nl"
- ],
- "resources": [
- "adscience.nl"
- ]
- },
- "AdScore": {
- "properties": [
- "adscoremarketing.com"
- ],
- "resources": [
- "adsco.re"
- ]
- },
- "AdServerPub": {
- "properties": [
- "adserverpub.com"
- ],
- "resources": [
- "adserverpub.com"
- ]
- },
- "AdShuffle": {
- "properties": [
- "adshuffle.com"
- ],
- "resources": [
- "adshuffle.com"
- ]
- },
- "AdSide": {
- "properties": [
- "adside.com",
- "doclix.com"
- ],
- "resources": [
- "adside.com",
- "doclix.com"
- ]
- },
- "AdSpeed": {
- "properties": [
- "adspeed.com",
- "adspeed.net"
- ],
- "resources": [
- "adspeed.com",
- "adspeed.net"
- ]
- },
- "Adsperity": {
- "properties": [
- "adsperity.com"
- ],
- "resources": [
- "adsperity.com"
- ]
- },
- "AdSpirit": {
- "properties": [
- "adspirit.com",
- "adspirit.de",
- "adspirit.net"
- ],
- "resources": [
- "adspirit.com",
- "adspirit.de",
- "adspirit.net"
- ]
- },
- "Adsrevenue.net": {
- "properties": [
- "adsrevenue.net"
- ],
- "resources": [
- "adsrevenue.net"
- ]
- },
- "AdStir": {
- "properties": [
- "ad-stir.com"
- ],
- "resources": [
- "ad-stir.com"
- ]
- },
- "AdsTours": {
- "properties": [
- "adstours.com",
- "clickintext.net"
- ],
- "resources": [
- "adstours.com",
- "clickintext.net"
- ]
- },
- "Adsty": {
- "properties": [
- "adsty.com",
- "adx1.com"
- ],
- "resources": [
- "adsty.com",
- "adx1.com"
- ]
- },
- "Adsupply": {
- "properties": [
- "4dsply.com",
- "adsupply.com"
- ],
- "resources": [
- "4dsply.com",
- "adsupply.com"
- ]
- },
- "Adswizz": {
- "properties": [
- "adswizz.com"
- ],
- "resources": [
- "adswizz.com"
- ]
- },
- "ADTECH": {
- "properties": [
- "adtech.com",
- "adtech.de",
- "adtechus.com"
- ],
- "resources": [
- "adtech.com",
- "adtech.de",
- "adtechus.com"
- ]
- },
- "Adtegrity.com": {
- "properties": [
- "adtegrity.com",
- "adtegrity.net"
- ],
- "resources": [
- "adtegrity.com",
- "adtegrity.net"
- ]
- },
- "ADTELLIGENCE": {
- "properties": [
- "adtelligence.de"
- ],
- "resources": [
- "adtelligence.de"
- ]
- },
- "Adthink": {
- "properties": [
- "adthink.com"
- ],
- "resources": [
- "adthink.com",
- "audienceinsights.net"
- ]
- },
- "AdTiger": {
- "properties": [
- "adtiger.de"
- ],
- "resources": [
- "adtiger.de"
- ]
- },
- "AdTruth": {
- "properties": [
- "adtruth.com"
- ],
- "resources": [
- "adtruth.com"
- ]
- },
- "Adult AdWorld": {
- "properties": [
- "adultadworld.com"
- ],
- "resources": [
- "adultadworld.com"
- ]
- },
- "Adultmoda": {
- "properties": [
- "adultmoda.com"
- ],
- "resources": [
- "adultmoda.com"
- ]
- },
- "Adventive": {
- "properties": [
- "adventive.com"
- ],
- "resources": [
- "adventive.com"
- ]
- },
- "Adventori": {
- "properties": [
- "adventori.com"
- ],
- "resources": [
- "adventori.com"
- ]
- },
- "Adverline": {
- "properties": [
- "adnext.fr",
- "adverline.com"
- ],
- "resources": [
- "adnext.fr",
- "adverline.com"
- ]
- },
- "Adversal.com": {
- "properties": [
- "adv-adserver.com",
- "adversal.com"
- ],
- "resources": [
- "adv-adserver.com",
- "adversal.com"
- ]
- },
- "Adverticum": {
- "properties": [
- "adsmart.com",
- "adverticum.com",
- "adverticum.net"
- ],
- "resources": [
- "adsmart.com",
- "adverticum.com",
- "adverticum.net"
- ]
- },
- "Advertise.com": {
- "properties": [
- "advertise.com"
- ],
- "resources": [
- "advertise.com"
- ]
- },
- "AdvertiseSpace": {
- "properties": [
- "advertisespace.com"
- ],
- "resources": [
- "advertisespace.com"
- ]
- },
- "Advert Stream": {
- "properties": [
- "advertstream.com"
- ],
- "resources": [
- "advertstream.com"
- ]
- },
- "Advisor Media": {
- "properties": [
- "advisormedia.cz"
- ],
- "resources": [
- "advisormedia.cz"
- ]
- },
- "Adworx": {
- "properties": [
- "adworx.at",
- "adworx.be",
- "adworx.nl"
- ],
- "resources": [
- "adworx.at",
- "adworx.be",
- "adworx.nl"
- ]
- },
- "AdXpansion": {
- "properties": [
- "adxpansion.com"
- ],
- "resources": [
- "adxpansion.com"
- ]
- },
- "Adxvalue": {
- "properties": [
- "adxvalue.com",
- "adxvalue.de"
- ],
- "resources": [
- "adxvalue.com",
- "adxvalue.de"
- ]
- },
- "adyard": {
- "properties": [
- "adyard.de"
- ],
- "resources": [
- "adyard.de"
- ]
- },
- "AdYield": {
- "properties": [
- "adyield.com"
- ],
- "resources": [
- "adxyield.com",
- "adyield.com"
- ]
- },
- "AdYouLike": {
- "properties": [
- "adyoulike.com"
- ],
- "resources": [
- "adyoulike.com",
- "omnitagjs.com",
- "pulpix.com"
- ]
- },
- "ADZ": {
- "properties": [
- "adzcentral.com"
- ],
- "resources": [
- "adzcentral.com"
- ]
- },
- "Adzerk": {
- "properties": [
- "adzerk.com"
- ],
- "resources": [
- "adzerk.com",
- "adzerk.net"
- ]
- },
- "adzly": {
- "properties": [
- "adzly.com"
- ],
- "resources": [
- "adzly.com"
- ]
- },
- "Aegis Group": {
- "properties": [
- "aemedia.com",
- "bluestreak.com",
- "dentsuaegisnetwork.com"
- ],
- "resources": [
- "aemedia.com",
- "bluestreak.com",
- "dentsuaegisnetwork.com"
- ]
- },
- "AERIFY MEDIA": {
- "properties": [
- "aerifymedia.com",
- "anonymous-media.com"
- ],
- "resources": [
- "aerifymedia.com",
- "anonymous-media.com"
- ]
- },
- "Affectv": {
- "properties": [
- "affectv.co.uk"
- ],
- "resources": [
- "affectv.co.uk"
- ]
- },
- "affilinet": {
- "properties": [
- "affili.net",
- "affilinet-inside.de"
- ],
- "resources": [
- "affili.net",
- "affilinet-inside.de",
- "banner-rotation.com",
- "successfultogether.co.uk"
- ]
- },
- "Affine": {
- "properties": [
- "affine.tv",
- "affinesystems.com"
- ],
- "resources": [
- "affine.tv",
- "affinesystems.com"
- ]
- },
- "Affinity": {
- "properties": [
- "affinity.com"
- ],
- "resources": [
- "affinity.com"
- ]
- },
- "AfterDownload": {
- "properties": [
- "afdads.com",
- "afterdownload.com"
- ],
- "resources": [
- "afdads.com",
- "afterdownload.com"
- ]
- },
- "AIData": {
- "properties": [
- "advombat.ru",
- "aidata.me"
- ],
- "resources": [
- "advombat.ru",
- "aidata.me"
- ]
- },
- "Aim4Media": {
- "properties": [
- "aim4media.com"
- ],
- "resources": [
- "aim4media.com"
- ]
- },
- "Airpush": {
- "properties": [
- "airpush.com"
- ],
- "resources": [
- "airpush.com"
- ]
- },
- "AivaLabs": {
- "properties": [
- "aivalabs.com"
- ],
- "resources": [
- "aivalabs.com"
- ]
- },
- "a.js": {
- "properties": [
- "alflying.date",
- "alflying.win",
- "anybest.site",
- "flightsy.bid",
- "flightsy.win",
- "flightzy.bid",
- "flightzy.date",
- "flightzy.win",
- "zymerget.bid",
- "zymerget.faith"
- ],
- "resources": [
- "alflying.date",
- "alflying.win",
- "anybest.site",
- "flightsy.bid",
- "flightsy.win",
- "flightzy.bid",
- "flightzy.date",
- "flightzy.win",
- "zymerget.bid",
- "zymerget.faith"
- ]
- },
- "AK": {
- "properties": [
- "aggregateknowledge.com",
- "agkn.com"
- ],
- "resources": [
- "aggregateknowledge.com",
- "agkn.com"
- ]
- },
- "Akamai": {
- "properties": [
- "akamai.com"
- ],
- "resources": [
- "abmr.net",
- "akamai.com",
- "edgesuite.net",
- "go-mpulse.net",
- "imiclk.com"
- ]
- },
- "AKQA": {
- "properties": [
- "akqa.com"
- ],
- "resources": [
- "akqa.com",
- "srtk.net"
- ]
- },
- "Albacross": {
- "properties": [
- "albacross.com"
- ],
- "resources": [
- "albacross.com"
- ]
- },
- "AllStarMediaGroup": {
- "properties": [
- "allstarmediagroup.com"
- ],
- "resources": [
- "allstarmediagroup.com"
- ]
- },
- "Aloodo": {
- "properties": [
- "aloodo.com"
- ],
- "resources": [
- "aloodo.com"
- ]
- },
- "AlterGeo": {
- "properties": [
- "altergeo.ru"
- ],
- "resources": [
- "altergeo.ru"
- ]
- },
- "Amadesa": {
- "properties": [
- "amadesa.com"
- ],
- "resources": [
- "amadesa.com"
- ]
- },
- "Amazing Counters": {
- "properties": [
- "amazingcounters.com"
- ],
- "resources": [
- "amazingcounters.com"
- ]
- },
- "Amazon.com": {
- "properties": [
- "6pm.com",
- "abebooks.co.uk",
- "abebooks.com",
- "abebooks.de",
- "abebooks.fr",
- "abebooks.it",
- "acx.com",
- "alexa.com",
- "amazon.ae",
- "amazon.ca",
- "amazon.cn",
- "amazon.co.jp",
- "amazon.co.uk",
- "amazon.com",
- "amazon.com.au",
- "amazon.com.br",
- "amazon.com.mx",
- "amazon.com.sg",
- "amazon.com.tr",
- "amazon.de",
- "amazon.es",
- "amazon.fr",
- "amazon.in",
- "amazon.it",
- "amazon.nl",
- "amazon.sa",
- "amazonaws.com",
- "amazoninspire.com",
- "assoc-amazon.com",
- "audible.co.jp",
- "audible.co.uk",
- "audible.com",
- "audible.de",
- "audible.fr",
- "audible.in",
- "audible.it",
- "bookdepository.com",
- "boxofficemojo.com",
- "brilliancepublishing.com",
- "comixology.com",
- "createspace.com",
- "dpreview.com",
- "dpreview.in",
- "eastdane.com",
- "fabric.com",
- "goodreads.com",
- "iberlibro.com",
- "imdb.com",
- "imdb.de",
- "junglee.com",
- "look.com",
- "pillpack.com",
- "shopbop.com",
- "souq.com",
- "twitch.com",
- "twitch.tv",
- "wholefoodsmarket.com",
- "withoutabox.com",
- "woot.com",
- "yoyo.com",
- "zappos.com",
- "zvab.com"
- ],
- "resources": [
- "alexa.com",
- "alexametrics.com",
- "amazon-adsystem.com",
- "amazon.ca",
- "amazon.co.jp",
- "amazon.co.uk",
- "amazon.com",
- "amazon.de",
- "amazon.es",
- "amazon.fr",
- "amazon.it",
- "amazonaws.com",
- "assoc-amazon.com",
- "cloudfront.net",
- "ssl-images-amazon.com"
- ]
- },
- "Ambient Digital": {
- "properties": [
- "adnetwork.vn",
- "ambientdigital.com.vn"
- ],
- "resources": [
- "adnetwork.vn",
- "ambientdigital.com.vn"
- ]
- },
- "Amobee": {
- "properties": [
- "amobee.com",
- "smartclip.com"
- ],
- "resources": [
- "adconion.com",
- "amgdgt.com",
- "amobee.com",
- "euroclick.com",
- "smartclip.com",
- "turn.com"
- ]
- },
- "Amplitude": {
- "properties": [
- "amplitude.com"
- ],
- "resources": [
- "amplitude.com"
- ]
- },
- "AndBeyond": {
- "properties": [
- "andbeyond.media"
- ],
- "resources": [
- "andbeyond.media"
- ]
- },
- "anormal-media.de": {
- "properties": [
- "anormal-media.de",
- "primawebtools.de"
- ],
- "resources": [
- "anormal-media.de",
- "anormal-tracker.de",
- "primawebtools.de"
- ]
- },
- "Answers.com": {
- "properties": [
- "answers.com",
- "dsply.com"
- ],
- "resources": [
- "dsply.com"
- ]
- },
- "AOL": {
- "properties": [
- "5min.com",
- "adsonar.com",
- "advertising.com",
- "aim.com",
- "aol.com",
- "aolcdn.com",
- "aoltechguru.com",
- "atwola.com",
- "autoblog.com",
- "cambio.com",
- "dailyfinance.com",
- "editions.com",
- "engadget.com",
- "games.com",
- "homesessive.com",
- "huffingtonpost.com",
- "leadback.com",
- "makers.com",
- "mandatory.com",
- "mapquest.com",
- "moviefone.com",
- "noisecreep.com",
- "patch.com",
- "pawnation.com",
- "shortcuts.com",
- "shoutcast.com",
- "spinner.com",
- "stylelist.com",
- "stylemepretty.com",
- "surphace.com",
- "tacoda.net",
- "techcrunch.com",
- "theboombox.com",
- "theboot.com",
- "userplane.com",
- "winamp.com"
- ],
- "resources": [
- "5min.com",
- "adsonar.com",
- "adtechjp.com",
- "advertising.com",
- "aim.com",
- "aol.com",
- "aolcdn.com",
- "aolcloud.net",
- "atwola.com",
- "editions.com",
- "leadback.com",
- "mapquest.com",
- "patch.com",
- "shortcuts.com",
- "shoutcast.com",
- "spinner.com",
- "surphace.com",
- "tacoda.net",
- "userplane.com",
- "vidible.tv",
- "winamp.com"
- ]
- },
- "AppCast": {
- "properties": [
- "appcast.io"
- ],
- "resources": [
- "appcast.io"
- ]
- },
- "Appenda": {
- "properties": [
- "appenda.com"
- ],
- "resources": [
- "appenda.com"
- ]
- },
- "AppFlood": {
- "properties": [
- "appflood.com"
- ],
- "resources": [
- "appflood.com"
- ]
- },
- "Appier": {
- "properties": [
- "appier.com"
- ],
- "resources": [
- "appier.com"
- ]
- },
- "Applifier": {
- "properties": [
- "applifier.com"
- ],
- "resources": [
- "applifier.com"
- ]
- },
- "Applovin": {
- "properties": [
- "applovin.com"
- ],
- "resources": [
- "applovin.com"
- ]
- },
- "AppNexus": {
- "properties": [
- "adlantic.nl",
- "adnxs.com",
- "adrdgt.com",
- "appnexus.com"
- ],
- "resources": [
- "adlantic.nl",
- "adnxs.com",
- "adrdgt.com",
- "appnexus.com"
- ]
- },
- "AppsFlyer": {
- "properties": [
- "appsflyer.com"
- ],
- "resources": [
- "appsflyer.com"
- ]
- },
- "appssavvy": {
- "properties": [
- "appssavvy.com"
- ],
- "resources": [
- "appssavvy.com"
- ]
- },
- "Arkwrights Homebrew": {
- "properties": [
- "whiskyandwines.com"
- ],
- "resources": [
- "arkwrightshomebrew.com",
- "ctasnet.com",
- "whiskyandwines.com"
- ]
- },
- "AT Internet": {
- "properties": [
- "atinternet.com",
- "xiti.com"
- ],
- "resources": [
- "at-o.net",
- "atinternet.com",
- "hit-parade.com",
- "xiti.com"
- ]
- },
- "ATN": {
- "properties": [
- "affiliatetracking.com"
- ],
- "resources": [
- "affiliatetracking.com"
- ]
- },
- "Atoomic.com": {
- "properties": [
- "atoomic.com"
- ],
- "resources": [
- "atoomic.com"
- ]
- },
- "Atrinsic": {
- "properties": [
- "atrinsic.com"
- ],
- "resources": [
- "atrinsic.com"
- ]
- },
- "AT&T": {
- "properties": [
- "att.com",
- "yp.com"
- ],
- "resources": [
- "att.com",
- "yp.com"
- ]
- },
- "Attracta": {
- "properties": [
- "attracta.com"
- ],
- "resources": [
- "attracta.com"
- ]
- },
- "Audience2Media": {
- "properties": [
- "audience2media.com"
- ],
- "resources": [
- "audience2media.com"
- ]
- },
- "Audience Ad Network": {
- "properties": [
- "audienceadnetwork.com"
- ],
- "resources": [
- "audienceadnetwork.com"
- ]
- },
- "AudienceScience": {
- "properties": [
- "audiencescience.com"
- ],
- "resources": [
- "audiencescience.com",
- "revsci.net",
- "targetingmarketplace.com",
- "wunderloop.net"
- ]
- },
- "AuditedMedia": {
- "properties": [
- "auditedmedia.com"
- ],
- "resources": [
- "aamapi.com",
- "aamsitecertifier.com",
- "auditedmedia.com"
- ]
- },
- "Augme": {
- "properties": [
- "hipcricket.com"
- ],
- "resources": [
- "augme.com",
- "hipcricket.com"
- ]
- },
- "Augur": {
- "properties": [
- "augur.io"
- ],
- "resources": [
- "augur.io"
- ]
- },
- "AUTOCENTRE.UA": {
- "properties": [
- "am.ua",
- "autocentre.ua"
- ],
- "resources": [
- "am.ua",
- "autocentre.ua"
- ]
- },
- "Automattic": {
- "properties": [
- "automattic.com",
- "gravatar.com",
- "intensedebate.com",
- "polldaddy.com"
- ],
- "resources": [
- "automattic.com",
- "gravatar.com",
- "intensedebate.com",
- "polldaddy.com",
- "pubmine.com"
- ]
- },
- "Avalanchers": {
- "properties": [
- "avalanchers.com"
- ],
- "resources": [
- "avalanchers.com"
- ]
- },
- "AvantLink": {
- "properties": [
- "avantlink.com",
- "avantmetrics.com"
- ],
- "resources": [
- "avantlink.com",
- "avmws.com"
- ]
- },
- "Avocet": {
- "properties": [
- "avocet.io"
- ],
- "resources": [
- "avocet.io"
- ]
- },
- "Avsads": {
- "properties": [
- "avsads.com"
- ],
- "resources": [
- "avsads.com"
- ]
- },
- "AWeber": {
- "properties": [
- "aweber.com"
- ],
- "resources": [
- "aweber.com"
- ]
- },
- "Awin": {
- "properties": [
- "awin.com"
- ],
- "resources": [
- "awin.com",
- "digitalwindow.com",
- "dwin1.com",
- "perfiliate.com"
- ]
- },
- "Awio": {
- "properties": [
- "awio.com",
- "w3counter.com"
- ],
- "resources": [
- "awio.com",
- "w3counter.com",
- "w3roi.com"
- ]
- },
- "Azet": {
- "properties": [
- "azet.sk",
- "mediaimpact.sk"
- ],
- "resources": [
- "azet.sk",
- "azetklik.sk",
- "mediaimpact.sk",
- "rsz.sk"
- ]
- },
- "BackBeat Media": {
- "properties": [
- "backbeatmedia.com"
- ],
- "resources": [
- "backbeatmedia.com"
- ]
- },
- "Bannerconnect": {
- "properties": [
- "bannerconnect.net"
- ],
- "resources": [
- "bannerconnect.net"
- ]
- },
- "Barilliance": {
- "properties": [
- "barilliance.com"
- ],
- "resources": [
- "barilliance.com"
- ]
- },
- "BaronsNetworks": {
- "properties": [
- "baronsoffers.com"
- ],
- "resources": [
- "baronsoffers.com"
- ]
- },
- "Batanga Network": {
- "properties": [
- "batanga.com",
- "corp.vix.com",
- "vix.com"
- ],
- "resources": [
- "batanga.com",
- "batanganetwork.com",
- "vix.com"
- ]
- },
- "Baynote": {
- "properties": [
- "baynote.com"
- ],
- "resources": [
- "baynote.com",
- "baynote.net"
- ]
- },
- "Bazaarvoice": {
- "properties": [
- "bazaarvoice.com"
- ],
- "resources": [
- "bazaarvoice.com"
- ]
- },
- "BeachFront": {
- "properties": [
- "beachfront.com"
- ],
- "resources": [
- "beachfront.com"
- ]
- },
- "Beanstock Media": {
- "properties": [
- "beanstockmedia.com"
- ],
- "resources": [
- "beanstockmedia.com"
- ]
- },
- "beencounter": {
- "properties": [
- "beencounter.com"
- ],
- "resources": [
- "beencounter.com"
- ]
- },
- "Begun": {
- "properties": [
- "begun.ru"
- ],
- "resources": [
- "begun.ru"
- ]
- },
- "belboon": {
- "properties": [
- "belboon.com"
- ],
- "resources": [
- "adbutler.de",
- "belboon.com"
- ]
- },
- "Belstat": {
- "properties": [
- "belstat.be",
- "belstat.com",
- "belstat.de",
- "belstat.fr",
- "belstat.nl"
- ],
- "resources": [
- "belstat.be",
- "belstat.com",
- "belstat.de",
- "belstat.fr",
- "belstat.nl"
- ]
- },
- "Betgenius": {
- "properties": [
- "betgenius.com",
- "connextra.com"
- ],
- "resources": [
- "betgenius.com",
- "connextra.com"
- ]
- },
- "BetssonPalantir": {
- "properties": [
- "betssonpalantir.com"
- ],
- "resources": [
- "betssonpalantir.com"
- ]
- },
- "BetweenDigital": {
- "properties": [
- "betweendigital.com"
- ],
- "resources": [
- "betweendigital.com"
- ]
- },
- "Bidfluence": {
- "properties": [
- "bidfluence.com"
- ],
- "resources": [
- "bidfluence.com"
- ]
- },
- "Bidr": {
- "properties": [
- "bidr.io"
- ],
- "resources": [
- "bidr.io"
- ]
- },
- "BidSwitch": {
- "properties": [
- "bidswitch.com"
- ],
- "resources": [
- "bidswitch.net",
- "mfadsrvr.com"
- ]
- },
- "Bidtellect": {
- "properties": [
- "bidtellect.com",
- "bttrack.com"
- ],
- "resources": [
- "bidtellect.com",
- "bttrack.com"
- ]
- },
- "BidVertiser": {
- "properties": [
- "bidvertiser.com"
- ],
- "resources": [
- "bidvertiser.com"
- ]
- },
- "BigClick": {
- "properties": [
- "bigclick.me"
- ],
- "resources": [
- "bgclck.me",
- "xcvgdf.party"
- ]
- },
- "BigDoor": {
- "properties": [
- "bigdoor.com"
- ],
- "resources": [
- "bigdoor.com",
- "onetruefan.com"
- ]
- },
- "bigmirnet": {
- "properties": [
- "bigmir.net"
- ],
- "resources": [
- "bigmir.net"
- ]
- },
- "BinLayer": {
- "properties": [
- "binlayer.com"
- ],
- "resources": [
- "binlayer.com"
- ]
- },
- "Bitcoin Plus": {
- "properties": [
- "bitcoinplus.com"
- ],
- "resources": [
- "bitcoinplus.com"
- ]
- },
- "BitMedia": {
- "properties": [
- "bitmedia.io"
- ],
- "resources": [
- "bitmedia.io"
- ]
- },
- "BittAds": {
- "properties": [
- "bittads.com"
- ],
- "resources": [
- "bittads.com"
- ]
- },
- "Bizo": {
- "properties": [
- "bizo.com",
- "bizographics.com"
- ],
- "resources": [
- "bizo.com",
- "bizographics.com"
- ]
- },
- "Black Label Ads": {
- "properties": [
- "blacklabelads.com"
- ],
- "resources": [
- "blacklabelads.com"
- ]
- },
- "BlogCatalog": {
- "properties": [
- "blogcatalog.com"
- ],
- "resources": [
- "blogcatalog.com"
- ]
- },
- "BlogCounter.com": {
- "properties": [
- "blogcounter.de"
- ],
- "resources": [
- "blogcounter.de"
- ]
- },
- "BlogFrog": {
- "properties": [
- "theblogfrog.com"
- ],
- "resources": [
- "theblogfrog.com"
- ]
- },
- "BlogHer": {
- "properties": [
- "blogher.com",
- "blogherads.com"
- ],
- "resources": [
- "blogher.com",
- "blogherads.com"
- ]
- },
- "BlogRollr": {
- "properties": [
- "blogrollr.com"
- ],
- "resources": [
- "blogrollr.com"
- ]
- },
- "BLOOM Digital Platforms": {
- "properties": [
- "adgear.com",
- "bloom-hq.com"
- ],
- "resources": [
- "adgear.com",
- "adgrx.com",
- "bloom-hq.com"
- ]
- },
- "BloomReach": {
- "properties": [
- "bloomreach.com",
- "brcdn.com"
- ],
- "resources": [
- "bloomreach.com",
- "brcdn.com",
- "brsrvr.com"
- ]
- },
- "BlueCava": {
- "properties": [
- "bluecava.com"
- ],
- "resources": [
- "bluecava.com"
- ]
- },
- "BlueKai": {
- "properties": [
- "bluekai.com",
- "tracksimple.com"
- ],
- "resources": [
- "bkrtx.com",
- "bluekai.com",
- "tracksimple.com"
- ]
- },
- "Bluemetrix": {
- "properties": [
- "bluemetrix.com",
- "bmmetrix.com"
- ],
- "resources": [
- "bluemetrix.com",
- "bmmetrix.com"
- ]
- },
- "Blu Trumpet": {
- "properties": [
- "blutrumpet.com"
- ],
- "resources": [
- "blutrumpet.com"
- ]
- },
- "Bombora": {
- "properties": [
- "bombora.com"
- ],
- "resources": [
- "ml314.com"
- ]
- },
- "Boo-Box": {
- "properties": [
- "boo-box.com"
- ],
- "resources": [
- "boo-box.com"
- ]
- },
- "BoostBox": {
- "properties": [
- "boostbox.com.br"
- ],
- "resources": [
- "boostbox.com.br"
- ]
- },
- "Bouncex": {
- "properties": [
- "bouncex.com"
- ],
- "resources": [
- "bounceexchange.com",
- "bouncex.com",
- "bouncex.net"
- ]
- },
- "Brainient": {
- "properties": [
- "brainient.com"
- ],
- "resources": [
- "brainient.com"
- ]
- },
- "Branch": {
- "properties": [
- "branch.io"
- ],
- "resources": [
- "branch.io"
- ]
- },
- "Brand Affinity Technologies": {
- "properties": [
- "brandaffinity.net"
- ],
- "resources": [
- "brandaffinity.net"
- ]
- },
- "Brandcrumb": {
- "properties": [
- "brandcrumb.com"
- ],
- "resources": [
- "brandcrumb.com"
- ]
- },
- "Brand.net": {
- "properties": [
- "brand.net"
- ],
- "resources": [
- "brand.net"
- ]
- },
- "Brandscreen": {
- "properties": [
- "brandscreen.com",
- "rtbidder.net"
- ],
- "resources": [
- "brandscreen.com",
- "rtbidder.net"
- ]
- },
- "Branica": {
- "properties": [
- "branica.com"
- ],
- "resources": [
- "branica.com"
- ]
- },
- "BreakTime": {
- "properties": [
- "breaktime.com.tw"
- ],
- "resources": [
- "breaktime.com.tw"
- ]
- },
- "Brightcove": {
- "properties": [
- "brightcove.com"
- ],
- "resources": [
- "brightcove.com"
- ]
- },
- "BrightEdge": {
- "properties": [
- "brightedge.com"
- ],
- "resources": [
- "b0e8.com",
- "brightedge.com"
- ]
- },
- "BrightRoll": {
- "properties": [
- "brightroll.com"
- ],
- "resources": [
- "brightroll.com",
- "btrll.com"
- ]
- },
- "BrightTag": {
- "properties": [
- "brighttag.com",
- "btstatic.com",
- "thebrighttag.com"
- ],
- "resources": [
- "brighttag.com",
- "btstatic.com",
- "thebrighttag.com"
- ]
- },
- "Brilig": {
- "properties": [
- "brilig.com"
- ],
- "resources": [
- "brilig.com"
- ]
- },
- "Browser-Update.org": {
- "properties": [
- "browser-update.org"
- ],
- "resources": [
- "browser-update.org"
- ]
- },
- "BTBuckets": {
- "properties": [
- "btbuckets.com"
- ],
- "resources": [
- "btbuckets.com"
- ]
- },
- "Bubblestat": {
- "properties": [
- "bubblestat.com"
- ],
- "resources": [
- "bubblestat.com"
- ]
- },
- "BuckSense": {
- "properties": [
- "bucksense.com"
- ],
- "resources": [
- "bucksense.com"
- ]
- },
- "Buffer": {
- "properties": [
- "bufferapp.com"
- ],
- "resources": [
- "bufferapp.com"
- ]
- },
- "Bunchball": {
- "properties": [
- "bunchball.com"
- ],
- "resources": [
- "bunchball.com"
- ]
- },
- "Burstly": {
- "properties": [
- "burstly.com"
- ],
- "resources": [
- "burstly.com"
- ]
- },
- "Burst Media": {
- "properties": [
- "burstbeacon.com",
- "burstdirectads.com",
- "burstmedia.com",
- "burstnet.com",
- "giantrealm.com"
- ],
- "resources": [
- "burstbeacon.com",
- "burstdirectads.com",
- "burstmedia.com",
- "burstnet.com",
- "giantrealm.com"
- ]
- },
- "BusinessOnline": {
- "properties": [
- "businessol.com"
- ],
- "resources": [
- "businessol.com"
- ]
- },
- "Button": {
- "properties": [
- "usebutton.com"
- ],
- "resources": [
- "usebutton.com"
- ]
- },
- "buySAFE": {
- "properties": [
- "buysafe.com"
- ],
- "resources": [
- "buysafe.com"
- ]
- },
- "BuySellAds": {
- "properties": [
- "beaconads.com",
- "buysellads.com"
- ],
- "resources": [
- "beaconads.com",
- "buysellads.com"
- ]
- },
- "Buysight": {
- "properties": [
- "buysight.com",
- "permuto.com",
- "pulsemgr.com"
- ],
- "resources": [
- "buysight.com",
- "permuto.com",
- "pulsemgr.com"
- ]
- },
- "BuzzFeed": {
- "properties": [
- "buzzfeed.com"
- ],
- "resources": [
- "buzzfed.com",
- "buzzfeed.com"
- ]
- },
- "BuzzParadise": {
- "properties": [
- "buzzparadise.com"
- ],
- "resources": [
- "buzzparadise.com"
- ]
- },
- "BV! MEDIA": {
- "properties": [
- "branchez-vous.com",
- "bvmedia.ca"
- ],
- "resources": [
- "branchez-vous.com",
- "bvmedia.ca",
- "networldmedia.com",
- "networldmedia.net"
- ]
- },
- "c1exchange": {
- "properties": [
- "c1exchange.com"
- ],
- "resources": [
- "c1exchange.com"
- ]
- },
- "C3 Metrics": {
- "properties": [
- "attributionmodel.com",
- "c3metrics.com",
- "c3tag.com"
- ],
- "resources": [
- "attributionmodel.com",
- "c3metrics.com",
- "c3tag.com"
- ]
- },
- "Cadreon": {
- "properties": [
- "cadreon.com"
- ],
- "resources": [
- "cadreon.com"
- ]
- },
- "CallSource": {
- "properties": [
- "callsource.com"
- ],
- "resources": [
- "leadtrackingdata.com"
- ]
- },
- "CampaignGrid": {
- "properties": [
- "campaigngrid.com"
- ],
- "resources": [
- "campaigngrid.com"
- ]
- },
- "CAPITALDATA": {
- "properties": [
- "capitaldata.fr"
- ],
- "resources": [
- "capitaldata.fr"
- ]
- },
- "Carambola": {
- "properties": [
- "carambola.com"
- ],
- "resources": [
- "carambo.la"
- ]
- },
- "Caraytech": {
- "properties": [
- "caraytech.com.ar",
- "e-planning.net",
- "www.caraytech.com.ar"
- ],
- "resources": [
- "caraytech.com.ar",
- "e-planning.net",
- "www.caraytech.com.ar"
- ]
- },
- "Cardlytics": {
- "properties": [
- "cardlytics.com"
- ],
- "resources": [
- "cardlytics.com"
- ]
- },
- "Cart.ro": {
- "properties": [
- "cart.ro"
- ],
- "resources": [
- "cart.ro",
- "statistics.ro"
- ]
- },
- "CartsGuru": {
- "properties": [
- "carts.guru"
- ],
- "resources": [
- "carts.guru"
- ]
- },
- "Casale Media": {
- "properties": [
- "casalemedia.com",
- "medianet.com"
- ],
- "resources": [
- "casalemedia.com",
- "medianet.com"
- ]
- },
- "CashBeet": {
- "properties": [
- "cashbeet.com"
- ],
- "resources": [
- "cashbeet.com",
- "serv1swork.com"
- ]
- },
- "Causes": {
- "properties": [
- "causes.com"
- ],
- "resources": [
- "causes.com"
- ]
- },
- "Cbox": {
- "properties": [
- "cbox.ws"
- ],
- "resources": [
- "cbox.ws"
- ]
- },
- "CBproADS": {
- "properties": [
- "cbproads.com"
- ],
- "resources": [
- "cbproads.com"
- ]
- },
- "CBS Interactive": {
- "properties": [
- "cbsinteractive.com",
- "com.com"
- ],
- "resources": [
- "cbsinteractive.com",
- "com.com"
- ]
- },
- "Cedato": {
- "properties": [
- "cedato.com"
- ],
- "resources": [
- "cedato.com"
- ]
- },
- "Cedexis": {
- "properties": [
- "cedexis.com"
- ],
- "resources": [
- "cedexis.com",
- "cedexis.net"
- ]
- },
- "Certona": {
- "properties": [
- "certona.com",
- "res-x.com"
- ],
- "resources": [
- "certona.com",
- "res-x.com"
- ]
- },
- "Chango": {
- "properties": [
- "chango.ca",
- "chango.com"
- ],
- "resources": [
- "chango.ca",
- "chango.com"
- ]
- },
- "ChannelAdvisor": {
- "properties": [
- "channeladvisor.com",
- "searchmarketing.com"
- ],
- "resources": [
- "channeladvisor.com",
- "searchmarketing.com"
- ]
- },
- "Channel Intelligence": {
- "properties": [
- "channelintelligence.com"
- ],
- "resources": [
- "channelintelligence.com"
- ]
- },
- "Chartbeat": {
- "properties": [
- "chartbeat.com",
- "chartbeat.net"
- ],
- "resources": [
- "chartbeat.com",
- "chartbeat.net"
- ]
- },
- "Chartboost": {
- "properties": [
- "chartboost.com"
- ],
- "resources": [
- "chartboost.com"
- ]
- },
- "CheckM8": {
- "properties": [
- "checkm8.com"
- ],
- "resources": [
- "checkm8.com"
- ]
- },
- "Chitika": {
- "properties": [
- "chitika.com"
- ],
- "resources": [
- "chitika.com",
- "chitika.net"
- ]
- },
- "ChoiceStream": {
- "properties": [
- "choicestream.com"
- ],
- "resources": [
- "choicestream.com"
- ]
- },
- "ClearLink": {
- "properties": [
- "clearlink.com"
- ],
- "resources": [
- "clearlink.com"
- ]
- },
- "ClearSaleing": {
- "properties": [
- "clearsaleing.com"
- ],
- "resources": [
- "clearsaleing.com",
- "csdata1.com",
- "csdata2.com",
- "csdata3.com"
- ]
- },
- "Clearsearch Media": {
- "properties": [
- "pathinteractive.com"
- ],
- "resources": [
- "clearsearchmedia.com",
- "csm-secure.com",
- "pathinteractive.com"
- ]
- },
- "ClearSight Interactive": {
- "properties": [
- "clearsightinteractive.com",
- "csi-tracking.com"
- ],
- "resources": [
- "clearsightinteractive.com",
- "csi-tracking.com"
- ]
- },
- "ClickAider": {
- "properties": [
- "clickaider.com"
- ],
- "resources": [
- "clickaider.com"
- ]
- },
- "Clickayab": {
- "properties": [
- "clickyab.com"
- ],
- "resources": [
- "clickyab.com"
- ]
- },
- "Clickbooth": {
- "properties": [
- "clickbooth.com"
- ],
- "resources": [
- "adtoll.com",
- "clickbooth.com"
- ]
- },
- "Clickdensity": {
- "properties": [
- "clickdensity.com"
- ],
- "resources": [
- "clickdensity.com"
- ]
- },
- "ClickDimensions": {
- "properties": [
- "clickdimensions.com"
- ],
- "resources": [
- "clickdimensions.com"
- ]
- },
- "ClickDistrict": {
- "properties": [
- "clickdistrict.com",
- "creative-serving.com"
- ],
- "resources": [
- "clickdistrict.com",
- "creative-serving.com"
- ]
- },
- "ClickFrog": {
- "properties": [
- "clickfrog.ru"
- ],
- "resources": [
- "bashirian.biz",
- "buckridge.link",
- "clickfrog.ru",
- "franecki.net",
- "quitzon.net",
- "reichelcormier.bid",
- "wisokykulas.bid"
- ]
- },
- "ClickFuel": {
- "properties": [
- "clickfuel.com",
- "myconversionlab.com"
- ],
- "resources": [
- "clickfuel.com",
- "conversiondashboard.com",
- "myconversionlab.com"
- ]
- },
- "ClickGuard": {
- "properties": [
- "clickguard.com"
- ],
- "resources": [
- "clickguard.com"
- ]
- },
- "ClickInc": {
- "properties": [
- "clickinc.com"
- ],
- "resources": [
- "clickinc.com"
- ]
- },
- "Clicksor": {
- "properties": [
- "clicksor.com",
- "clicksor.net"
- ],
- "resources": [
- "clicksor.com",
- "clicksor.net"
- ]
- },
- "ClickTale": {
- "properties": [
- "clicktale.com"
- ],
- "resources": [
- "clicktale.com",
- "clicktale.net",
- "pantherssl.com"
- ]
- },
- "Clickwinks": {
- "properties": [
- "clickwinks.com"
- ],
- "resources": [
- "clickwinks.com"
- ]
- },
- "ClicManager": {
- "properties": [
- "clicmanager.fr"
- ],
- "resources": [
- "clicmanager.fr"
- ]
- },
- "ClipSyndicate": {
- "properties": [
- "clipsyndicate.com"
- ],
- "resources": [
- "clipsyndicate.com"
- ]
- },
- "ClixMetrix": {
- "properties": [
- "clixmetrix.com"
- ],
- "resources": [
- "clixmetrix.com"
- ]
- },
- "Clixpy": {
- "properties": [
- "clixpy.com"
- ],
- "resources": [
- "clixpy.com"
- ]
- },
- "Clixtell": {
- "properties": [
- "clixtell.com"
- ],
- "resources": [
- "clixtell.com"
- ]
- },
- "Clove Network": {
- "properties": [
- "clovenetwork.com"
- ],
- "resources": [
- "clovenetwork.com"
- ]
- },
- "ClustrMaps": {
- "properties": [
- "clustrmaps.com"
- ],
- "resources": [
- "clustrmaps.com"
- ]
- },
- "CNZZ": {
- "properties": [
- "cnzz.com"
- ],
- "resources": [
- "cnzz.com"
- ]
- },
- "Cognitive Match": {
- "properties": [
- "cmads.com.tw",
- "cmadsasia.com",
- "cmadseu.com",
- "cmmeglobal.com",
- "cognitivematch.com"
- ],
- "resources": [
- "cmads.com.tw",
- "cmadsasia.com",
- "cmadseu.com",
- "cmmeglobal.com",
- "cognitivematch.com"
- ]
- },
- "CoinHive": {
- "properties": [
- "authedmine.com",
- "coinhive.com"
- ],
- "resources": [
- "ad-miner.com",
- "authedmine.com",
- "bmst.pw",
- "cnhv.co",
- "coin-hive.com",
- "coinhive.com",
- "wsservices.org"
- ]
- },
- "CoinPot": {
- "properties": [
- "coinpot.co"
- ],
- "resources": [
- "coinpot.co"
- ]
- },
- "Collarity": {
- "properties": [
- "collarity.com"
- ],
- "resources": [
- "collarity.com"
- ]
- },
- "Collective": {
- "properties": [
- "collective.com"
- ],
- "resources": [
- "collective-media.net",
- "collective.com",
- "oggifinogi.com",
- "tumri.com",
- "tumri.net",
- "yt1187.net"
- ]
- },
- "Commission Junction": {
- "properties": [
- "cj.com"
- ],
- "resources": [
- "apmebf.com",
- "awltovhc.com",
- "cj.com",
- "ftjcfx.com",
- "kcdwa.com",
- "qksz.com",
- "qksz.net",
- "tqlkg.com",
- "yceml.net"
- ]
- },
- "Communicator Corp": {
- "properties": [
- "communicatorcorp.com"
- ],
- "resources": [
- "communicatorcorp.com"
- ]
- },
- "Compass Labs": {
- "properties": [
- "compasslabs.com"
- ],
- "resources": [
- "compasslabs.com"
- ]
- },
- "Complex Media": {
- "properties": [
- "collider.com",
- "complex.com",
- "complexmedianetwork.com",
- "firstwefeast.com",
- "pigeonsandplanes.com",
- "solecollector.com",
- "theridechannel.com"
- ],
- "resources": [
- "complex.com",
- "complexmedianetwork.com"
- ]
- },
- "Compuware": {
- "properties": [
- "axf8.net",
- "compuware.com",
- "dynatrace.com"
- ],
- "resources": [
- "axf8.net",
- "compuware.com",
- "dynatrace.com",
- "gomez.com"
- ]
- },
- "comScore": {
- "properties": [
- "adxpose.com",
- "comscore.com",
- "scorecardresearch.com",
- "sitestat.com",
- "voicefive.com"
- ],
- "resources": [
- "adxpose.com",
- "certifica.com",
- "comscore.com",
- "mdotlabs.com",
- "proxilinks.com",
- "proximic.com",
- "proximic.net",
- "scorecardresearch.com",
- "sitestat.com",
- "voicefive.com"
- ]
- },
- "Conduit": {
- "properties": [
- "conduit-banners.com",
- "conduit.com"
- ],
- "resources": [
- "conduit-banners.com",
- "conduit-services.com",
- "conduit.com",
- "wibiya.com"
- ]
- },
- "Congoo": {
- "properties": [
- "congoo.com"
- ],
- "resources": [
- "congoo.com"
- ]
- },
- "Connatix.com": {
- "properties": [
- "connatix.com"
- ],
- "resources": [
- "connatix.com"
- ]
- },
- "Connexity": {
- "properties": [
- "connexity.com",
- "pricegrabber.com"
- ],
- "resources": [
- "connexity.com",
- "connexity.net",
- "pricegrabber.com"
- ]
- },
- "Consilium Media": {
- "properties": [
- "consiliummedia.com"
- ],
- "resources": [
- "consiliummedia.com"
- ]
- },
- "Consumable": {
- "properties": [
- "consumable.com"
- ],
- "resources": [
- "consumable.com"
- ]
- },
- "Contact At Once!": {
- "properties": [
- "contactatonce.com"
- ],
- "resources": [
- "contactatonce.com"
- ]
- },
- "CONTAXE": {
- "properties": [
- "contaxe.com"
- ],
- "resources": [
- "contaxe.com"
- ]
- },
- "ContentABC": {
- "properties": [
- "contentabc.com"
- ],
- "resources": [
- "contentabc.com"
- ]
- },
- "CONTEXTin": {
- "properties": [
- "admailtiser.com",
- "contextin.com"
- ],
- "resources": [
- "admailtiser.com",
- "contextin.com"
- ]
- },
- "ContextuAds": {
- "properties": [
- "agencytradingdesk.net",
- "contextuads.com"
- ],
- "resources": [
- "agencytradingdesk.net",
- "contextuads.com"
- ]
- },
- "CONTEXTWEB": {
- "properties": [
- "contextweb.com"
- ],
- "resources": [
- "contextweb.com"
- ]
- },
- "ConvergeDirect": {
- "properties": [
- "convergedirect.com",
- "convergetrack.com"
- ],
- "resources": [
- "convergedirect.com",
- "convergetrack.com"
- ]
- },
- "ConversantMedia": {
- "properties": [
- "conversantmedia.com"
- ],
- "resources": [
- "adserver.com",
- "conversantmedia.com",
- "dotomi.com",
- "dtmpub.com",
- "emjcd.com",
- "fastclick.com",
- "fastclick.net",
- "greystripe.com",
- "lduhtrp.net",
- "mediaplex.com",
- "valueclick.com",
- "valueclick.net",
- "valueclickmedia.com"
- ]
- },
- "ConversionRuler": {
- "properties": [
- "conversionruler.com"
- ],
- "resources": [
- "conversionruler.com"
- ]
- },
- "Conversive": {
- "properties": [
- "conversive.nl"
- ],
- "resources": [
- "conversive.nl"
- ]
- },
- "Convert Insights": {
- "properties": [
- "convert.com",
- "reedge.com"
- ],
- "resources": [
- "convert.com",
- "reedge.com"
- ]
- },
- "Convertro": {
- "properties": [
- "convertro.com"
- ],
- "resources": [
- "convertro.com"
- ]
- },
- "Conviva": {
- "properties": [
- "conviva.com"
- ],
- "resources": [
- "conviva.com"
- ]
- },
- "CoreMotives": {
- "properties": [
- "coremotives.com"
- ],
- "resources": [
- "coremotives.com"
- ]
- },
- "Cox Digital Solutions": {
- "properties": [
- "adify.com",
- "coxdigitalsolutions.com",
- "novomotus.com"
- ],
- "resources": [
- "adify.com",
- "afy11.net",
- "coxdigitalsolutions.com",
- "novomotus.com"
- ]
- },
- "CPMStar": {
- "properties": [
- "cpmstar.com"
- ],
- "resources": [
- "cpmstar.com"
- ]
- },
- "CPX Interactive": {
- "properties": [
- "cpxadroit.com"
- ],
- "resources": [
- "adreadypixels.com",
- "cpxadroit.com",
- "cpxinteractive.com"
- ]
- },
- "Crazy Egg": {
- "properties": [
- "cetrk.com",
- "crazyegg.com"
- ],
- "resources": [
- "cetrk.com",
- "crazyegg.com"
- ]
- },
- "Creafi": {
- "properties": [
- "creafi.com"
- ],
- "resources": [
- "creafi.com"
- ]
- },
- "Crimtan": {
- "properties": [
- "crimtan.com"
- ],
- "resources": [
- "crimtan.com"
- ]
- },
- "Crisp Media": {
- "properties": [
- "crispmedia.com"
- ],
- "resources": [
- "crispmedia.com"
- ]
- },
- "Criteo": {
- "properties": [
- "criteo.com",
- "criteo.net"
- ],
- "resources": [
- "criteo.com",
- "criteo.net",
- "hlserve.com",
- "hooklogic.com",
- "storetail.io"
- ]
- },
- "Cross Pixel": {
- "properties": [
- "crosspixel.net"
- ],
- "resources": [
- "crosspixel.net",
- "crosspixelmedia.com",
- "crsspxl.com"
- ]
- },
- "Crowd Science": {
- "properties": [
- "crowdscience.com"
- ],
- "resources": [
- "crowdscience.com"
- ]
- },
- "CryptoLoot": {
- "properties": [
- "crypto-loot.com"
- ],
- "resources": [
- "cryptaloot.pro",
- "crypto-loot.com",
- "cryptolootminer.com",
- "flashx.pw",
- "gitgrub.pro",
- "reauthenticator.com",
- "statdynamic.com",
- "webmine.pro"
- ]
- },
- "CryptoWebMiner": {
- "properties": [
- "crypto-webminer.com"
- ],
- "resources": [
- "bitcoin-pay.eu",
- "crypto-webminer.com",
- "ethpocket.de",
- "ethtrader.de"
- ]
- },
- "cXense": {
- "properties": [
- "cxense.com"
- ],
- "resources": [
- "cxense.com",
- "emediate.biz",
- "emediate.com",
- "emediate.dk",
- "emediate.eu"
- ]
- },
- "Cya2": {
- "properties": [
- "cya2.net"
- ],
- "resources": [
- "cya2.net"
- ]
- },
- "Cyberplex": {
- "properties": [
- "cyberplex.com"
- ],
- "resources": [
- "cyberplex.com"
- ]
- },
- "Dada": {
- "properties": [
- "dada.eu",
- "dada.pro",
- "simply.com"
- ],
- "resources": [
- "dada.eu",
- "dada.pro",
- "simply.com"
- ]
- },
- "DailyMe": {
- "properties": [
- "dailyme.com",
- "newstogram.com"
- ],
- "resources": [
- "dailyme.com",
- "newstogram.com"
- ]
- },
- "Dataium": {
- "properties": [
- "collserve.com",
- "ihs.com"
- ],
- "resources": [
- "collserve.com",
- "dataium.com",
- "ihs.com"
- ]
- },
- "Datalogix": {
- "properties": [
- "datalogix.com",
- "nexac.com"
- ],
- "resources": [
- "datalogix.com",
- "nexac.com",
- "nextaction.net"
- ]
- },
- "DataSift": {
- "properties": [
- "datasift.com",
- "tweetmeme.com"
- ],
- "resources": [
- "datasift.com",
- "tweetmeme.com"
- ]
- },
- "DataXu": {
- "properties": [
- "dataxu.com",
- "mexad.com",
- "w55c.net"
- ],
- "resources": [
- "dataxu.com",
- "dataxu.net",
- "mexad.com",
- "w55c.net"
- ]
- },
- "Datonics": {
- "properties": [
- "datonics.com"
- ],
- "resources": [
- "datonics.com",
- "pro-market.net"
- ]
- },
- "Datran Media": {
- "properties": [
- "datranmedia.com",
- "displaymarketplace.com"
- ],
- "resources": [
- "datranmedia.com",
- "displaymarketplace.com"
- ]
- },
- "Datvantage": {
- "properties": [
- "datvantage.com"
- ],
- "resources": [
- "datvantage.com"
- ]
- },
- "DC Storm": {
- "properties": [
- "dc-storm.com",
- "stormiq.com"
- ],
- "resources": [
- "dc-storm.com",
- "stormiq.com"
- ]
- },
- "Dedicated Media": {
- "properties": [
- "dedicatedmedia.com",
- "dedicatednetworks.com"
- ],
- "resources": [
- "dedicatedmedia.com",
- "dedicatednetworks.com"
- ]
- },
- "Deep Intent": {
- "properties": [
- "deepintent.com"
- ],
- "resources": [
- "deepintent.com"
- ]
- },
- "Delivr": {
- "properties": [
- "delivr.com"
- ],
- "resources": [
- "delivr.com",
- "percentmobile.com"
- ]
- },
- "Delta Projects": {
- "properties": [
- "deltaprojects.com"
- ],
- "resources": [
- "adaction.se",
- "de17a.com",
- "deltaprojects.com",
- "deltaprojects.se"
- ]
- },
- "Demandbase": {
- "properties": [
- "demandbase.com"
- ],
- "resources": [
- "company-target.com",
- "demandbase.com"
- ]
- },
- "Demand Media": {
- "properties": [
- "leafgroup.com"
- ],
- "resources": [
- "demandmedia.com",
- "indieclick.com"
- ]
- },
- "Deutsche Post DHL": {
- "properties": [
- "dpdhl.com"
- ],
- "resources": [
- "adcloud.com",
- "adcloud.net",
- "dp-dhl.com",
- "dpdhl.com"
- ]
- },
- "Developer Media": {
- "properties": [
- "developermedia.com"
- ],
- "resources": [
- "developermedia.com",
- "lqcdn.com"
- ]
- },
- "DG": {
- "properties": [
- "dgit.com",
- "sizmek.com"
- ],
- "resources": [
- "dgit.com",
- "eyeblaster.com",
- "eyewonder.com",
- "mdadx.com",
- "serving-sys.com",
- "unicast.com"
- ]
- },
- "dianomi": {
- "properties": [
- "dianomi.com"
- ],
- "resources": [
- "dianomi.com"
- ]
- },
- "Didit": {
- "properties": [
- "didit.com"
- ],
- "resources": [
- "did-it.com",
- "didit.com"
- ]
- },
- "Digg": {
- "properties": [
- "digg.com"
- ],
- "resources": [
- "digg.com"
- ]
- },
- "DigitalAdConsortium": {
- "properties": [
- "dac.co.jp"
- ],
- "resources": [
- "impact-ad.jp"
- ]
- },
- "Digital River": {
- "properties": [
- "digitalriver.com",
- "keywordmax.com",
- "netflame.cc"
- ],
- "resources": [
- "digitalriver.com",
- "keywordmax.com",
- "netflame.cc"
- ]
- },
- "Digital Target": {
- "properties": [
- "digitaltarget.ru"
- ],
- "resources": [
- "digitaltarget.ru"
- ]
- },
- "Digitize": {
- "properties": [
- "digitize.ie"
- ],
- "resources": [
- "digitize.ie"
- ]
- },
- "DirectAdvert": {
- "properties": [
- "directadvert.ru"
- ],
- "resources": [
- "directadvert.ru"
- ]
- },
- "DirectCORP": {
- "properties": [
- "directcorp.de",
- "ipcounter.de"
- ],
- "resources": [
- "directcorp.de",
- "ipcounter.de"
- ]
- },
- "Direct Response Group": {
- "properties": [
- "directresponsegroup.com"
- ],
- "resources": [
- "directresponsegroup.com",
- "ppctracking.net"
- ]
- },
- "Directtrack": {
- "properties": [
- "directtrack.com"
- ],
- "resources": [
- "directtrack.com"
- ]
- },
- "Disqus": {
- "properties": [
- "disqus.com",
- "disqusads.com"
- ],
- "resources": [
- "disqus.com",
- "disqusads.com"
- ]
- },
- "DistilNetworks": {
- "properties": [
- "distilnetworks.com"
- ],
- "resources": [
- "distilnetworks.com",
- "distiltag.com"
- ]
- },
- "DistrictM": {
- "properties": [
- "districtm.net"
- ],
- "resources": [
- "districtm.io"
- ]
- },
- "dmpxs": {
- "properties": [
- "dmpxs.com"
- ],
- "resources": [
- "dmpxs.com"
- ]
- },
- "DoublePimp": {
- "properties": [
- "doublepimp.com"
- ],
- "resources": [
- "doublepimp.com"
- ]
- },
- "DoublePositive": {
- "properties": [
- "doublepositive.com"
- ],
- "resources": [
- "bid-tag.com",
- "doublepositive.com"
- ]
- },
- "DoubleVerify": {
- "properties": [
- "doubleverify.com"
- ],
- "resources": [
- "doubleverify.com"
- ]
- },
- "Drawbridge": {
- "properties": [
- "drawbridge.com"
- ],
- "resources": [
- "adsymptotic.com",
- "drawbrid.ge",
- "drawbridge.com"
- ]
- },
- "DS-IQ": {
- "properties": [
- "ds-iq.com"
- ],
- "resources": [
- "ds-iq.com"
- ]
- },
- "DSNR Group": {
- "properties": [
- "dsnrgroup.com",
- "dsnrmg.com",
- "traffiliate.com",
- "z5x.net"
- ],
- "resources": [
- "dsnrgroup.com",
- "dsnrmg.com",
- "traffiliate.com",
- "z5x.com",
- "z5x.net"
- ]
- },
- "dwstat.com": {
- "properties": [
- "dwstat.cn"
- ],
- "resources": [
- "dwstat.cn"
- ]
- },
- "DynAdmic": {
- "properties": [
- "dynadmic.com"
- ],
- "resources": [
- "dynadmic.com",
- "dyntrk.com"
- ]
- },
- "DynamicOxygen": {
- "properties": [
- "dynamicoxygen.com",
- "exitjunction.com"
- ],
- "resources": [
- "dynamicoxygen.com",
- "exitjunction.com"
- ]
- },
- "DynamicYield": {
- "properties": [
- "dynamicyield.com"
- ],
- "resources": [
- "dynamicyield.com"
- ]
- },
- "Earnify": {
- "properties": [
- "earnify.com"
- ],
- "resources": [
- "earnify.com"
- ]
- },
- "eBay": {
- "properties": [
- "ebay.at",
- "ebay.ba",
- "ebay.be",
- "ebay.ca",
- "ebay.ch",
- "ebay.cn",
- "ebay.co.jp",
- "ebay.co.kr",
- "ebay.co.uk",
- "ebay.com",
- "ebay.com.au",
- "ebay.com.hk",
- "ebay.com.my",
- "ebay.com.ph",
- "ebay.com.sg",
- "ebay.com.tw",
- "ebay.de",
- "ebay.es",
- "ebay.fr",
- "ebay.ie",
- "ebay.in",
- "ebay.it",
- "ebay.nl",
- "ebay.pl"
- ],
- "resources": [
- "ebay.com"
- ]
- },
- "Echo": {
- "properties": [
- "aboutecho.com",
- "haloscan.com",
- "js-kit.com"
- ],
- "resources": [
- "aboutecho.com",
- "haloscan.com",
- "js-kit.com"
- ]
- },
- "ECSAnalytics": {
- "properties": [
- "ecsanalytics.com",
- "theecsinc.com"
- ],
- "resources": [
- "ecsanalytics.com"
- ]
- },
- "EFF": {
- "properties": [
- "do-not-tracker.org",
- "eff.org",
- "eviltracker.net",
- "trackersimulator.org"
- ],
- "resources": [
- "do-not-tracker.org",
- "eff.org",
- "eviltracker.net",
- "trackersimulator.org"
- ]
- },
- "Effective Measure": {
- "properties": [
- "effectivemeasure.com",
- "effectivemeasure.net"
- ],
- "resources": [
- "effectivemeasure.com",
- "effectivemeasure.net"
- ]
- },
- "ekolay": {
- "properties": [
- "hurriyet.com.tr"
- ],
- "resources": [
- "e-kolay.net",
- "ekolay.net",
- "hurriyet.com.tr"
- ]
- },
- "Eleavers": {
- "properties": [
- "eleavers.com"
- ],
- "resources": [
- "eleavers.com"
- ]
- },
- "Emego": {
- "properties": [
- "usemax.de"
- ],
- "resources": [
- "usemax.de"
- ]
- },
- "Emerse": {
- "properties": [
- "emerse.com"
- ],
- "resources": [
- "emerse.com"
- ]
- },
- "EMX": {
- "properties": [
- "emxdigital.com"
- ],
- "resources": [
- "brealtime.com",
- "clearstream.tv",
- "emxdgt.com",
- "emxdigital.com"
- ]
- },
- "Enecto": {
- "properties": [
- "enecto.com"
- ],
- "resources": [
- "enecto.com"
- ]
- },
- "engage:BDR": {
- "properties": [
- "engagebdr.com"
- ],
- "resources": [
- "bnmla.com",
- "engagebdr.com"
- ]
- },
- "Engago Technology": {
- "properties": [
- "engago.com"
- ],
- "resources": [
- "appmetrx.com",
- "engago.com"
- ]
- },
- "Engine Network": {
- "properties": [
- "enginenetwork.com"
- ],
- "resources": [
- "enginenetwork.com"
- ]
- },
- "Ensighten": {
- "properties": [
- "ensighten.com"
- ],
- "resources": [
- "ensighten.com"
- ]
- },
- "Entireweb": {
- "properties": [
- "entireweb.com"
- ],
- "resources": [
- "entireweb.com"
- ]
- },
- "Epic Media Group": {
- "properties": [
- "epicadvertising.com",
- "epicmarketplace.com",
- "theepicmediagroup.com"
- ],
- "resources": [
- "epicadvertising.com",
- "epicmarketplace.com",
- "epicmobileads.com",
- "theepicmediagroup.com",
- "trafficmp.com"
- ]
- },
- "eProof.com": {
- "properties": [
- "eproof.com"
- ],
- "resources": [
- "eproof.com"
- ]
- },
- "Epsilon": {
- "properties": [
- "epsilon.com"
- ],
- "resources": [
- "epsilon.com"
- ]
- },
- "EQ Ads": {
- "properties": [
- "eqads.com"
- ],
- "resources": [
- "eqads.com"
- ]
- },
- "EroAdvertising": {
- "properties": [
- "ero-advertising.com"
- ],
- "resources": [
- "ero-advertising.com"
- ]
- },
- "Etarget": {
- "properties": [
- "etarget.net",
- "etargetnet.com"
- ],
- "resources": [
- "etarget.net",
- "etargetnet.com"
- ]
- },
- "Etineria": {
- "properties": [
- "adwitserver.com",
- "etineria.com"
- ],
- "resources": [
- "adwitserver.com",
- "etineria.com"
- ]
- },
- "etracker": {
- "properties": [
- "etracker.com",
- "etracker.de"
- ],
- "resources": [
- "etracker.com",
- "etracker.de",
- "sedotracker.com",
- "sedotracker.de"
- ]
- },
- "eTrigue": {
- "properties": [
- "etrigue.com"
- ],
- "resources": [
- "etrigue.com"
- ]
- },
- "Eulerian Technologies": {
- "properties": [
- "eulerian.com"
- ],
- "resources": [
- "eulerian.com",
- "eulerian.net"
- ]
- },
- "Evergage": {
- "properties": [
- "evergage.com"
- ],
- "resources": [
- "mybuys.com",
- "veruta.com"
- ]
- },
- "Everyday Health": {
- "properties": [
- "everydayhealth.com",
- "waterfrontmedia.com"
- ],
- "resources": [
- "everydayhealth.com",
- "waterfrontmedia.com"
- ]
- },
- "Evisions Marketing": {
- "properties": [
- "engineseeker.com",
- "evisionsmarketing.com"
- ],
- "resources": [
- "engineseeker.com",
- "evisionsmarketing.com"
- ]
- },
- "Evolve": {
- "properties": [
- "evolvemediacorp.com",
- "gorillanation.com"
- ],
- "resources": [
- "evolvemediacorp.com",
- "evolvemediametrics.com",
- "gorillanation.com"
- ]
- },
- "eWayDirect": {
- "properties": [
- "ewaydirect.com"
- ],
- "resources": [
- "ewaydirect.com",
- "ixs1.net"
- ]
- },
- "ewebse": {
- "properties": [
- "777seo.com",
- "ewebse.com"
- ],
- "resources": [
- "777seo.com",
- "ewebse.com"
- ]
- },
- "excitad": {
- "properties": [
- "excitad.com"
- ],
- "resources": [
- "excitad.com"
- ]
- },
- "eXelate": {
- "properties": [
- "exelate.com"
- ],
- "resources": [
- "exelate.com",
- "exelator.com"
- ]
- },
- "ExoClick": {
- "properties": [
- "exoclick.com"
- ],
- "resources": [
- "exoclick.com"
- ]
- },
- "Exosrv": {
- "properties": [
- "exosrv.com"
- ],
- "resources": [
- "exosrv.com"
- ]
- },
- "Experian": {
- "properties": [
- "experian.com"
- ],
- "resources": [
- "audienceiq.com",
- "experian.com"
- ]
- },
- "expo-MAX": {
- "properties": [
- "expo-max.com"
- ],
- "resources": [
- "expo-max.com"
- ]
- },
- "Exponential Interactive": {
- "properties": [
- "exponential.com",
- "fulltango.com"
- ],
- "resources": [
- "adotube.com",
- "exponential.com",
- "fulltango.com",
- "tribalfusion.com"
- ]
- },
- "Extension Factory": {
- "properties": [
- "extensionfactory.com"
- ],
- "resources": [
- "extensionfactory.com"
- ]
- },
- "EXTENSIONS.RU": {
- "properties": [
- "extensions.ru"
- ],
- "resources": [
- "extensions.ru"
- ]
- },
- "eXTReMe digital": {
- "properties": [
- "extremetracking.com"
- ],
- "resources": [
- "extreme-dm.com",
- "extremetracking.com"
- ]
- },
- "Eyeconomy": {
- "properties": [
- "eyeconomy.co.uk"
- ],
- "resources": [
- "eyeconomy.co.uk",
- "eyeconomy.com",
- "sublimemedia.net",
- "www.eyeconomy.co.uk"
- ]
- },
- "EyeNewton": {
- "properties": [
- "eyenewton.ru"
- ],
- "resources": [
- "eyenewton.ru"
- ]
- },
- "Eyeota": {
- "properties": [
- "eyeota.net"
- ],
- "resources": [
- "eyeota.net"
- ]
- },
- "eyeReturn Marketing": {
- "properties": [
- "eyereturnmarketing.com"
- ],
- "resources": [
- "eyereturn.com",
- "eyereturnmarketing.com"
- ]
- },
- "Eyeviewdigital": {
- "properties": [
- "eyeviewdigital.com"
- ],
- "resources": [
- "eyeviewads.com",
- "eyeviewdigital.com"
- ]
- },
- "Facebook": {
- "properties": [
- "atlassolutions.com",
- "facebook.com",
- "facebook.de",
- "facebook.fr",
- "facebook.net",
- "fb.com",
- "fb.me",
- "fbcdn.net",
- "friendfeed.com",
- "instagram.com",
- "internalfb.com",
- "messenger.com",
- "oculus.com",
- "whatsapp.com",
- "workplace.com"
- ],
- "resources": [
- "apps.fbsbx.com",
- "atdmt.com",
- "atlassolutions.com",
- "facebook.com",
- "facebook.de",
- "facebook.fr",
- "facebook.net",
- "fb.com",
- "fb.me",
- "fbcdn.net",
- "fbsbx.com",
- "friendfeed.com",
- "instagram.com",
- "messenger.com"
- ]
- },
- "Facilitate Digital": {
- "properties": [
- "adsfac.eu",
- "adsfac.net",
- "adsfac.us",
- "facilitatedigital.com"
- ],
- "resources": [
- "adsfac.eu",
- "adsfac.info",
- "adsfac.net",
- "adsfac.sg",
- "adsfac.us",
- "facilitatedigital.com"
- ]
- },
- "Fairfax Media": {
- "properties": [
- "fairfax.com.au",
- "fxj.com.au",
- "www.fxj.com.au"
- ],
- "resources": [
- "fairfax.com.au",
- "fxj.com.au",
- "www.fxj.com.au"
- ]
- },
- "faithadnet": {
- "properties": [
- "faithadnet.com"
- ],
- "resources": [
- "faithadnet.com"
- ]
- },
- "Fanplayr": {
- "properties": [
- "fanplayr.com"
- ],
- "resources": [
- "fanplayr.com"
- ]
- },
- "Fathom": {
- "properties": [
- "fathomdelivers.com",
- "fathomseo.com"
- ],
- "resources": [
- "fathomdelivers.com",
- "fathomseo.com"
- ]
- },
- "Federated Media": {
- "properties": [
- "hyfn.com",
- "lijit.com"
- ],
- "resources": [
- "federatedmedia.net",
- "fmpub.net",
- "hyfn.com",
- "lijit.com"
- ]
- },
- "Feedjit": {
- "properties": [
- "feedjit.com"
- ],
- "resources": [
- "feedjit.com"
- ]
- },
- "FetchBack": {
- "properties": [
- "fetchback.com"
- ],
- "resources": [
- "fetchback.com"
- ]
- },
- "Fiksu": {
- "properties": [
- "fiksu.com"
- ],
- "resources": [
- "fiksu.com"
- ]
- },
- "FinancialContent": {
- "properties": [
- "financialcontent.com"
- ],
- "resources": [
- "financialcontent.com"
- ]
- },
- "Fizz-Buzz Media": {
- "properties": [
- "fizzbuzzmedia.com",
- "fizzbuzzmedia.net"
- ],
- "resources": [
- "fizzbuzzmedia.com",
- "fizzbuzzmedia.net"
- ]
- },
- "Flashtalking": {
- "properties": [
- "flashtalking.com"
- ],
- "resources": [
- "encoremetrics.com",
- "flashtalking.com",
- "sitecompass.com"
- ]
- },
- "Flattr": {
- "properties": [
- "flattr.com"
- ],
- "resources": [
- "flattr.com"
- ]
- },
- "Flite": {
- "properties": [
- "flite.com",
- "widgetserver.com"
- ],
- "resources": [
- "flite.com",
- "widgetserver.com"
- ]
- },
- "Fluct": {
- "properties": [
- "adingo.jp",
- "fluct.jp"
- ],
- "resources": [
- "adingo.jp",
- "fluct.jp"
- ]
- },
- "Flytxt": {
- "properties": [
- "flytxt.com"
- ],
- "resources": [
- "flytxt.com"
- ]
- },
- "Footprint": {
- "properties": [
- "footprintlive.com"
- ],
- "resources": [
- "footprintlive.com"
- ]
- },
- "Forbes": {
- "properties": [
- "brandsideplatform.com",
- "forbes.com"
- ],
- "resources": [
- "brandsideplatform.com",
- "forbes.com"
- ]
- },
- "Foresee": {
- "properties": [
- "foresee.com"
- ],
- "resources": [
- "answerscloud.com"
- ]
- },
- "Fox One Stop Media": {
- "properties": [
- "fimserve.com",
- "foxnetworks.com",
- "foxonestop.com",
- "mobsmith.com",
- "myads.com",
- "othersonline.com"
- ],
- "resources": [
- "fimserve.com",
- "foxnetworks.com",
- "foxonestop.com",
- "mobsmith.com",
- "myads.com",
- "othersonline.com"
- ]
- },
- "FreakOut": {
- "properties": [
- "fout.jp"
- ],
- "resources": [
- "fout.jp"
- ]
- },
- "Freedom Communications": {
- "properties": [
- "freedom.com"
- ],
- "resources": [
- "freedom.com"
- ]
- },
- "Free Online Users": {
- "properties": [
- "freeonlineusers.com"
- ],
- "resources": [
- "freeonlineusers.com"
- ]
- },
- "Free-PageRank.com": {
- "properties": [
- "free-pagerank.com"
- ],
- "resources": [
- "free-pagerank.com"
- ]
- },
- "FreeWheel": {
- "properties": [
- "freewheel.tv",
- "fwmrm.net"
- ],
- "resources": [
- "freewheel.tv",
- "fwmrm.net",
- "stickyadstv.com"
- ]
- },
- "FriendFinder Networks": {
- "properties": [
- "adultfriendfinder.com",
- "ffn.com",
- "pop6.com"
- ],
- "resources": [
- "adultfriendfinder.com",
- "ffn.com",
- "pop6.com"
- ]
- },
- "Friends2Follow": {
- "properties": [
- "friends2follow.com"
- ],
- "resources": [
- "friends2follow.com"
- ]
- },
- "Frog Sex": {
- "properties": [
- "double-check.com",
- "frogsex.com"
- ],
- "resources": [
- "double-check.com",
- "frogsex.com"
- ]
- },
- "FuelX": {
- "properties": [
- "fuelx.com"
- ],
- "resources": [
- "fuel451.com"
- ]
- },
- "Fullstory": {
- "properties": [
- "fullstory.com"
- ],
- "resources": [
- "fullstory.com"
- ]
- },
- "Future Ads": {
- "properties": [
- "futureads.com",
- "resultlinks.com"
- ],
- "resources": [
- "futureads.com",
- "resultlinks.com"
- ]
- },
- "Fyber": {
- "properties": [
- "fyber.com"
- ],
- "resources": [
- "fyber.com"
- ]
- },
- "Game Advertising Online": {
- "properties": [
- "game-advertising-online.com"
- ],
- "resources": [
- "game-advertising-online.com"
- ]
- },
- "Games2win": {
- "properties": [
- "games2win.com",
- "inviziads.com"
- ],
- "resources": [
- "games2win.com",
- "inviziads.com"
- ]
- },
- "Gamned": {
- "properties": [
- "gamned.com"
- ],
- "resources": [
- "gamned.com"
- ]
- },
- "Gannett": {
- "properties": [
- "gannett.com",
- "pointroll.com"
- ],
- "resources": [
- "gannett.com",
- "pointroll.com"
- ]
- },
- "GB-World": {
- "properties": [
- "gb-world.net"
- ],
- "resources": [
- "gb-world.net"
- ]
- },
- "Gemius": {
- "properties": [
- "gemius.com",
- "gemius.pl"
- ],
- "resources": [
- "gemius.com",
- "gemius.pl"
- ]
- },
- "Genesis Media": {
- "properties": [
- "genesismedia.com"
- ],
- "resources": [
- "genesismedia.com",
- "genesismediaus.com"
- ]
- },
- "GENIEE": {
- "properties": [
- "geniee.co.jp"
- ],
- "resources": [
- "geniee.co.jp",
- "gssprt.jp"
- ]
- },
- "GENIE GROUP": {
- "properties": [
- "geniegroupltd.co.uk",
- "www.geniegroupltd.co.uk"
- ],
- "resources": [
- "geniegroupltd.co.uk",
- "www.geniegroupltd.co.uk"
- ]
- },
- "Genius.com": {
- "properties": [
- "genius.com",
- "rsvpgenius.com"
- ],
- "resources": [
- "genius.com",
- "rsvpgenius.com"
- ]
- },
- "GeoAds": {
- "properties": [
- "geoads.com"
- ],
- "resources": [
- "geoads.com"
- ]
- },
- "GetGlue": {
- "properties": [
- "elfie.com",
- "smrtlnks.com"
- ],
- "resources": [
- "getglue.com",
- "smrtlnks.com"
- ]
- },
- "GetIntent": {
- "properties": [
- "adhigh.net",
- "getintent.com"
- ],
- "resources": [
- "adhigh.net",
- "getintent.com"
- ]
- },
- "Get Satisfaction": {
- "properties": [
- "getsatisfaction.com"
- ],
- "resources": [
- "getsatisfaction.com"
- ]
- },
- "GetSiteControl": {
- "properties": [
- "getsitecontrol.com"
- ],
- "resources": [
- "getsitecontrol.com"
- ]
- },
- "GfK Group": {
- "properties": [
- "gfk.com"
- ],
- "resources": [
- "daphnecm.com",
- "gfk.com",
- "gfkdaphne.com"
- ]
- },
- "Gigya": {
- "properties": [
- "gigya.com"
- ],
- "resources": [
- "gigcount.com",
- "gigya.com"
- ]
- },
- "GISMAds": {
- "properties": [
- "gismads.jp"
- ],
- "resources": [
- "gismads.jp"
- ]
- },
- "GitHub": {
- "properties": [
- "gaug.es",
- "github.com"
- ],
- "resources": [
- "gaug.es",
- "github.com"
- ]
- },
- "Glam Media": {
- "properties": [
- "glam.com",
- "glammedia.com"
- ],
- "resources": [
- "glam.com",
- "glammedia.com"
- ]
- },
- "Gleam": {
- "properties": [
- "gleam.io"
- ],
- "resources": [
- "fraudjs.io",
- "gleam.io"
- ]
- },
- "Global Takeoff": {
- "properties": [
- "globaltakeoff.com",
- "globaltakeoff.net"
- ],
- "resources": [
- "globaltakeoff.com",
- "globaltakeoff.net"
- ]
- },
- "Globe7": {
- "properties": [
- "globe7.com"
- ],
- "resources": [
- "globe7.com"
- ]
- },
- "Go Daddy": {
- "properties": [
- "godaddy.com",
- "trafficfacts.com"
- ],
- "resources": [
- "godaddy.com",
- "trafficfacts.com"
- ]
- },
- "GoDataFeed": {
- "properties": [
- "godatafeed.com"
- ],
- "resources": [
- "godatafeed.com"
- ]
- },
- "GoGrid": {
- "properties": [
- "datapipe.com",
- "formalyzer.com"
- ],
- "resources": [
- "datapipe.com",
- "formalyzer.com",
- "gogrid.com",
- "komli.net"
- ]
- },
- "Goldbach": {
- "properties": [
- "goldbachgroup.com"
- ],
- "resources": [
- "goldbach.com",
- "goldbachgroup.com"
- ]
- },
- "GoldSpot Media": {
- "properties": [
- "goldspotmedia.com"
- ],
- "resources": [
- "goldspotmedia.com"
- ]
- },
- "Google": {
- "properties": [
- "abc.xyz",
- "admeld.com",
- "blogger.com",
- "blogspot.com",
- "crashlytics.com",
- "google-melange.com",
- "google.ac",
- "google.ad",
- "google.ae",
- "google.al",
- "google.am",
- "google.as",
- "google.at",
- "google.az",
- "google.ba",
- "google.be",
- "google.bf",
- "google.bg",
- "google.bi",
- "google.bj",
- "google.bs",
- "google.bt",
- "google.by",
- "google.ca",
- "google.cat",
- "google.cd",
- "google.cf",
- "google.cg",
- "google.ch",
- "google.ci",
- "google.cl",
- "google.cm",
- "google.cn",
- "google.co.ao",
- "google.co.bw",
- "google.co.ck",
- "google.co.cr",
- "google.co.id",
- "google.co.il",
- "google.co.in",
- "google.co.jp",
- "google.co.ke",
- "google.co.kr",
- "google.co.ls",
- "google.co.ma",
- "google.co.mz",
- "google.co.nz",
- "google.co.th",
- "google.co.tz",
- "google.co.ug",
- "google.co.uk",
- "google.co.uz",
- "google.co.ve",
- "google.co.vi",
- "google.co.za",
- "google.co.zm",
- "google.co.zw",
- "google.com",
- "google.com.af",
- "google.com.ag",
- "google.com.ai",
- "google.com.ar",
- "google.com.au",
- "google.com.bd",
- "google.com.bh",
- "google.com.bn",
- "google.com.bo",
- "google.com.br",
- "google.com.bz",
- "google.com.co",
- "google.com.cu",
- "google.com.cy",
- "google.com.do",
- "google.com.ec",
- "google.com.eg",
- "google.com.et",
- "google.com.fj",
- "google.com.gh",
- "google.com.gi",
- "google.com.gt",
- "google.com.hk",
- "google.com.jm",
- "google.com.kh",
- "google.com.kw",
- "google.com.lb",
- "google.com.ly",
- "google.com.mm",
- "google.com.mt",
- "google.com.mx",
- "google.com.my",
- "google.com.na",
- "google.com.nf",
- "google.com.ng",
- "google.com.ni",
- "google.com.np",
- "google.com.om",
- "google.com.pa",
- "google.com.pe",
- "google.com.pg",
- "google.com.ph",
- "google.com.pk",
- "google.com.pr",
- "google.com.py",
- "google.com.qa",
- "google.com.sa",
- "google.com.sb",
- "google.com.sg",
- "google.com.sl",
- "google.com.sv",
- "google.com.tj",
- "google.com.tr",
- "google.com.tw",
- "google.com.ua",
- "google.com.uy",
- "google.com.vc",
- "google.com.vn",
- "google.cv",
- "google.cz",
- "google.de",
- "google.dj",
- "google.dk",
- "google.dm",
- "google.dz",
- "google.ee",
- "google.es",
- "google.fi",
- "google.fm",
- "google.fr",
- "google.ga",
- "google.ge",
- "google.gg",
- "google.gl",
- "google.gm",
- "google.gp",
- "google.gr",
- "google.gy",
- "google.hn",
- "google.hr",
- "google.ht",
- "google.hu",
- "google.ie",
- "google.im",
- "google.iq",
- "google.is",
- "google.it",
- "google.je",
- "google.jo",
- "google.kg",
- "google.ki",
- "google.kz",
- "google.la",
- "google.li",
- "google.lk",
- "google.lt",
- "google.lu",
- "google.lv",
- "google.md",
- "google.me",
- "google.mg",
- "google.mk",
- "google.ml",
- "google.mn",
- "google.ms",
- "google.mu",
- "google.mv",
- "google.mw",
- "google.ne",
- "google.nl",
- "google.no",
- "google.nr",
- "google.nu",
- "google.pl",
- "google.pn",
- "google.ps",
- "google.pt",
- "google.ro",
- "google.rs",
- "google.ru",
- "google.rw",
- "google.sc",
- "google.se",
- "google.sh",
- "google.si",
- "google.sk",
- "google.sm",
- "google.sn",
- "google.so",
- "google.st",
- "google.td",
- "google.tg",
- "google.tk",
- "google.tl",
- "google.tm",
- "google.tn",
- "google.to",
- "google.tt",
- "google.vg",
- "google.vu",
- "google.ws",
- "googlesource.com",
- "ingress.com",
- "nest.com",
- "panoramio.com",
- "pinpoint-dot-chromeperf.appspot.com",
- "youtube.com"
- ],
- "resources": [
- "2mdn.net",
- "admeld.com",
- "admob.com",
- "apture.com",
- "blogger.com",
- "cc-dt.com",
- "crashlytics.com",
- "destinationurl.com",
- "doubleclick.net",
- "ggpht.com",
- "gmail.com",
- "gmodules.com",
- "google-analytics.com",
- "google.ac",
- "google.ad",
- "google.ae",
- "google.al",
- "google.am",
- "google.as",
- "google.at",
- "google.az",
- "google.ba",
- "google.be",
- "google.bf",
- "google.bg",
- "google.bi",
- "google.bj",
- "google.bs",
- "google.bt",
- "google.by",
- "google.ca",
- "google.cat",
- "google.cc",
- "google.cd",
- "google.cf",
- "google.cg",
- "google.ch",
- "google.ci",
- "google.cl",
- "google.cm",
- "google.cn",
- "google.co.ao",
- "google.co.bw",
- "google.co.ck",
- "google.co.cr",
- "google.co.id",
- "google.co.il",
- "google.co.in",
- "google.co.jp",
- "google.co.ke",
- "google.co.kr",
- "google.co.ls",
- "google.co.ma",
- "google.co.mz",
- "google.co.nz",
- "google.co.th",
- "google.co.tz",
- "google.co.ug",
- "google.co.uk",
- "google.co.uz",
- "google.co.ve",
- "google.co.vi",
- "google.co.za",
- "google.co.zm",
- "google.co.zw",
- "google.com",
- "google.com.af",
- "google.com.ag",
- "google.com.ai",
- "google.com.ar",
- "google.com.au",
- "google.com.bd",
- "google.com.bh",
- "google.com.bn",
- "google.com.bo",
- "google.com.br",
- "google.com.bz",
- "google.com.co",
- "google.com.cu",
- "google.com.cy",
- "google.com.do",
- "google.com.ec",
- "google.com.eg",
- "google.com.et",
- "google.com.fj",
- "google.com.gh",
- "google.com.gi",
- "google.com.gt",
- "google.com.hk",
- "google.com.jm",
- "google.com.kh",
- "google.com.kw",
- "google.com.lb",
- "google.com.lc",
- "google.com.ly",
- "google.com.mm",
- "google.com.mt",
- "google.com.mx",
- "google.com.my",
- "google.com.na",
- "google.com.nf",
- "google.com.ng",
- "google.com.ni",
- "google.com.np",
- "google.com.om",
- "google.com.pa",
- "google.com.pe",
- "google.com.pg",
- "google.com.ph",
- "google.com.pk",
- "google.com.pr",
- "google.com.py",
- "google.com.qa",
- "google.com.sa",
- "google.com.sb",
- "google.com.sg",
- "google.com.sl",
- "google.com.sv",
- "google.com.tj",
- "google.com.tn",
- "google.com.tr",
- "google.com.tw",
- "google.com.ua",
- "google.com.uy",
- "google.com.vc",
- "google.com.vn",
- "google.cv",
- "google.cz",
- "google.de",
- "google.dj",
- "google.dk",
- "google.dm",
- "google.dz",
- "google.ee",
- "google.es",
- "google.fi",
- "google.fm",
- "google.fr",
- "google.ga",
- "google.ge",
- "google.gf",
- "google.gg",
- "google.gl",
- "google.gm",
- "google.gp",
- "google.gr",
- "google.gy",
- "google.hn",
- "google.hr",
- "google.ht",
- "google.hu",
- "google.ie",
- "google.im",
- "google.io",
- "google.iq",
- "google.is",
- "google.it",
- "google.je",
- "google.jo",
- "google.kg",
- "google.ki",
- "google.kz",
- "google.la",
- "google.li",
- "google.lk",
- "google.lt",
- "google.lu",
- "google.lv",
- "google.md",
- "google.me",
- "google.mg",
- "google.mk",
- "google.ml",
- "google.mn",
- "google.ms",
- "google.mu",
- "google.mv",
- "google.mw",
- "google.ne",
- "google.nl",
- "google.no",
- "google.nr",
- "google.nu",
- "google.pl",
- "google.pn",
- "google.ps",
- "google.pt",
- "google.ro",
- "google.rs",
- "google.ru",
- "google.rw",
- "google.sc",
- "google.se",
- "google.sh",
- "google.si",
- "google.sk",
- "google.sm",
- "google.sn",
- "google.so",
- "google.st",
- "google.td",
- "google.tg",
- "google.tk",
- "google.tl",
- "google.tm",
- "google.tn",
- "google.to",
- "google.tt",
- "google.vg",
- "google.vu",
- "google.ws",
- "googleadservices.com",
- "googleapis.com",
- "googlemail.com",
- "googlesyndication.com",
- "googletagservices.com",
- "googleusercontent.com",
- "googlevideo.com",
- "gstatic.com",
- "invitemedia.com",
- "postrank.com",
- "recaptcha.net",
- "smtad.net",
- "youtube.com"
- ]
- },
- "GoSquared": {
- "properties": [
- "gosquared.com"
- ],
- "resources": [
- "gosquared.com"
- ]
- },
- "GoStats": {
- "properties": [
- "gostats.com"
- ],
- "resources": [
- "gostats.com"
- ]
- },
- "Grapeshot": {
- "properties": [
- "grapeshot.co.uk",
- "www.grapeshot.co.uk"
- ],
- "resources": [
- "grapeshot.co.uk",
- "www.grapeshot.co.uk"
- ]
- },
- "GrapheneMedia": {
- "properties": [
- "graphenemedia.in"
- ],
- "resources": [
- "graphenedigitalanalytics.in"
- ]
- },
- "Graphnium": {
- "properties": [
- "graphinium.com"
- ],
- "resources": [
- "crm4d.com"
- ]
- },
- "Gravity": {
- "properties": [
- "gravity.com",
- "grvcdn.com"
- ],
- "resources": [
- "gravity.com",
- "grvcdn.com"
- ]
- },
- "Gridcash": {
- "properties": [
- "adless.io",
- "gridcash.net"
- ],
- "resources": [
- "adless.io",
- "gridcash.net"
- ]
- },
- "Grocery Shopping Network": {
- "properties": [
- "groceryshopping.net"
- ],
- "resources": [
- "groceryshopping.net"
- ]
- },
- "GroovinAds": {
- "properties": [
- "groovinads.com"
- ],
- "resources": [
- "groovinads.com"
- ]
- },
- "Gruner + Jahr": {
- "properties": [
- "guj.de",
- "ligatus.com"
- ],
- "resources": [
- "guj.de",
- "ligatus.com"
- ]
- },
- "GTop": {
- "properties": [
- "arenaweb.ro"
- ],
- "resources": [
- "arenaweb.ro",
- "gtop.ro",
- "gtopstats.com"
- ]
- },
- "GumGum": {
- "properties": [
- "gumgum.com"
- ],
- "resources": [
- "gumgum.com"
- ]
- },
- "Gunggo": {
- "properties": [
- "gunggo.com"
- ],
- "resources": [
- "gunggo.com"
- ]
- },
- "Hands Mobile": {
- "properties": [
- "hands.com.br",
- "www.hands.com.br"
- ],
- "resources": [
- "hands.com.br",
- "www.hands.com.br"
- ]
- },
- "Harrenmedia": {
- "properties": [
- "harrenmedia.com",
- "harrenmedianetwork.com"
- ],
- "resources": [
- "harrenmedia.com",
- "harrenmedianetwork.com"
- ]
- },
- "HealthPricer": {
- "properties": [
- "adacado.com",
- "healthpricer.com"
- ],
- "resources": [
- "adacado.com",
- "healthpricer.com"
- ]
- },
- "Hearst": {
- "properties": [
- "hearst.com",
- "ic-live.com",
- "iclive.com",
- "icrossing.com",
- "raasnet.com"
- ],
- "resources": [
- "hearst.com",
- "ic-live.com",
- "iclive.com",
- "icrossing.com",
- "raasnet.com",
- "redaril.com",
- "sptag.com",
- "sptag1.com",
- "sptag2.com",
- "sptag3.com"
- ]
- },
- "Heyzap": {
- "properties": [
- "heyzap.com"
- ],
- "resources": [
- "heyzap.com"
- ]
- },
- "HilltopAds": {
- "properties": [
- "hilltopads.com"
- ],
- "resources": [
- "hilltopads.com",
- "hilltopads.net",
- "shoporielder.pro"
- ]
- },
- "Hi-media": {
- "properties": [
- "himediagroup.com"
- ],
- "resources": [
- "comclick.com",
- "hi-media.com",
- "himediagroup.com"
- ]
- },
- "Histats": {
- "properties": [
- "histats.com"
- ],
- "resources": [
- "histats.com"
- ]
- },
- "HitsLink": {
- "properties": [
- "hitslink.com"
- ],
- "resources": [
- "hitslink.com"
- ]
- },
- "Hit Sniffer": {
- "properties": [
- "hitsniffer.com"
- ],
- "resources": [
- "hitsniffer.com"
- ]
- },
- "Horyzon Media": {
- "properties": [
- "horyzon-media.com"
- ],
- "resources": [
- "horyzon-media.com"
- ]
- },
- "HotelChamp": {
- "properties": [
- "hotelchamp.com"
- ],
- "resources": [
- "hotelchamp.com"
- ]
- },
- "Hotjar": {
- "properties": [
- "hotjar.com"
- ],
- "resources": [
- "hotjar.com"
- ]
- },
- "HotMart": {
- "properties": [
- "hotmart.com"
- ],
- "resources": [
- "hotmart.com"
- ]
- },
- "HOTWords": {
- "properties": [
- "hotwords.com",
- "hotwords.es"
- ],
- "resources": [
- "hotwords.com",
- "hotwords.es"
- ]
- },
- "HP": {
- "properties": [
- "hp.com",
- "opentext.com",
- "optimost.com"
- ],
- "resources": [
- "hp.com",
- "optimost.com"
- ]
- },
- "Httpool": {
- "properties": [
- "httpool.com"
- ],
- "resources": [
- "httpool.com"
- ]
- },
- "HubSpot": {
- "properties": [
- "hubspot.com"
- ],
- "resources": [
- "hs-analytics.net",
- "hubspot.com"
- ]
- },
- "HUNT Mobile Ads": {
- "properties": [
- "huntmads.com"
- ],
- "resources": [
- "huntmads.com"
- ]
- },
- "Hurra.com": {
- "properties": [
- "hurra.com"
- ],
- "resources": [
- "hurra.com"
- ]
- },
- "IAB": {
- "properties": [
- "digitru.st",
- "iabtechlab.com"
- ],
- "resources": [
- "digitru.st"
- ]
- },
- "IAC": {
- "properties": [
- "iac.com",
- "iacadvertising.com"
- ],
- "resources": [
- "iac.com",
- "iacadvertising.com"
- ]
- },
- "iBehavior": {
- "properties": [
- "i-behavior.com",
- "ib-ibi.com"
- ],
- "resources": [
- "i-behavior.com",
- "ib-ibi.com"
- ]
- },
- "IBM": {
- "properties": [
- "ibm.com",
- "multicloud-ibm.com"
- ],
- "resources": [
- "cmcore.com",
- "coremetrics.com",
- "ibm.com",
- "unica.com",
- "xtify.com"
- ]
- },
- "ID5": {
- "properties": [
- "id5.io"
- ],
- "resources": [
- "id5-sync.com"
- ]
- },
- "IDG": {
- "properties": [
- "idg.com",
- "idgtechnetwork.com"
- ],
- "resources": [
- "idg.com",
- "idgtechnetwork.com"
- ]
- },
- "iEntry": {
- "properties": [
- "600z.com",
- "ientry.com"
- ],
- "resources": [
- "600z.com",
- "ientry.com"
- ]
- },
- "IgnitAd": {
- "properties": [
- "ignitad.com"
- ],
- "resources": [
- "ignitad.com"
- ]
- },
- "IgnitionOne": {
- "properties": [
- "ignitionone.com",
- "ignitionone.net",
- "searchignite.com"
- ],
- "resources": [
- "ignitionone.com",
- "ignitionone.net",
- "searchignite.com"
- ]
- },
- "iMedia": {
- "properties": [
- "imedia.cz"
- ],
- "resources": [
- "imedia.cz"
- ]
- },
- "Improve Digital": {
- "properties": [
- "360yield.com",
- "improvedigital.com"
- ],
- "resources": [
- "360yield.com",
- "improvedigital.com"
- ]
- },
- "Inadco": {
- "properties": [
- "inadco.com"
- ],
- "resources": [
- "anadcoads.com",
- "inadco.com",
- "inadcoads.com"
- ]
- },
- "InboundWriter": {
- "properties": [
- "enquisite.com",
- "inboundwriter.com"
- ],
- "resources": [
- "enquisite.com",
- "inboundwriter.com"
- ]
- },
- "IndexExchange": {
- "properties": [
- "indexexchange.com"
- ],
- "resources": [
- "indexexchange.com"
- ]
- },
- "Infectious Media": {
- "properties": [
- "infectiousmedia.com"
- ],
- "resources": [
- "impressiondesk.com",
- "infectiousmedia.com"
- ]
- },
- "Infernotions": {
- "properties": [
- "infernotions.com"
- ],
- "resources": [
- "infernotions.com"
- ]
- },
- "Inflection Point Media": {
- "properties": [
- "inflectionpointmedia.com"
- ],
- "resources": [
- "inflectionpointmedia.com"
- ]
- },
- "Infogroup": {
- "properties": [
- "infogroup.com"
- ],
- "resources": [
- "infogroup.com"
- ]
- },
- "Infolinks": {
- "properties": [
- "infolinks.com"
- ],
- "resources": [
- "infolinks.com"
- ]
- },
- "INFOnline": {
- "properties": [
- "infonline.de"
- ],
- "resources": [
- "infonline.de",
- "ioam.de",
- "ivwbox.de"
- ]
- },
- "InfoStars": {
- "properties": [
- "hotlog.ru",
- "infostars.ru"
- ],
- "resources": [
- "hotlog.ru",
- "infostars.ru"
- ]
- },
- "Infra-Ad": {
- "properties": [
- "infra-ad.com"
- ],
- "resources": [
- "infra-ad.com"
- ]
- },
- "InMobi": {
- "properties": [
- "aerserv.com",
- "inmobi.com",
- "sproutinc.com"
- ],
- "resources": [
- "aerserv.com",
- "inmobi.com",
- "sproutinc.com"
- ]
- },
- "inneractive": {
- "properties": [
- "inner-active.com"
- ],
- "resources": [
- "inner-active.com"
- ]
- },
- "Innity": {
- "properties": [
- "innity.com"
- ],
- "resources": [
- "innity.com"
- ]
- },
- "InsightExpress": {
- "properties": [
- "insightexpress.com"
- ],
- "resources": [
- "insightexpress.com",
- "insightexpressai.com"
- ]
- },
- "InSkin Media": {
- "properties": [
- "inskinmedia.com"
- ],
- "resources": [
- "inskinmedia.com"
- ]
- },
- "Inspectlet": {
- "properties": [
- "inspectlet.com"
- ],
- "resources": [
- "inspectlet.com"
- ]
- },
- "Instinctive": {
- "properties": [
- "instinctive.io"
- ],
- "resources": [
- "instinctive.io",
- "instinctiveads.com"
- ]
- },
- "Integral Ad Science": {
- "properties": [
- "integralads.com"
- ],
- "resources": [
- "adsafemedia.com",
- "adsafeprotected.com",
- "iasds01.com",
- "integralads.com"
- ]
- },
- "IntelligenceFocus": {
- "properties": [
- "intelligencefocus.com",
- "leadchampion.com"
- ],
- "resources": [
- "domodomain.com",
- "intelligencefocus.com",
- "leadchampion.com"
- ]
- },
- "Intent Media": {
- "properties": [
- "intentmedia.com"
- ],
- "resources": [
- "intentmedia.com",
- "intentmedia.net"
- ]
- },
- "Intergi": {
- "properties": [
- "intergi.com"
- ],
- "resources": [
- "intergi.com"
- ]
- },
- "Intermarkets": {
- "properties": [
- "intermarkets.net"
- ],
- "resources": [
- "intermarkets.net"
- ]
- },
- "Intermundo Media": {
- "properties": [
- "intermundomedia.com"
- ],
- "resources": [
- "intermundomedia.com"
- ]
- },
- "Internet Brands": {
- "properties": [
- "ibpxl.com",
- "internetbrands.com"
- ],
- "resources": [
- "ibpxl.com",
- "internetbrands.com"
- ]
- },
- "Interpolls": {
- "properties": [
- "interpolls.com"
- ],
- "resources": [
- "interpolls.com"
- ]
- },
- "Inuvo": {
- "properties": [
- "inuvo.com"
- ],
- "resources": [
- "inuvo.com"
- ]
- },
- "InvestingChannel": {
- "properties": [
- "investingchannel.com"
- ],
- "resources": [
- "investingchannel.com"
- ]
- },
- "iovation": {
- "properties": [
- "iovation.com"
- ],
- "resources": [
- "iesnare.com",
- "iovation.com"
- ]
- },
- "iPerceptions": {
- "properties": [
- "iperceptions.com"
- ],
- "resources": [
- "iperceptions.com"
- ]
- },
- "IponWeb": {
- "properties": [
- "iponweb.com"
- ],
- "resources": [
- "iponweb.com",
- "iponweb.net"
- ]
- },
- "iPROM": {
- "properties": [
- "centraliprom.com",
- "iprom.net",
- "iprom.si",
- "mediaiprom.com"
- ],
- "resources": [
- "centraliprom.com",
- "iprom.net",
- "iprom.si",
- "mediaiprom.com"
- ]
- },
- "iPromote": {
- "properties": [
- "ipromote.com"
- ],
- "resources": [
- "ipromote.com"
- ]
- },
- "iProspect": {
- "properties": [
- "iprospect.com"
- ],
- "resources": [
- "clickmanage.com",
- "iprospect.com"
- ]
- },
- "ISI Technologies": {
- "properties": [
- "adversalservers.com",
- "digbro.com"
- ],
- "resources": [
- "adversalservers.com",
- "digbro.com"
- ]
- },
- "IslayTech": {
- "properties": [
- "islay.tech"
- ],
- "resources": [
- "islay.tech"
- ]
- },
- "ismatlab.com": {
- "properties": [
- "ismatlab.com"
- ],
- "resources": [
- "ismatlab.com"
- ]
- },
- "Itch": {
- "properties": [
- "itch.io"
- ],
- "resources": [
- "itch.io"
- ]
- },
- "ItIsATracker": {
- "properties": [
- "itisatracker.com"
- ],
- "resources": [
- "itisatracker.com"
- ]
- },
- "I.UA": {
- "properties": [
- "i.ua"
- ],
- "resources": [
- "i.ua"
- ]
- },
- "Jaroop": {
- "properties": [
- "jaroop.com"
- ],
- "resources": [
- "jaroop.com"
- ]
- },
- "JasperLabs": {
- "properties": [
- "jasperlabs.com"
- ],
- "resources": [
- "jasperlabs.com"
- ]
- },
- "Jemm": {
- "properties": [
- "jemmgroup.com"
- ],
- "resources": [
- "jemmgroup.com"
- ]
- },
- "Jink": {
- "properties": [
- "jink.de",
- "jinkads.com"
- ],
- "resources": [
- "jink.de",
- "jinkads.com"
- ]
- },
- "Jirbo": {
- "properties": [
- "adcolony.com"
- ],
- "resources": [
- "adcolony.com",
- "jirbo.com"
- ]
- },
- "Jivox": {
- "properties": [
- "jivox.com"
- ],
- "resources": [
- "jivox.com"
- ]
- },
- "JobThread": {
- "properties": [
- "jobthread.com"
- ],
- "resources": [
- "jobthread.com"
- ]
- },
- "JSE": {
- "properties": [
- "jsecoin.com"
- ],
- "resources": [
- "freecontent.bid",
- "freecontent.date",
- "freecontent.stream",
- "hashing.win",
- "hostingcloud.racing",
- "hostingcloud.science",
- "jsecoin.com"
- ]
- },
- "JuicyAds": {
- "properties": [
- "juicyads.com"
- ],
- "resources": [
- "juicyads.com"
- ]
- },
- "Jumptap": {
- "properties": [
- "jumptap.com"
- ],
- "resources": [
- "jumptap.com"
- ]
- },
- "justuno": {
- "properties": [
- "justuno.com"
- ],
- "resources": [
- "justuno.com"
- ]
- },
- "Kaltura": {
- "properties": [
- "kaltura.com"
- ],
- "resources": [
- "kaltura.com"
- ]
- },
- "Kargo": {
- "properties": [
- "kargo.com"
- ],
- "resources": [
- "kargo.com"
- ]
- },
- "Kenshoo": {
- "properties": [
- "kenshoo.com",
- "xg4ken.com"
- ],
- "resources": [
- "kenshoo.com",
- "xg4ken.com"
- ]
- },
- "Keyade": {
- "properties": [
- "keyade.com"
- ],
- "resources": [
- "keyade.com"
- ]
- },
- "KeyMetric": {
- "properties": [
- "keymetric.net"
- ],
- "resources": [
- "keymetric.net"
- ]
- },
- "Keywee": {
- "properties": [
- "keywee.co"
- ],
- "resources": [
- "keywee.co"
- ]
- },
- "kikin": {
- "properties": [
- "kikin.com"
- ],
- "resources": [
- "kikin.com"
- ]
- },
- "KISSmetrics": {
- "properties": [
- "kissmetrics.com"
- ],
- "resources": [
- "kissmetrics.com"
- ]
- },
- "KissMyAds": {
- "properties": [
- "kissmyads.com"
- ],
- "resources": [
- "kissmyads.com"
- ]
- },
- "Kitara Media": {
- "properties": [
- "103092804.com",
- "kitaramedia.com"
- ],
- "resources": [
- "103092804.com",
- "kitaramedia.com"
- ]
- },
- "Kitcode": {
- "properties": [
- "kitcode.net"
- ],
- "resources": [
- "kitcode.net"
- ]
- },
- "KIT digital": {
- "properties": [
- "kitd.com"
- ],
- "resources": [
- "keewurd.com",
- "kitd.com",
- "peerset.com"
- ]
- },
- "Kokteyl": {
- "properties": [
- "admost.com",
- "kokteyl.com"
- ],
- "resources": [
- "admost.com",
- "kokteyl.com"
- ]
- },
- "Komli": {
- "properties": [
- "komli.com"
- ],
- "resources": [
- "komli.com"
- ]
- },
- "Konduto": {
- "properties": [
- "konduto.com"
- ],
- "resources": [
- "k-analytix.com",
- "konduto.com"
- ]
- },
- "Kontera": {
- "properties": [
- "kontera.com"
- ],
- "resources": [
- "kontera.com"
- ]
- },
- "Korrelate": {
- "properties": [
- "korrelate.com"
- ],
- "resources": [
- "adsummos.com",
- "adsummos.net",
- "korrelate.com"
- ]
- },
- "Krux": {
- "properties": [
- "krux.com",
- "kruxdigital.com"
- ],
- "resources": [
- "krux.com",
- "kruxdigital.com",
- "krxd.net"
- ]
- },
- "Lakana": {
- "properties": [
- "lakana.com"
- ],
- "resources": [
- "ibsys.com",
- "lakana.com"
- ]
- },
- "Layer-Ad.org": {
- "properties": [
- "layer-ad.org"
- ],
- "resources": [
- "layer-ad.org"
- ]
- },
- "Layer Ads": {
- "properties": [
- "layer-ads.net"
- ],
- "resources": [
- "layer-ads.net"
- ]
- },
- "LeadBolt": {
- "properties": [
- "leadbolt.com"
- ],
- "resources": [
- "leadbolt.com"
- ]
- },
- "LeadForensics": {
- "properties": [
- "leadforensics.com"
- ],
- "resources": [
- "leadforensics.com"
- ]
- },
- "LeadFormix": {
- "properties": [
- "calliduscloud.com",
- "leadforce1.com",
- "leadformix.com"
- ],
- "resources": [
- "calliduscloud.com",
- "leadforce1.com",
- "leadformix.com"
- ]
- },
- "LeadsHub": {
- "properties": [
- "ztsrv.com"
- ],
- "resources": [
- "ztsrv.com"
- ]
- },
- "LeanPlum": {
- "properties": [
- "leanplum.com"
- ],
- "resources": [
- "leanplum.com"
- ]
- },
- "Legolas Media": {
- "properties": [
- "legolas-media.com"
- ],
- "resources": [
- "legolas-media.com"
- ]
- },
- "Levexis": {
- "properties": [
- "levexis.com"
- ],
- "resources": [
- "levexis.com"
- ]
- },
- "Lexos Media": {
- "properties": [
- "adbull.com",
- "lexosmedia.com"
- ],
- "resources": [
- "adbull.com",
- "lexosmedia.com"
- ]
- },
- "LifeStreet": {
- "properties": [
- "lfstmedia.com",
- "lifestreetmedia.com"
- ],
- "resources": [
- "lfstmedia.com",
- "lifestreetmedia.com"
- ]
- },
- "Limelight Networks": {
- "properties": [
- "limelight.com"
- ],
- "resources": [
- "clickability.com",
- "limelight.com",
- "llnwd.net"
- ]
- },
- "LineZing": {
- "properties": [
- "linezing.com"
- ],
- "resources": [
- "linezing.com"
- ]
- },
- "LinkConnector": {
- "properties": [
- "linkconnector.com"
- ],
- "resources": [
- "linkconnector.com"
- ]
- },
- "LinkedIn": {
- "properties": [
- "linkedin.com"
- ],
- "resources": [
- "licdn.com",
- "linkedin.com"
- ]
- },
- "LinkShare": {
- "properties": [
- "rakutenmarketing.com"
- ],
- "resources": [
- "linkshare.com",
- "linksynergy.com",
- "rakutenmarketing.com"
- ]
- },
- "Linkz": {
- "properties": [
- "linkz.net"
- ],
- "resources": [
- "linkz.net"
- ]
- },
- "Listrak": {
- "properties": [
- "listrak.com",
- "listrakbi.com"
- ],
- "resources": [
- "listrak.com",
- "listrakbi.com"
- ]
- },
- "LiveIntent": {
- "properties": [
- "liveintent.com"
- ],
- "resources": [
- "liadm.com",
- "liveintent.com"
- ]
- },
- "LiveInternet": {
- "properties": [
- "liveinternet.ru",
- "yadro.ru"
- ],
- "resources": [
- "liveinternet.ru",
- "yadro.ru"
- ]
- },
- "LivePerson": {
- "properties": [
- "liveperson.com"
- ],
- "resources": [
- "liveperson.com",
- "liveperson.net",
- "nuconomy.com"
- ]
- },
- "LiveRail": {
- "properties": [
- "liverail.com"
- ],
- "resources": [
- "liverail.com"
- ]
- },
- "LiveRamp": {
- "properties": [
- "liveramp.com"
- ],
- "resources": [
- "liveramp.com",
- "tvpixel.com"
- ]
- },
- "LKQD": {
- "properties": [
- "lkqd.com",
- "lkqd.net"
- ],
- "resources": [
- "lkqd.com",
- "lkqd.net"
- ]
- },
- "Local Yokel Media": {
- "properties": [
- "localyokelmedia.com"
- ],
- "resources": [
- "localyokelmedia.com"
- ]
- },
- "Localytics": {
- "properties": [
- "localytics.com"
- ],
- "resources": [
- "localytics.com"
- ]
- },
- "LockerDome": {
- "properties": [
- "lockerdome.com"
- ],
- "resources": [
- "lockerdome.com"
- ]
- },
- "Lockerz": {
- "properties": [
- "lockerz.com"
- ],
- "resources": [
- "lockerz.com"
- ]
- },
- "Logdy": {
- "properties": [
- "logdy.com"
- ],
- "resources": [
- "logdy.com"
- ]
- },
- "Longboard Media": {
- "properties": [
- "longboardmedia.com"
- ],
- "resources": [
- "longboardmedia.com"
- ]
- },
- "LongTail Video": {
- "properties": [
- "jwplayer.com"
- ],
- "resources": [
- "longtailvideo.com",
- "ltassrv.com"
- ]
- },
- "Loomia": {
- "properties": [
- "loomia.com"
- ],
- "resources": [
- "loomia.com"
- ]
- },
- "LoopFuse": {
- "properties": [
- "lfov.net",
- "loopfuse.net"
- ],
- "resources": [
- "lfov.net",
- "loopfuse.net"
- ]
- },
- "LoopMe": {
- "properties": [
- "loopme.com"
- ],
- "resources": [
- "loopme.com"
- ]
- },
- "Lotame": {
- "properties": [
- "crwdcntrl.net",
- "lotame.com"
- ],
- "resources": [
- "crwdcntrl.net",
- "lotame.com"
- ]
- },
- "LotLinx": {
- "properties": [
- "lotlinx.com"
- ],
- "resources": [
- "lotlinx.com"
- ]
- },
- "Lower My Bills": {
- "properties": [
- "lowermybills.com"
- ],
- "resources": [
- "lowermybills.com"
- ]
- },
- "lptracker": {
- "properties": [
- "lptracker.io"
- ],
- "resources": [
- "lptracker.io"
- ]
- },
- "LucidMedia": {
- "properties": [
- "lucidmedia.com"
- ],
- "resources": [
- "lucidmedia.com"
- ]
- },
- "LuckyOrange": {
- "properties": [
- "luckyorange.com"
- ],
- "resources": [
- "luckyorange.com",
- "luckyorange.net"
- ]
- },
- "Lynchpin": {
- "properties": [
- "lynchpin.com"
- ],
- "resources": [
- "lynchpin.com",
- "lypn.com"
- ]
- },
- "Lyris": {
- "properties": [
- "aurea.com"
- ],
- "resources": [
- "aurea.com",
- "clicktracks.com",
- "lyris.com"
- ]
- },
- "Lytiks": {
- "properties": [
- "lytiks.com"
- ],
- "resources": [
- "lytiks.com"
- ]
- },
- "m6d": {
- "properties": [
- "dstillery.com"
- ],
- "resources": [
- "dstillery.com",
- "m6d.com",
- "media6degrees.com"
- ]
- },
- "Madhouse": {
- "properties": [
- "madhouse.cn"
- ],
- "resources": [
- "madhouse.cn"
- ]
- },
- "Madison Logic": {
- "properties": [
- "dinclinx.com",
- "madisonlogic.com"
- ],
- "resources": [
- "dinclinx.com",
- "madisonlogic.com"
- ]
- },
- "madvertise": {
- "properties": [
- "madvertise.com"
- ],
- "resources": [
- "madvertise.com"
- ]
- },
- "Magnetic": {
- "properties": [
- "domdex.net",
- "magnetic.com"
- ],
- "resources": [
- "domdex.com",
- "domdex.net",
- "magnetic.com",
- "qjex.net"
- ]
- },
- "Magnify360": {
- "properties": [
- "dialogmgr.com",
- "magnify360.com"
- ],
- "resources": [
- "dialogmgr.com",
- "magnify360.com"
- ]
- },
- "MailChimp": {
- "properties": [
- "campaign-archive1.com",
- "mailchi.mp",
- "mailchimp.com"
- ],
- "resources": [
- "campaign-archive1.com",
- "list-manage.com",
- "mailchi.mp",
- "mailchimp.com"
- ]
- },
- "Mail.Ru": {
- "properties": [
- "list.ru",
- "mail.ru"
- ],
- "resources": [
- "list.ru",
- "mail.ru"
- ]
- },
- "Manifest": {
- "properties": [
- "bannerbank.ru",
- "manifest.ru"
- ],
- "resources": [
- "bannerbank.ru",
- "manifest.ru"
- ]
- },
- "Marchex": {
- "properties": [
- "industrybrains.com",
- "marchex.com"
- ],
- "resources": [
- "industrybrains.com",
- "marchex.com"
- ]
- },
- "Marimedia": {
- "properties": [
- "marimedia.net"
- ],
- "resources": [
- "marimedia.net"
- ]
- },
- "MarketGid": {
- "properties": [
- "dt00.net",
- "dt07.net",
- "marketgid.com"
- ],
- "resources": [
- "dt00.net",
- "dt07.net",
- "marketgid.com"
- ]
- },
- "Marketo": {
- "properties": [
- "marketo.com"
- ],
- "resources": [
- "marketo.com",
- "marketo.net"
- ]
- },
- "Markit": {
- "properties": [
- "markit.com",
- "wsod.com"
- ],
- "resources": [
- "markit.com",
- "wsod.com"
- ]
- },
- "MarkMonitor": {
- "properties": [
- "9c9media.ca",
- "markmonitor.com"
- ],
- "resources": [
- "9c9media.ca",
- "markmonitor.com"
- ]
- },
- "Marktest": {
- "properties": [
- "marktest.com",
- "marktest.pt"
- ],
- "resources": [
- "marktest.com",
- "marktest.pt"
- ]
- },
- "Martini Media": {
- "properties": [
- "martiniadnetwork.com"
- ],
- "resources": [
- "martiniadnetwork.com",
- "martinimedianetwork.com"
- ]
- },
- "mashero": {
- "properties": [
- "mashero.com"
- ],
- "resources": [
- "mashero.com"
- ]
- },
- "MashLogic": {
- "properties": [
- "mashlogic.com"
- ],
- "resources": [
- "mashlogic.com"
- ]
- },
- "Match.com": {
- "properties": [
- "chemistry.com",
- "match.com"
- ],
- "resources": [
- "chemistry.com",
- "match.com",
- "meetic-partners.com"
- ]
- },
- "Matomy": {
- "properties": [
- "matomy.com"
- ],
- "resources": [
- "adnetinteractive.com",
- "adsmarket.com",
- "matomy.com",
- "matomymarket.com",
- "matomymedia.com",
- "mediawhiz.com",
- "optimatic.com",
- "xtendmedia.com"
- ]
- },
- "MaxBounty": {
- "properties": [
- "maxbounty.com",
- "mb01.com"
- ],
- "resources": [
- "maxbounty.com",
- "mb01.com"
- ]
- },
- "MaxMind": {
- "properties": [
- "maxmind.com"
- ],
- "resources": [
- "maxmind.com",
- "mmapiws.com"
- ]
- },
- "MaxPoint": {
- "properties": [
- "maxpointinteractive.com",
- "maxusglobal.com",
- "mxptint.net"
- ],
- "resources": [
- "maxpointinteractive.com",
- "maxusglobal.com",
- "mxptint.net"
- ]
- },
- "McAfee": {
- "properties": [
- "mcafee.com",
- "mcafeesecure.com"
- ],
- "resources": [
- "mcafee.com",
- "mcafeesecure.com",
- "scanalert.com"
- ]
- },
- "MdotM": {
- "properties": [
- "mdotm.com"
- ],
- "resources": [
- "mdotm.com"
- ]
- },
- "MediaBrix": {
- "properties": [
- "mediabrix.com"
- ],
- "resources": [
- "mediabrix.com"
- ]
- },
- "MediaCom": {
- "properties": [
- "mediacom.com"
- ],
- "resources": [
- "mediacom.com"
- ]
- },
- "mediaFORGE": {
- "properties": [
- "mediaforge.com"
- ],
- "resources": [
- "mediaforge.com"
- ]
- },
- "Medialets": {
- "properties": [
- "medialets.com"
- ],
- "resources": [
- "medialets.com"
- ]
- },
- "MediaMath": {
- "properties": [
- "mediamath.com"
- ],
- "resources": [
- "adroitinteractive.com",
- "designbloxlive.com",
- "mathtag.com",
- "mediamath.com"
- ]
- },
- "Médiamétrie-eStat": {
- "properties": [
- "mediametrie-estat.com"
- ],
- "resources": [
- "estat.com",
- "mediametrie-estat.com"
- ]
- },
- "media.net": {
- "properties": [
- "media.net"
- ],
- "resources": [
- "media.net"
- ]
- },
- "Mediaocean": {
- "properties": [
- "adbuyer.com",
- "mediaocean.com"
- ],
- "resources": [
- "adbuyer.com",
- "mediaocean.com"
- ]
- },
- "MediaShakers": {
- "properties": [
- "media-servers.net",
- "mediashakers.com"
- ],
- "resources": [
- "media-servers.net",
- "mediashakers.com"
- ]
- },
- "MediaTrust": {
- "properties": [
- "mediatrust.com"
- ],
- "resources": [
- "mediatrust.com"
- ]
- },
- "Medicx Media Solutions": {
- "properties": [
- "medicxmedia.com"
- ],
- "resources": [
- "medicxmedia.com"
- ]
- },
- "Meebo": {
- "properties": [
- "meebo.com"
- ],
- "resources": [
- "meebo.com",
- "meebocdn.net"
- ]
- },
- "MegaIndex": {
- "properties": [
- "megaindex.ru"
- ],
- "resources": [
- "megaindex.ru"
- ]
- },
- "Mercadopago": {
- "properties": [
- "mercadolibre.cl",
- "mercadolibre.co.cr",
- "mercadolibre.com",
- "mercadolibre.com.ar",
- "mercadolibre.com.bo",
- "mercadolibre.com.co",
- "mercadolibre.com.do",
- "mercadolibre.com.ec",
- "mercadolibre.com.gt",
- "mercadolibre.com.hn",
- "mercadolibre.com.mx",
- "mercadolibre.com.ni",
- "mercadolibre.com.pa",
- "mercadolibre.com.pe",
- "mercadolibre.com.py",
- "mercadolibre.com.sv",
- "mercadolibre.com.uy",
- "mercadolibre.com.ve",
- "mercadolivre.com.br",
- "mercadopago.com"
- ],
- "resources": [
- "mercadopago.com"
- ]
- },
- "Mercent": {
- "properties": [
- "mercent.com"
- ],
- "resources": [
- "mercent.com"
- ]
- },
- "MerchantAdvantage": {
- "properties": [
- "merchantadvantage.com"
- ],
- "resources": [
- "merchantadvantage.com"
- ]
- },
- "Merchenta": {
- "properties": [
- "merchenta.com"
- ],
- "resources": [
- "merchenta.com"
- ]
- },
- "Merkle": {
- "properties": [
- "merkleinc.com",
- "rkdms.com"
- ],
- "resources": [
- "merkleinc.com",
- "rimmkaufman.com",
- "rkdms.com"
- ]
- },
- "Meta Network": {
- "properties": [
- "metanetwork.com"
- ],
- "resources": [
- "metanetwork.com"
- ]
- },
- "Meteor": {
- "properties": [
- "meteorsolutions.com"
- ],
- "resources": [
- "meteorsolutions.com"
- ]
- },
- "MetrixLab": {
- "properties": [
- "crm-metrix.com",
- "customerconversio.com",
- "metrixlab.com",
- "opinionbar.com"
- ],
- "resources": [
- "adoftheyear.com",
- "crm-metrix.com",
- "customerconversio.com",
- "metrixlab.com",
- "opinionbar.com"
- ]
- },
- "MicroAd": {
- "properties": [
- "microad.jp",
- "www.microad.jp"
- ],
- "resources": [
- "microad.jp",
- "www.microad.jp"
- ]
- },
- "Microsoft": {
- "properties": [
- "acompli.net",
- "aka.ms",
- "azure.com",
- "azure.net",
- "azurerms.com",
- "bing.com",
- "cloudappsecurity.com",
- "gamesforwindows.com",
- "getgamesmart.com",
- "gfx.ms",
- "healthvault.com",
- "hockeyapp.net",
- "ieaddons.com",
- "iegallery.com",
- "live.com",
- "microsoft.com",
- "microsoftalumni.com",
- "microsoftalumni.org",
- "microsoftazuread-sso.com",
- "microsoftedgeinsiders.com",
- "microsoftonline-p.com",
- "microsoftonline-p.net",
- "microsoftonline.com",
- "microsoftstore.com",
- "microsoftstream.com",
- "msappproxy.net",
- "msft.net",
- "msftidentity.com",
- "msidentity.com",
- "msn.com",
- "o365weve.com",
- "oaspapps.com",
- "office.com",
- "office365.com",
- "officelive.com",
- "onedrive.com",
- "onenote.com",
- "outlook.com",
- "outlookmobile.com",
- "phonefactor.net",
- "s-msn.com",
- "sfx.ms",
- "sharepoint.com",
- "skype.com",
- "skypeforbusiness.com",
- "staffhub.ms",
- "sway-extensions.com",
- "sway.com",
- "trafficmanager.net",
- "virtualearth.net",
- "visualstudio.com",
- "windows.net",
- "windowsazure.com",
- "windowsphone.com",
- "worldwidetelescope.org",
- "wunderlist.com",
- "xbox.com",
- "yammer.com"
- ],
- "resources": [
- "aadrm.com",
- "adbureau.net",
- "adecn.com",
- "aquantive.com",
- "aspnetcdn.com",
- "assets-yammer.com",
- "azure.com",
- "azureedge.net",
- "bing.com",
- "cloudapp.net",
- "gamesforwindows.com",
- "getgamesmart.com",
- "gfx.ms",
- "healthvault.com",
- "live.com",
- "microsoft.com",
- "microsoftazuread-sso.com",
- "microsoftonline-p.com",
- "microsoftonline-p.net",
- "microsoftonline.com",
- "microsoftstore.com",
- "msads.net",
- "msauthimages.net",
- "msecnd.net",
- "msedge.net",
- "msndirect.com",
- "msocdn.com",
- "netconversions.com",
- "oaspapps.com",
- "office.com",
- "office.net",
- "officelive.com",
- "onenote.net",
- "onestore.ms",
- "onmicrosoft.com",
- "outlook.com",
- "roiservice.com",
- "s-msn.com",
- "sfbassets.com",
- "sharepoint.com",
- "skype.com",
- "skypeassets.com",
- "sway-cdn.com",
- "sway-extensions.com",
- "windows.net",
- "windowsazure.com",
- "yammerusercontent.com"
- ]
- },
- "Millennial Media": {
- "properties": [
- "decktrade.com",
- "millennialmedia.com",
- "mydas.mobi"
- ],
- "resources": [
- "decktrade.com",
- "millennialmedia.com",
- "mydas.mobi"
- ]
- },
- "Mindset Media": {
- "properties": [
- "mindset-media.com"
- ],
- "resources": [
- "mindset-media.com",
- "mmismm.com"
- ]
- },
- "MinerAlt": {
- "properties": [
- "mineralt.io",
- "vidzi.nu",
- "vidzi.tv"
- ],
- "resources": [
- "1q2w3.website",
- "analytics.blue",
- "aster18cdn.nl",
- "belicimo.pw",
- "besstahete.info",
- "dinorslick.icu",
- "feesocrald.com",
- "gramombird.com",
- "istlandoll.com",
- "mepirtedic.com",
- "mineralt.io",
- "pampopholf.com",
- "tercabilis.info",
- "tulip18.com",
- "vidzi.tv",
- "yololike.space"
- ]
- },
- "Minescripts": {
- "properties": [
- "minescripts.info"
- ],
- "resources": [
- "minescripts.info",
- "sslverify.info"
- ]
- },
- "MineXMR": {
- "properties": [
- "minexmr.stream"
- ],
- "resources": [
- "minexmr.stream"
- ]
- },
- "Mirando": {
- "properties": [
- "mirando.de"
- ],
- "resources": [
- "mirando.de"
- ]
- },
- "Mixpanel": {
- "properties": [
- "mixpanel.com"
- ],
- "resources": [
- "mixpanel.com",
- "mxpnl.com"
- ]
- },
- "Mixpo": {
- "properties": [
- "mixpo.com"
- ],
- "resources": [
- "mixpo.com"
- ]
- },
- "Moat": {
- "properties": [
- "moat.com",
- "moatads.com"
- ],
- "resources": [
- "moat.com",
- "moatads.com"
- ]
- },
- "MobFox": {
- "properties": [
- "mobfox.com"
- ],
- "resources": [
- "mobfox.com"
- ]
- },
- "Mobials": {
- "properties": [
- "mobials.com"
- ],
- "resources": [
- "mobials.com"
- ]
- },
- "MobileAdTrading": {
- "properties": [
- "mobileadtrading.com"
- ],
- "resources": [
- "mobileadtrading.com"
- ]
- },
- "Mobile Meteor": {
- "properties": [
- "mobilemeteor.com"
- ],
- "resources": [
- "mobilemeteor.com",
- "showmeinn.com"
- ]
- },
- "Mobile Storm": {
- "properties": [
- "mobilestorm.com"
- ],
- "resources": [
- "mobilestorm.com"
- ]
- },
- "MobVision": {
- "properties": [
- "admoda.com"
- ],
- "resources": [
- "admoda.com",
- "mobvision.com"
- ]
- },
- "Mocean Mobile": {
- "properties": [
- "moceanmobile.com"
- ],
- "resources": [
- "moceanmobile.com"
- ]
- },
- "Mochila": {
- "properties": [
- "mochila.com"
- ],
- "resources": [
- "mochila.com"
- ]
- },
- "Mojiva": {
- "properties": [
- "mojiva.com"
- ],
- "resources": [
- "mojiva.com"
- ]
- },
- "Monetate": {
- "properties": [
- "monetate.com",
- "monetate.net"
- ],
- "resources": [
- "monetate.com",
- "monetate.net"
- ]
- },
- "MONETIZEdigital": {
- "properties": [
- "cpalead.com"
- ],
- "resources": [
- "cpalead.com"
- ]
- },
- "Monetize More": {
- "properties": [
- "monetizemore.com"
- ],
- "resources": [
- "monetizemore.com"
- ]
- },
- "Mongoose Metrics": {
- "properties": [
- "mongoosemetrics.com"
- ],
- "resources": [
- "mongoosemetrics.com"
- ]
- },
- "Monitus": {
- "properties": [
- "monitus.net"
- ],
- "resources": [
- "monitus.net"
- ]
- },
- "Monoloop": {
- "properties": [
- "monoloop.com"
- ],
- "resources": [
- "monoloop.com"
- ]
- },
- "Monster": {
- "properties": [
- "monster.com"
- ],
- "resources": [
- "monster.com"
- ]
- },
- "Moolah Media": {
- "properties": [
- "moolah-media.com",
- "moolahmedia.com"
- ],
- "resources": [
- "moolah-media.com",
- "moolahmedia.com"
- ]
- },
- "MoPub": {
- "properties": [
- "mopub.com"
- ],
- "resources": [
- "mopub.com"
- ]
- },
- "motigo": {
- "properties": [
- "motigo.com"
- ],
- "resources": [
- "motigo.com",
- "nedstatbasic.net"
- ]
- },
- "Mouseflow": {
- "properties": [
- "mouseflow.com"
- ],
- "resources": [
- "mouseflow.com"
- ]
- },
- "MovieLush.com": {
- "properties": [
- "affbuzzads.com",
- "movielush.com"
- ],
- "resources": [
- "affbuzzads.com",
- "movielush.com"
- ]
- },
- "Multiple Stream Media": {
- "properties": [
- "adclickmedia.com",
- "multiplestreammktg.com"
- ],
- "resources": [
- "adclickmedia.com",
- "multiplestreammktg.com"
- ]
- },
- "MUNDO Media": {
- "properties": [
- "mundomedia.com",
- "silver-path.com"
- ],
- "resources": [
- "mundomedia.com",
- "silver-path.com"
- ]
- },
- "MyCounter": {
- "properties": [
- "mycounter.com.ua"
- ],
- "resources": [
- "mycounter.com.ua"
- ]
- },
- "MyPagerank.Net": {
- "properties": [
- "mypagerank.net"
- ],
- "resources": [
- "mypagerank.net"
- ]
- },
- "MyPressPlus": {
- "properties": [
- "mypressplus.com",
- "ppjol.net"
- ],
- "resources": [
- "mypressplus.com",
- "ppjol.net"
- ]
- },
- "Mystighty": {
- "properties": [
- "mystighty.info"
- ],
- "resources": [
- "mystighty.info",
- "sweeterge.info"
- ]
- },
- "myThings": {
- "properties": [
- "mythings.com",
- "mythingsmedia.com"
- ],
- "resources": [
- "mythings.com",
- "mythingsmedia.com"
- ]
- },
- "MyWebGrocer": {
- "properties": [
- "mywebgrocer.com"
- ],
- "resources": [
- "mywebgrocer.com"
- ]
- },
- "Nanigans": {
- "properties": [
- "nanigans.com"
- ],
- "resources": [
- "nanigans.com"
- ]
- },
- "Narrative": {
- "properties": [
- "narrative.io"
- ],
- "resources": [
- "narrative.io"
- ]
- },
- "NativeAds": {
- "properties": [
- "nativeads.com"
- ],
- "resources": [
- "nativeads.com"
- ]
- },
- "Nativo": {
- "properties": [
- "nativo.com",
- "postrelease.com"
- ],
- "resources": [
- "nativo.com",
- "postrelease.com"
- ]
- },
- "Navegg": {
- "properties": [
- "navdmp.com",
- "navegg.com"
- ],
- "resources": [
- "navdmp.com",
- "navegg.com"
- ]
- },
- "NDN": {
- "properties": [
- "newsinc.com"
- ],
- "resources": [
- "newsinc.com"
- ]
- },
- "Negishim": {
- "properties": [
- "negishim.org"
- ],
- "resources": [
- "negishim.org"
- ]
- },
- "NeroHut": {
- "properties": [
- "nerohut.com"
- ],
- "resources": [
- "nerohut.com",
- "nhsrv.cf"
- ]
- },
- "NetAffiliation": {
- "properties": [
- "netaffiliation.com"
- ],
- "resources": [
- "netaffiliation.com"
- ]
- },
- "Net Applications": {
- "properties": [
- "netapplications.com"
- ],
- "resources": [
- "hitsprocessor.com",
- "netapplications.com"
- ]
- },
- "NetBina": {
- "properties": [
- "netbina.com"
- ],
- "resources": [
- "netbina.com"
- ]
- },
- "NetElixir": {
- "properties": [
- "adelixir.com",
- "netelixir.com"
- ],
- "resources": [
- "adelixir.com",
- "netelixir.com"
- ]
- },
- "Netmining": {
- "properties": [
- "netmining.com",
- "netmng.com"
- ],
- "resources": [
- "netmining.com",
- "netmng.com"
- ]
- },
- "Net-Results": {
- "properties": [
- "net-results.com",
- "nr7.us"
- ],
- "resources": [
- "cdnma.com",
- "net-results.com",
- "nr7.us"
- ]
- },
- "NetSeer": {
- "properties": [
- "netseer.com"
- ],
- "resources": [
- "netseer.com"
- ]
- },
- "NetShelter": {
- "properties": [
- "ziffdavistech.com"
- ],
- "resources": [
- "netshelter.com",
- "netshelter.net",
- "ziffdavistech.com"
- ]
- },
- "Neustar": {
- "properties": [
- "adadvisor.net",
- "home.neustar",
- "neustar.biz"
- ],
- "resources": [
- "adadvisor.net",
- "neustar.biz"
- ]
- },
- "New Relic": {
- "properties": [
- "newrelic.com"
- ],
- "resources": [
- "newrelic.com",
- "nr-data.net"
- ]
- },
- "NewsRight": {
- "properties": [
- "apnewsregistry.com",
- "newsright.com"
- ],
- "resources": [
- "apnewsregistry.com",
- "newsright.com"
- ]
- },
- "newtention": {
- "properties": [
- "newtention.de",
- "newtention.net",
- "newtentionassets.net"
- ],
- "resources": [
- "newtention.de",
- "newtention.net",
- "newtentionassets.net"
- ]
- },
- "Nexage": {
- "properties": [
- "nexage.com"
- ],
- "resources": [
- "nexage.com"
- ]
- },
- "Nextag": {
- "properties": [
- "nextag.com"
- ],
- "resources": [
- "nextag.com"
- ]
- },
- "NextPerformance": {
- "properties": [
- "nextperf.com",
- "nextperformance.com",
- "nxtck.com"
- ],
- "resources": [
- "nextperf.com",
- "nextperformance.com",
- "nxtck.com"
- ]
- },
- "NextSTAT": {
- "properties": [
- "nextstat.com"
- ],
- "resources": [
- "nextstat.com"
- ]
- },
- "Nielsen": {
- "properties": [
- "glanceguide.com",
- "imrworldwide.com",
- "imrworldwide.net",
- "nielsen.com"
- ],
- "resources": [
- "glanceguide.com",
- "imrworldwide.com",
- "imrworldwide.net",
- "nielsen.com"
- ]
- },
- "Ninua": {
- "properties": [
- "networkedblogs.com",
- "ninua.com"
- ],
- "resources": [
- "networkedblogs.com",
- "ninua.com"
- ]
- },
- "Nokta": {
- "properties": [
- "noktamedya.com",
- "virgul.com"
- ],
- "resources": [
- "noktamedya.com",
- "virgul.com"
- ]
- },
- "NowSpots": {
- "properties": [
- "nowspots.com"
- ],
- "resources": [
- "nowspots.com"
- ]
- },
- "nrelate": {
- "properties": [
- "nrelate.com"
- ],
- "resources": [
- "nrelate.com"
- ]
- },
- "NuDataSecurity": {
- "properties": [
- "nudatasecurity.com"
- ],
- "resources": [
- "nudatasecurity.com"
- ]
- },
- "Nuffnang": {
- "properties": [
- "nuffnang.com",
- "nuffnang.com.my",
- "www.nuffnang.com.my"
- ],
- "resources": [
- "nuffnang.com",
- "nuffnang.com.my",
- "www.nuffnang.com.my"
- ]
- },
- "nugg.ad": {
- "properties": [
- "nugg.ad"
- ],
- "resources": [
- "nugg.ad",
- "nuggad.net"
- ]
- },
- "nurago": {
- "properties": [
- "sensic.net"
- ],
- "resources": [
- "nurago.com",
- "nurago.de",
- "sensic.net"
- ]
- },
- "Oberon Media": {
- "properties": [
- "iwin.com"
- ],
- "resources": [
- "blaze.com",
- "iwin.com",
- "oberon-media.com"
- ]
- },
- "Observer": {
- "properties": [
- "observerapp.com"
- ],
- "resources": [
- "observerapp.com"
- ]
- },
- "Ohana Media": {
- "properties": [
- "adohana.com",
- "ohana-media.com",
- "ohanaqb.com"
- ],
- "resources": [
- "adohana.com",
- "ohana-media.com",
- "ohanaqb.com"
- ]
- },
- "Omnicom Group": {
- "properties": [
- "accuenmedia.com",
- "omnicomgroup.com"
- ],
- "resources": [
- "accuenmedia.com",
- "omnicomgroup.com",
- "p-td.com"
- ]
- },
- "onAd": {
- "properties": [
- "onad.eu"
- ],
- "resources": [
- "onad.eu"
- ]
- },
- "OnAudience": {
- "properties": [
- "behavioralengine.com",
- "onaudience.com"
- ],
- "resources": [
- "behavioralengine.com",
- "onaudience.com"
- ]
- },
- "Onclusive": {
- "properties": [
- "onclusive.com"
- ],
- "resources": [
- "airpr.com"
- ]
- },
- "OneAd": {
- "properties": [
- "onead.com.tw"
- ],
- "resources": [
- "guoshipartners.com",
- "onevision.com.tw"
- ]
- },
- "One iota": {
- "properties": [
- "itsoneiota.com",
- "oneiota.co.uk"
- ],
- "resources": [
- "itsoneiota.com",
- "oneiota.co.uk"
- ]
- },
- "OneStat": {
- "properties": [
- "onestat.com"
- ],
- "resources": [
- "onestat.com"
- ]
- },
- "Oneupweb": {
- "properties": [
- "oneupweb.com",
- "sodoit.com"
- ],
- "resources": [
- "oneupweb.com",
- "sodoit.com"
- ]
- },
- "OnlineMetrix": {
- "properties": [
- "online-metrix.net"
- ],
- "resources": [
- "online-metrix.net"
- ]
- },
- "Ooyala": {
- "properties": [
- "ooyala.com"
- ],
- "resources": [
- "oo4.com",
- "ooyala.com"
- ]
- },
- "Open New Media": {
- "properties": [
- "onm.de"
- ],
- "resources": [
- "onm.de"
- ]
- },
- "Openstat": {
- "properties": [
- "openstat.com"
- ],
- "resources": [
- "openstat.com",
- "openstat.ru",
- "spylog.com"
- ]
- },
- "Opentracker": {
- "properties": [
- "opentracker.net"
- ],
- "resources": [
- "opentracker.net"
- ]
- },
- "OpenX": {
- "properties": [
- "openx.com",
- "openx.net"
- ],
- "resources": [
- "liftdna.com",
- "openx.com",
- "openx.net",
- "openx.org",
- "openxenterprise.com",
- "servedbyopenx.com"
- ]
- },
- "Opera": {
- "properties": [
- "opera.com"
- ],
- "resources": [
- "mobiletheory.com",
- "opera.com"
- ]
- },
- "Opolen": {
- "properties": [
- "opolen.com.br"
- ],
- "resources": [
- "opolen.com.br"
- ]
- },
- "OPT": {
- "properties": [
- "www.opt.ne.jp"
- ],
- "resources": [
- "advg.jp",
- "opt.ne.jp",
- "p-advg.com",
- "www.opt.ne.jp"
- ]
- },
- "Optify": {
- "properties": [
- "optify.net"
- ],
- "resources": [
- "optify.net"
- ]
- },
- "Optimal": {
- "properties": [
- "bn.co"
- ],
- "resources": [
- "cpmadvisors.com",
- "cpmatic.com",
- "nprove.com",
- "optim.al",
- "orbengine.com",
- "xa.net"
- ]
- },
- "Optimizely": {
- "properties": [
- "optimizely.com"
- ],
- "resources": [
- "optimizely.com"
- ]
- },
- "OptimumResponse": {
- "properties": [
- "optimumresponse.com"
- ],
- "resources": [
- "optimumresponse.com"
- ]
- },
- "OptinMonster": {
- "properties": [
- "optinmonster.com",
- "optnmstr.com"
- ],
- "resources": [
- "optinmonster.com",
- "optnmstr.com"
- ]
- },
- "OptMD": {
- "properties": [
- "optmd.com"
- ],
- "resources": [
- "optmd.com"
- ]
- },
- "Oracle": {
- "properties": [
- "oracle.com"
- ],
- "resources": [
- "atgsvcs.com",
- "eloqua.com",
- "estara.com",
- "instantservice.com",
- "istrack.com",
- "maxymiser.com",
- "oracle.com"
- ]
- },
- "OrangeSoda": {
- "properties": [
- "orangesoda.com",
- "otracking.com"
- ],
- "resources": [
- "orangesoda.com",
- "otracking.com"
- ]
- },
- "Outbrain": {
- "properties": [
- "outbrain.com",
- "sphere.com"
- ],
- "resources": [
- "outbrain.com",
- "sphere.com",
- "visualrevenue.com"
- ]
- },
- "Out There Media": {
- "properties": [
- "out-there-media.com"
- ],
- "resources": [
- "out-there-media.com"
- ]
- },
- "Oversee.net": {
- "properties": [
- "dsnextgen.com",
- "oversee.net"
- ],
- "resources": [
- "dsnextgen.com",
- "oversee.net"
- ]
- },
- "ÖWA": {
- "properties": [
- "oewa.at"
- ],
- "resources": [
- "oewa.at",
- "oewabox.at"
- ]
- },
- "OwnerIQ": {
- "properties": [
- "owneriq.com",
- "owneriq.net"
- ],
- "resources": [
- "owneriq.com",
- "owneriq.net"
- ]
- },
- "OxaMedia": {
- "properties": [
- "oxamedia.com"
- ],
- "resources": [
- "adconnexa.com",
- "adsbwm.com",
- "oxamedia.com"
- ]
- },
- "PageFair": {
- "properties": [
- "pagefair.com",
- "pagefair.net"
- ],
- "resources": [
- "pagefair.com",
- "pagefair.net"
- ]
- },
- "Paid-To-Promote.net": {
- "properties": [
- "paid-to-promote.net"
- ],
- "resources": [
- "paid-to-promote.net"
- ]
- },
- "Papaya": {
- "properties": [
- "papayamobile.com"
- ],
- "resources": [
- "papayamobile.com"
- ]
- },
- "Pardot": {
- "properties": [
- "pardot.com"
- ],
- "resources": [
- "pardot.com"
- ]
- },
- "Parse.ly": {
- "properties": [
- "parsely.com"
- ],
- "resources": [
- "parsely.com"
- ]
- },
- "PayHit": {
- "properties": [
- "payhit.com"
- ],
- "resources": [
- "payhit.com"
- ]
- },
- "PaymentsMB": {
- "properties": [
- "paymentsmb.com"
- ],
- "resources": [
- "paymentsmb.com"
- ]
- },
- "Paypal": {
- "properties": [
- "paypal.com",
- "simility.com"
- ],
- "resources": [
- "paypal.com",
- "simility.com"
- ]
- },
- "Paypopup.com": {
- "properties": [
- "paypopup.com"
- ],
- "resources": [
- "lzjl.com",
- "paypopup.com"
- ]
- },
- "PebblePost": {
- "properties": [
- "pebblepost.com"
- ],
- "resources": [
- "pbbl.co"
- ]
- },
- "Peer39": {
- "properties": [
- "peer39.com",
- "peer39.net"
- ],
- "resources": [
- "peer39.com",
- "peer39.net"
- ]
- },
- "PeerFly": {
- "properties": [
- "peerfly.com"
- ],
- "resources": [
- "peerfly.com"
- ]
- },
- "Peerius": {
- "properties": [
- "peerius.com"
- ],
- "resources": [
- "peerius.com"
- ]
- },
- "Performancing": {
- "properties": [
- "performancing.com"
- ],
- "resources": [
- "performancing.com"
- ]
- },
- "PerimeterX": {
- "properties": [
- "perimeterx.com"
- ],
- "resources": [
- "perimeterx.com"
- ]
- },
- "PersianStat.com": {
- "properties": [
- "persianstat.com"
- ],
- "resources": [
- "persianstat.com"
- ]
- },
- "Pheedo": {
- "properties": [
- "pheedo.com"
- ],
- "resources": [
- "pheedo.com"
- ]
- },
- "Phonalytics": {
- "properties": [
- "phonalytics.com"
- ],
- "resources": [
- "phonalytics.com"
- ]
- },
- "phpMyVisites": {
- "properties": [
- "phpmyvisites.us"
- ],
- "resources": [
- "phpmyvisites.us"
- ]
- },
- "Pictela": {
- "properties": [
- "pictela.com",
- "pictela.net"
- ],
- "resources": [
- "pictela.com",
- "pictela.net"
- ]
- },
- "PinPoll": {
- "properties": [
- "pinpoll.com"
- ],
- "resources": [
- "pinpoll.com"
- ]
- },
- "Pinterest": {
- "properties": [
- "pinterest.at",
- "pinterest.ca",
- "pinterest.ch",
- "pinterest.cl",
- "pinterest.co.kr",
- "pinterest.co.uk",
- "pinterest.com",
- "pinterest.com.au",
- "pinterest.com.mx",
- "pinterest.de",
- "pinterest.dk",
- "pinterest.es",
- "pinterest.fr",
- "pinterest.ie",
- "pinterest.jp",
- "pinterest.nz",
- "pinterest.pt",
- "pinterest.se"
- ],
- "resources": [
- "pinimg.com",
- "pinterest.com"
- ]
- },
- "Piwik": {
- "properties": [
- "piwik.org"
- ],
- "resources": [
- "piwik.org"
- ]
- },
- "PixAnalytics": {
- "properties": [
- "pixanalytics.com"
- ],
- "resources": [
- "pixanalytics.com"
- ]
- },
- "Pixel.sg": {
- "properties": [
- "pixel.sg"
- ],
- "resources": [
- "pixel.sg"
- ]
- },
- "Piximedia": {
- "properties": [
- "piximedia.com"
- ],
- "resources": [
- "piximedia.com"
- ]
- },
- "Pixlee": {
- "properties": [
- "pixlee.com"
- ],
- "resources": [
- "pixlee.com"
- ]
- },
- "PLATFORM ONE": {
- "properties": [
- "platform-one.co.jp",
- "www.platform-one.co.jp"
- ],
- "resources": [
- "platform-one.co.jp",
- "www.platform-one.co.jp"
- ]
- },
- "plista": {
- "properties": [
- "plista.com"
- ],
- "resources": [
- "plista.com"
- ]
- },
- "PocketCents": {
- "properties": [
- "pocketcents.com"
- ],
- "resources": [
- "pocketcents.com"
- ]
- },
- "Polar Mobile": {
- "properties": [
- "mediavoice.com"
- ],
- "resources": [
- "mediavoice.com",
- "polarmobile.com"
- ]
- },
- "Politads": {
- "properties": [
- "politads.com"
- ],
- "resources": [
- "politads.com"
- ]
- },
- "Polymorph": {
- "properties": [
- "getpolymorph.com"
- ],
- "resources": [
- "adsnative.com",
- "getpolymorph.com"
- ]
- },
- "Pontiflex": {
- "properties": [
- "pontiflex.com"
- ],
- "resources": [
- "pontiflex.com"
- ]
- },
- "Poool": {
- "properties": [
- "poool.fr"
- ],
- "resources": [
- "poool.fr"
- ]
- },
- "PopAds": {
- "properties": [
- "popads.net"
- ],
- "resources": [
- "popads.net",
- "popadscdn.net"
- ]
- },
- "PopRule": {
- "properties": [
- "gocampaignlive.com",
- "poprule.com"
- ],
- "resources": [
- "gocampaignlive.com",
- "poprule.com"
- ]
- },
- "Popunder.ru": {
- "properties": [
- "popunder.ru"
- ],
- "resources": [
- "popunder.ru"
- ]
- },
- "Po.st": {
- "properties": [
- "po.st"
- ],
- "resources": [
- "po.st"
- ]
- },
- "Powerlinks": {
- "properties": [
- "powerlinks.com"
- ],
- "resources": [
- "powerlinks.com"
- ]
- },
- "PPCProtect": {
- "properties": [
- "ppcprotect.com"
- ],
- "resources": [
- "ppcprotect.com"
- ]
- },
- "PrecisionClick": {
- "properties": [
- "precisionclick.com"
- ],
- "resources": [
- "precisionclick.com"
- ]
- },
- "PredictAd": {
- "properties": [
- "predictad.com"
- ],
- "resources": [
- "predictad.com"
- ]
- },
- "Pressflex": {
- "properties": [
- "blogads.com",
- "pressflex.com"
- ],
- "resources": [
- "blogads.com",
- "pressflex.com"
- ]
- },
- "Prime Visibility": {
- "properties": [
- "primevisibility.com"
- ],
- "resources": [
- "adcde.com",
- "addlvr.com",
- "adonnetwork.com",
- "adonnetwork.net",
- "adtrgt.com",
- "bannertgt.com",
- "cptgt.com",
- "cpvfeed.com",
- "cpvtgt.com",
- "dashboardad.net",
- "popcde.com",
- "primevisibility.com",
- "sdfje.com",
- "urtbk.com"
- ]
- },
- "Primis": {
- "properties": [
- "primis.tech"
- ],
- "resources": [
- "sekindo.com"
- ]
- },
- "PrismApp": {
- "properties": [
- "prismapp.io"
- ],
- "resources": [
- "prismapp.io"
- ]
- },
- "Proclivity": {
- "properties": [
- "proclivitysystems.com",
- "pswec.com"
- ],
- "resources": [
- "proclivitymedia.com",
- "proclivitysystems.com",
- "pswec.com"
- ]
- },
- "Project Wonderful": {
- "properties": [
- "projectwonderful.com"
- ],
- "resources": [
- "projectwonderful.com"
- ]
- },
- "PrometheusIntelligenceTechnology": {
- "properties": [
- "prometheusintelligencetechnology.com"
- ],
- "resources": [
- "prometheusintelligencetechnology.com"
- ]
- },
- "Pronunciator": {
- "properties": [
- "pronunciator.com",
- "visitorville.com"
- ],
- "resources": [
- "pronunciator.com",
- "visitorville.com"
- ]
- },
- "Propeller Ads": {
- "properties": [
- "propellerads.com"
- ],
- "resources": [
- "propellerads.com"
- ]
- },
- "Prosperent": {
- "properties": [
- "prosperent.com"
- ],
- "resources": [
- "prosperent.com"
- ]
- },
- "Protected Media": {
- "properties": [
- "ad-score.com",
- "protected.media"
- ],
- "resources": [
- "ad-score.com",
- "protected.media"
- ]
- },
- "Provers": {
- "properties": [
- "provers.pro"
- ],
- "resources": [
- "provers.pro"
- ]
- },
- "Psonstrentie": {
- "properties": [
- "psonstrentie.info"
- ],
- "resources": [
- "psonstrentie.info"
- ]
- },
- "Public-Idées": {
- "properties": [
- "publicidees.com"
- ],
- "resources": [
- "publicidees.com"
- ]
- },
- "Publishers Clearing House": {
- "properties": [
- "pch.com"
- ],
- "resources": [
- "pch.com"
- ]
- },
- "PubMatic": {
- "properties": [
- "pubmatic.com"
- ],
- "resources": [
- "pubmatic.com",
- "revinet.com"
- ]
- },
- "PulsePoint": {
- "properties": [
- "pulsepoint.com"
- ],
- "resources": [
- "pulsepoint.com"
- ]
- },
- "PunchTab": {
- "properties": [
- "punchtab.com"
- ],
- "resources": [
- "punchtab.com"
- ]
- },
- "quadrantOne": {
- "properties": [
- "quadrantone.com"
- ],
- "resources": [
- "quadrantone.com"
- ]
- },
- "Quake Marketing": {
- "properties": [
- "quakemarketing.com"
- ],
- "resources": [
- "quakemarketing.com"
- ]
- },
- "Qualaroo": {
- "properties": [
- "qualaroo.com"
- ],
- "resources": [
- "kissinsights.com",
- "qualaroo.com"
- ]
- },
- "Quantcast": {
- "properties": [
- "quantcast.com",
- "quantserve.com"
- ],
- "resources": [
- "quantcast.com",
- "quantserve.com"
- ]
- },
- "QuantumAdvertising": {
- "properties": [
- "quantum-advertising.com"
- ],
- "resources": [
- "quantum-advertising.com"
- ]
- },
- "QuinStreet": {
- "properties": [
- "quinstreet.com",
- "thecounter.com"
- ],
- "resources": [
- "qnsr.com",
- "qsstats.com",
- "quinstreet.com",
- "thecounter.com"
- ]
- },
- "Quintelligence": {
- "properties": [
- "quintelligence.com"
- ],
- "resources": [
- "quintelligence.com"
- ]
- },
- "QUISMA": {
- "properties": [
- "quisma.com"
- ],
- "resources": [
- "iaded.com",
- "quisma.com",
- "quismatch.com",
- "xaded.com",
- "xmladed.com"
- ]
- },
- "RadarURL": {
- "properties": [
- "radarurl.com"
- ],
- "resources": [
- "radarurl.com"
- ]
- },
- "Radial": {
- "properties": [
- "radial.com"
- ],
- "resources": [
- "gsicommerce.com",
- "gsimedia.net"
- ]
- },
- "Radiate Media": {
- "properties": [
- "gtnetwork.com.au",
- "solesolution.com"
- ],
- "resources": [
- "gtnetwork.com.au",
- "matchbin.com",
- "radiatemedia.com",
- "solesolution.com"
- ]
- },
- "RadiumOne": {
- "properties": [
- "radiumone.com"
- ],
- "resources": [
- "gwallet.com",
- "radiumone.com"
- ]
- },
- "Radius Marketing": {
- "properties": [
- "radiusmarketing.com"
- ],
- "resources": [
- "radiusmarketing.com"
- ]
- },
- "Rambler": {
- "properties": [
- "rambler.ru"
- ],
- "resources": [
- "rambler.ru"
- ]
- },
- "Rapleaf": {
- "properties": [
- "rapleaf.com",
- "rlcdn.com"
- ],
- "resources": [
- "rapleaf.com",
- "rlcdn.com"
- ]
- },
- "ReachLocal": {
- "properties": [
- "reachlocal.com",
- "rlcdn.net"
- ],
- "resources": [
- "reachlocal.com",
- "rlcdn.net"
- ]
- },
- "React2Media": {
- "properties": [
- "react2media.com"
- ],
- "resources": [
- "react2media.com"
- ]
- },
- "reddit": {
- "properties": [
- "reddit.com"
- ],
- "resources": [
- "reddit.com"
- ]
- },
- "Redux Media": {
- "properties": [
- "reduxmedia.com"
- ],
- "resources": [
- "reduxmedia.com"
- ]
- },
- "Rekko": {
- "properties": [
- "convertglobal.com",
- "rekko.com"
- ],
- "resources": [
- "convertglobal.com",
- "rekko.com"
- ]
- },
- "Reklamport": {
- "properties": [
- "reklamport.com"
- ],
- "resources": [
- "reklamport.com"
- ]
- },
- "Reklam Store": {
- "properties": [
- "reklamstore.com"
- ],
- "resources": [
- "reklamstore.com"
- ]
- },
- "Reklamz": {
- "properties": [
- "reklamz.com"
- ],
- "resources": [
- "reklamz.com"
- ]
- },
- "Relevad": {
- "properties": [
- "relestar.com",
- "relevad.com"
- ],
- "resources": [
- "relestar.com",
- "relevad.com"
- ]
- },
- "Renegade Internet": {
- "properties": [
- "advertserve.com",
- "renegadeinternet.com"
- ],
- "resources": [
- "advertserve.com",
- "renegadeinternet.com"
- ]
- },
- "Reporo": {
- "properties": [
- "reporo.com"
- ],
- "resources": [
- "buzzcity.com"
- ]
- },
- "Research Now": {
- "properties": [
- "researchnow.com",
- "valuedopinions.co.uk"
- ],
- "resources": [
- "researchnow.com",
- "valuedopinions.co.uk"
- ]
- },
- "ResolutionMedia": {
- "properties": [
- "nonstoppartner.net"
- ],
- "resources": [
- "nonstoppartner.net"
- ]
- },
- "Resolution Media": {
- "properties": [
- "resolutionmedia.com"
- ],
- "resources": [
- "resolutionmedia.com"
- ]
- },
- "Resonate": {
- "properties": [
- "resonateinsights.com",
- "resonatenetworks.com"
- ],
- "resources": [
- "reson8.com",
- "resonateinsights.com",
- "resonatenetworks.com"
- ]
- },
- "Responsys": {
- "properties": [
- "responsys.com"
- ],
- "resources": [
- "responsys.com"
- ]
- },
- "Retail Automata": {
- "properties": [
- "retailautomata.com"
- ],
- "resources": [
- "retailautomata.com"
- ]
- },
- "ReTargeter": {
- "properties": [
- "retargeter.com"
- ],
- "resources": [
- "retargeter.com"
- ]
- },
- "Retirement Living": {
- "properties": [
- "blvdstatus.com",
- "retirement-living.com"
- ],
- "resources": [
- "blvdstatus.com",
- "retirement-living.com"
- ]
- },
- "RevContent": {
- "properties": [
- "revcontent.com"
- ],
- "resources": [
- "revcontent.com"
- ]
- },
- "RevenueMax": {
- "properties": [
- "revenuemax.de"
- ],
- "resources": [
- "revenuemax.de"
- ]
- },
- "Revtracks": {
- "properties": [
- "revtrax.com"
- ],
- "resources": [
- "revtrax.com"
- ]
- },
- "Rhythm": {
- "properties": [
- "rhythmone.com"
- ],
- "resources": [
- "1rx.io",
- "rhythmnewmedia.com",
- "rhythmone.com",
- "rhythmxchange.com",
- "rnmd.net"
- ]
- },
- "RichAudience": {
- "properties": [
- "richaudience.com"
- ],
- "resources": [
- "richaudience.com"
- ]
- },
- "RichRelevance": {
- "properties": [
- "richrelevance.com"
- ],
- "resources": [
- "richrelevance.com"
- ]
- },
- "RightAction": {
- "properties": [
- "rightaction.com"
- ],
- "resources": [
- "rightaction.com"
- ]
- },
- "RIM": {
- "properties": [
- "global.blackberry.com",
- "laptopverge.com"
- ],
- "resources": [
- "global.blackberry.com",
- "laptopverge.com",
- "rim.com",
- "scoreloop.com"
- ]
- },
- "Ringier": {
- "properties": [
- "ringier.cz"
- ],
- "resources": [
- "ringier.cz"
- ]
- },
- "RMBN": {
- "properties": [
- "traforet.com"
- ],
- "resources": [
- "rmbn.net",
- "rmbn.ru",
- "traforet.com"
- ]
- },
- "RMM": {
- "properties": [
- "rmmonline.com"
- ],
- "resources": [
- "rmmonline.com"
- ]
- },
- "Rocket Fuel": {
- "properties": [
- "rfihub.com",
- "rfihub.net",
- "rocketfuel.com"
- ],
- "resources": [
- "rfihub.com",
- "rfihub.net",
- "rocketfuel.com",
- "ru4.com",
- "xplusone.com"
- ]
- },
- "Rollick": {
- "properties": [
- "gorollick.com"
- ],
- "resources": [
- "rollick.io"
- ]
- },
- "Rovion": {
- "properties": [
- "rovion.com"
- ],
- "resources": [
- "rovion.com"
- ]
- },
- "Roxr": {
- "properties": [
- "clicky.com",
- "roxr.net"
- ],
- "resources": [
- "clicky.com",
- "getclicky.com",
- "roxr.net",
- "staticstuff.net"
- ]
- },
- "rtk": {
- "properties": [
- "rtk.io"
- ],
- "resources": [
- "rtk.io"
- ]
- },
- "RubiconProject": {
- "properties": [
- "rubiconproject.com"
- ],
- "resources": [
- "adsbyisocket.com",
- "isocket.com",
- "rubiconproject.com"
- ]
- },
- "RunAds": {
- "properties": [
- "runads.com"
- ],
- "resources": [
- "runads.com",
- "rundsp.com"
- ]
- },
- "RuTarget": {
- "properties": [
- "rutarget.ru"
- ],
- "resources": [
- "rutarget.ru"
- ]
- },
- "Sabavision": {
- "properties": [
- "sabavision.com"
- ],
- "resources": [
- "sabavision.com"
- ]
- },
- "Sabre": {
- "properties": [
- "reztrack.com",
- "sabre.com",
- "sabrehospitality.com"
- ],
- "resources": [
- "reztrack.com",
- "sabre.com",
- "sabrehospitality.com"
- ]
- },
- "Safecount": {
- "properties": [
- "safecount.net"
- ],
- "resources": [
- "dl-rms.com",
- "dlqm.net",
- "questionmarket.com",
- "safecount.net"
- ]
- },
- "SageMetrics": {
- "properties": [
- "sagemetrics.com"
- ],
- "resources": [
- "sageanalyst.net",
- "sagemetrics.com"
- ]
- },
- "Salesforce.com": {
- "properties": [
- "force.com",
- "salesforce.com",
- "trailblazer.me"
- ],
- "resources": [
- "documentforce.com",
- "force.com",
- "forcesslreports.com",
- "forceusercontent.com",
- "lightning.com",
- "salesforce-communities.com",
- "salesforce-hub.com",
- "salesforce.com",
- "salesforceliveagent.com",
- "trailblazer.me",
- "visualforce.com"
- ]
- },
- "Salesintelligence": {
- "properties": [
- "salesintelligence.pl"
- ],
- "resources": [
- "plugin.management"
- ]
- },
- "Samurai Factory": {
- "properties": [
- "samurai-factory.jp",
- "shinobi.jp"
- ],
- "resources": [
- "samurai-factory.jp",
- "shinobi.jp"
- ]
- },
- "SAP": {
- "properties": [
- "sap.com"
- ],
- "resources": [
- "sap.com",
- "seewhy.com"
- ]
- },
- "Sapient": {
- "properties": [
- "bridgetrack.com",
- "sapient.com"
- ],
- "resources": [
- "bridgetrack.com",
- "sapient.com"
- ]
- },
- "SAS": {
- "properties": [
- "aimatch.com",
- "sas.com"
- ],
- "resources": [
- "aimatch.com",
- "sas.com"
- ]
- },
- "SAY": {
- "properties": [
- "saymedia.com",
- "typepad.com",
- "videoegg.com"
- ],
- "resources": [
- "saymedia.com",
- "typepad.com",
- "videoegg.com"
- ]
- },
- "Scandinavian AdNetworks": {
- "properties": [
- "scandinavianadnetworks.com"
- ],
- "resources": [
- "scandinavianadnetworks.com"
- ]
- },
- "ScribeFire": {
- "properties": [
- "scribefire.com"
- ],
- "resources": [
- "scribefire.com"
- ]
- },
- "Scribol": {
- "properties": [
- "scribol.com"
- ],
- "resources": [
- "scribol.com"
- ]
- },
- "SearchForce": {
- "properties": [
- "searchforce.com",
- "searchforce.net"
- ],
- "resources": [
- "searchforce.com",
- "searchforce.net"
- ]
- },
- "Seevast": {
- "properties": [
- "kanoodle.com"
- ],
- "resources": [
- "kanoodle.com",
- "pulse360.com",
- "seevast.com",
- "syndigonetworks.com"
- ]
- },
- "SeeVolution": {
- "properties": [
- "seevolution.com",
- "svlu.net"
- ],
- "resources": [
- "seevolution.com",
- "svlu.net"
- ]
- },
- "Segment.io": {
- "properties": [
- "segment.io"
- ],
- "resources": [
- "segment.io"
- ]
- },
- "Selectable Media": {
- "properties": [
- "selectablemedia.com"
- ],
- "resources": [
- "nabbr.com",
- "selectablemedia.com"
- ]
- },
- "Semantiqo": {
- "properties": [
- "semantiqo.com"
- ],
- "resources": [
- "semantiqo.com"
- ]
- },
- "Semasio": {
- "properties": [
- "semasio.com"
- ],
- "resources": [
- "semasio.com",
- "semasio.net"
- ]
- },
- "SendPulse": {
- "properties": [
- "sendpulse.com"
- ],
- "resources": [
- "sendpulse.com"
- ]
- },
- "Service4refresh": {
- "properties": [
- "service4refresh.info"
- ],
- "resources": [
- "service4refresh.info"
- ]
- },
- "SessionCam": {
- "properties": [
- "sessioncam.com"
- ],
- "resources": [
- "sessioncam.com"
- ]
- },
- "SevenAds": {
- "properties": [
- "sevenads.net"
- ],
- "resources": [
- "sevenads.net"
- ]
- },
- "SexInYourCity": {
- "properties": [
- "sexinyourcity.com"
- ],
- "resources": [
- "sexinyourcity.com"
- ]
- },
- "ShaftTraffic": {
- "properties": [
- "shafttraffic.com"
- ],
- "resources": [
- "libertystmedia.com",
- "shafttraffic.com"
- ]
- },
- "Shareaholic": {
- "properties": [
- "shareaholic.com"
- ],
- "resources": [
- "shareaholic.com"
- ]
- },
- "ShareASale": {
- "properties": [
- "shareasale.com"
- ],
- "resources": [
- "shareasale.com"
- ]
- },
- "ShareThis": {
- "properties": [
- "sharethis.com"
- ],
- "resources": [
- "sharethis.com"
- ]
- },
- "Sharethrough": {
- "properties": [
- "sharethrough.com"
- ],
- "resources": [
- "sharethrough.com"
- ]
- },
- "ShinyStat": {
- "properties": [
- "shinystat.com"
- ],
- "resources": [
- "shinystat.com"
- ]
- },
- "Shopzilla": {
- "properties": [
- "shopzilla.com"
- ],
- "resources": [
- "shopzilla.com"
- ]
- },
- "Shortest": {
- "properties": [
- "shorte.st"
- ],
- "resources": [
- "shorte.st"
- ]
- },
- "SiftScience": {
- "properties": [
- "sift.com"
- ],
- "resources": [
- "siftscience.com"
- ]
- },
- "Signifyd": {
- "properties": [
- "signifyd.com"
- ],
- "resources": [
- "signifyd.com"
- ]
- },
- "Silverpop": {
- "properties": [
- "mkt51.net",
- "silverpop.com"
- ],
- "resources": [
- "mkt51.net",
- "pages05.net",
- "silverpop.com",
- "vtrenz.net"
- ]
- },
- "Simpli.fi": {
- "properties": [
- "simpli.fi"
- ],
- "resources": [
- "simpli.fi"
- ]
- },
- "SiteScout": {
- "properties": [
- "sitescout.com"
- ],
- "resources": [
- "sitescout.com"
- ]
- },
- "Six Apart": {
- "properties": [
- "movabletype.com",
- "sixapart.com"
- ],
- "resources": [
- "movabletype.com",
- "sixapart.com"
- ]
- },
- "Skimlinks": {
- "properties": [
- "skimlinks.com",
- "skimresources.com"
- ],
- "resources": [
- "skimlinks.com",
- "skimresources.com"
- ]
- },
- "Skribit": {
- "properties": [
- "paulstamatiou.com"
- ],
- "resources": [
- "paulstamatiou.com",
- "skribit.com"
- ]
- },
- "Skupe Net": {
- "properties": [
- "adcentriconline.com",
- "skupenet.com"
- ],
- "resources": [
- "adcentriconline.com",
- "skupenet.com"
- ]
- },
- "Smaato": {
- "properties": [
- "smaato.com"
- ],
- "resources": [
- "smaato.com"
- ]
- },
- "SmartAdServer": {
- "properties": [
- "smartadserver.com"
- ],
- "resources": [
- "smartadserver.com"
- ]
- },
- "Smartlook": {
- "properties": [
- "smartlook.com"
- ],
- "resources": [
- "smartlook.com"
- ]
- },
- "SmartyAds": {
- "properties": [
- "smartyads.com"
- ],
- "resources": [
- "smartyads.com"
- ]
- },
- "Smi": {
- "properties": [
- "24smi.net"
- ],
- "resources": [
- "24smi.net"
- ]
- },
- "Smiley Media": {
- "properties": [
- "smileymedia.com"
- ],
- "resources": [
- "smileymedia.com"
- ]
- },
- "Smowtion": {
- "properties": [
- "smowtion.com"
- ],
- "resources": [
- "smowtion.com"
- ]
- },
- "Snap": {
- "properties": [
- "snap.com"
- ],
- "resources": [
- "snap.com"
- ]
- },
- "SnapEngage": {
- "properties": [
- "snapengage.com"
- ],
- "resources": [
- "snapengage.com"
- ]
- },
- "Snoobi": {
- "properties": [
- "snoobi.fi"
- ],
- "resources": [
- "snoobi.com",
- "snoobi.fi"
- ]
- },
- "SocialChorus": {
- "properties": [
- "socialchorus.com"
- ],
- "resources": [
- "halogenmediagroup.com",
- "halogennetwork.com",
- "socialchorus.com"
- ]
- },
- "SocialInterface": {
- "properties": [
- "socialinterface.com"
- ],
- "resources": [
- "ratevoice.com",
- "socialinterface.com"
- ]
- },
- "SocialTwist": {
- "properties": [
- "socialtwist.com"
- ],
- "resources": [
- "socialtwist.com"
- ]
- },
- "sociomantic labs": {
- "properties": [
- "sociomantic.com"
- ],
- "resources": [
- "sociomantic.com"
- ]
- },
- "Socital": {
- "properties": [
- "socital.com"
- ],
- "resources": [
- "socital.com"
- ]
- },
- "Sojern": {
- "properties": [
- "sojern.com"
- ],
- "resources": [
- "sojern.com"
- ]
- },
- "SomoAudience": {
- "properties": [
- "somoaudience.com"
- ],
- "resources": [
- "somoaudience.com"
- ]
- },
- "Sonobi": {
- "properties": [
- "sonobi.com"
- ],
- "resources": [
- "sonobi.com"
- ]
- },
- "sophus3": {
- "properties": [
- "sophus3.com"
- ],
- "resources": [
- "sophus3.co.uk",
- "sophus3.com"
- ]
- },
- "Sortable": {
- "properties": [
- "sortable.com"
- ],
- "resources": [
- "deployads.com"
- ]
- },
- "Sourcepoint": {
- "properties": [
- "sourcepoint.com"
- ],
- "resources": [
- "summerhamster.com"
- ]
- },
- "Sovrn": {
- "properties": [
- "sovrn.com"
- ],
- "resources": [
- "sovrn.com"
- ]
- },
- "Space Chimp Media": {
- "properties": [
- "spacechimpmedia.com"
- ],
- "resources": [
- "spacechimpmedia.com"
- ]
- },
- "SpareChange": {
- "properties": [
- "sparechange.io"
- ],
- "resources": [
- "sparechange.io"
- ]
- },
- "Sparklit": {
- "properties": [
- "adbutler.com",
- "sparklit.com"
- ],
- "resources": [
- "adbutler.com",
- "sparklit.com"
- ]
- },
- "Spark Studios": {
- "properties": [
- "sparkstudios.com"
- ],
- "resources": [
- "sparkstudios.com"
- ]
- },
- "Specific Media": {
- "properties": [
- "sitemeter.com",
- "specificmedia.com"
- ],
- "resources": [
- "adviva.co.uk",
- "adviva.net",
- "sitemeter.com",
- "specificclick.net",
- "specificmedia.com"
- ]
- },
- "Spectate": {
- "properties": [
- "spectate.com"
- ],
- "resources": [
- "spectate.com"
- ]
- },
- "Sponge": {
- "properties": [
- "spongegroup.com"
- ],
- "resources": [
- "spongegroup.com"
- ]
- },
- "Spongecell": {
- "properties": [
- "spongecell.com"
- ],
- "resources": [
- "spongecell.com"
- ]
- },
- "SponsorAds": {
- "properties": [
- "sponsorads.de"
- ],
- "resources": [
- "sponsorads.de"
- ]
- },
- "Spot200": {
- "properties": [
- "spot200.com"
- ],
- "resources": [
- "spot200.com"
- ]
- },
- "SpotX": {
- "properties": [
- "spotx.tv"
- ],
- "resources": [
- "spotx.tv"
- ]
- },
- "SpotXchange": {
- "properties": [
- "spotxchange.com"
- ],
- "resources": [
- "spotxcdn.com",
- "spotxchange.com"
- ]
- },
- "Spring Metrics": {
- "properties": [
- "springmetrics.com"
- ],
- "resources": [
- "springmetrics.com"
- ]
- },
- "SpringServe": {
- "properties": [
- "springserve.com"
- ],
- "resources": [
- "springserve.com"
- ]
- },
- "Sputnik.ru": {
- "properties": [
- "sputnik.ru"
- ],
- "resources": [
- "sputnik.ru"
- ]
- },
- "StackAdapt": {
- "properties": [
- "stackadapt.com"
- ],
- "resources": [
- "stackadapt.com"
- ]
- },
- "StackTrack": {
- "properties": [
- "stat-track.com"
- ],
- "resources": [
- "stat-track.com"
- ]
- },
- "StarGames": {
- "properties": [
- "stargames.net",
- "stargamesaffiliate.com"
- ],
- "resources": [
- "stargames.net",
- "stargamesaffiliate.com"
- ]
- },
- "stat4u": {
- "properties": [
- "4u.pl"
- ],
- "resources": [
- "4u.pl"
- ]
- },
- "StatCounter": {
- "properties": [
- "statcounter.com"
- ],
- "resources": [
- "statcounter.com"
- ]
- },
- "Statisfy": {
- "properties": [
- "statisfy.net"
- ],
- "resources": [
- "statisfy.net"
- ]
- },
- "STATSIT": {
- "properties": [
- "statsit.com"
- ],
- "resources": [
- "statsit.com"
- ]
- },
- "SteelHouse": {
- "properties": [
- "steelhouse.com",
- "steelhousemedia.com"
- ],
- "resources": [
- "steelhouse.com",
- "steelhousemedia.com"
- ]
- },
- "Storeland": {
- "properties": [
- "storeland.ru"
- ],
- "resources": [
- "storeland.ru"
- ]
- },
- "Storygize": {
- "properties": [
- "storygize.com"
- ],
- "resources": [
- "storygize.com",
- "storygize.net"
- ]
- },
- "Stratigent": {
- "properties": [
- "stratigent.com"
- ],
- "resources": [
- "stratigent.com"
- ]
- },
- "Streamray": {
- "properties": [
- "cams.com",
- "streamray.com"
- ],
- "resources": [
- "cams.com",
- "streamray.com"
- ]
- },
- "StrikeAd": {
- "properties": [
- "strikead.com"
- ],
- "resources": [
- "strikead.com"
- ]
- },
- "Stripe": {
- "properties": [
- "stripe.com"
- ],
- "resources": [
- "stripe.network"
- ]
- },
- "StrongMail": {
- "properties": [
- "strongmail.com"
- ],
- "resources": [
- "popularmedia.com",
- "strongmail.com"
- ]
- },
- "Struq": {
- "properties": [
- "struq.com"
- ],
- "resources": [
- "struq.com"
- ]
- },
- "StumbleUpon": {
- "properties": [
- "stumbleupon.com"
- ],
- "resources": [
- "stumble-upon.com",
- "stumbleupon.com"
- ]
- },
- "Sublime Skinz": {
- "properties": [
- "sublime.xyz"
- ],
- "resources": [
- "ayads.co",
- "sublime.xyz"
- ]
- },
- "Suite 66": {
- "properties": [
- "suite66.com"
- ],
- "resources": [
- "suite66.com"
- ]
- },
- "Summit": {
- "properties": [
- "summitmedia.co.uk",
- "www.summit.co.uk"
- ],
- "resources": [
- "summitmedia.co.uk",
- "www.summit.co.uk"
- ]
- },
- "Superfish": {
- "properties": [
- "superfish.com"
- ],
- "resources": [
- "superfish.com"
- ]
- },
- "SupersonicAds": {
- "properties": [
- "supersonicads.com"
- ],
- "resources": [
- "supersonicads.com"
- ]
- },
- "Survata": {
- "properties": [
- "survata.com"
- ],
- "resources": [
- "survata.com"
- ]
- },
- "SwiftMining": {
- "properties": [
- "swiftmining.win"
- ],
- "resources": [
- "swiftmining.win"
- ]
- },
- "Switch": {
- "properties": [
- "switchadhub.com",
- "switchconcepts.com"
- ],
- "resources": [
- "switchadhub.com",
- "switchads.com",
- "switchconcepts.co.uk",
- "switchconcepts.com"
- ]
- },
- "Swoop": {
- "properties": [
- "swoop.com"
- ],
- "resources": [
- "swoop.com"
- ]
- },
- "SymphonyAM": {
- "properties": [
- "factortg.com"
- ],
- "resources": [
- "factortg.com"
- ]
- },
- "Synacor": {
- "properties": [
- "synacor.com"
- ],
- "resources": [
- "synacor.com"
- ]
- },
- "Syncapse": {
- "properties": [
- "clickable.net",
- "syncapse.com"
- ],
- "resources": [
- "clickable.net",
- "syncapse.com"
- ]
- },
- "Syrup Ad": {
- "properties": [
- "adotsolution.com"
- ],
- "resources": [
- "adotsolution.com"
- ]
- },
- "Taboola": {
- "properties": [
- "taboola.com"
- ],
- "resources": [
- "perfectmarket.com",
- "taboola.com"
- ]
- },
- "Tailsweep": {
- "properties": [
- "tailsweep.com"
- ],
- "resources": [
- "tailsweep.com"
- ]
- },
- "Taleria": {
- "properties": [
- "telaria.com"
- ],
- "resources": [
- "freeskreen.com"
- ]
- },
- "Tapad": {
- "properties": [
- "tapad.com"
- ],
- "resources": [
- "tapad.com"
- ]
- },
- "Tapgage": {
- "properties": [
- "bizmey.com",
- "tapgage.com"
- ],
- "resources": [
- "bizmey.com",
- "tapgage.com"
- ]
- },
- "TapIt!": {
- "properties": [
- "tapit.com"
- ],
- "resources": [
- "tapit.com"
- ]
- },
- "Tap.me": {
- "properties": [
- "tap.me"
- ],
- "resources": [
- "tap.me"
- ]
- },
- "Targetix": {
- "properties": [
- "targetix.net"
- ],
- "resources": [
- "targetix.net"
- ]
- },
- "Tatto Media": {
- "properties": [
- "tattomedia.com"
- ],
- "resources": [
- "quicknoodles.com",
- "tattomedia.com"
- ]
- },
- "Teadma": {
- "properties": [
- "teadma.com"
- ],
- "resources": [
- "teadma.com"
- ]
- },
- "Teads.tv": {
- "properties": [
- "teads.tv"
- ],
- "resources": [
- "teads.tv"
- ]
- },
- "Tealium": {
- "properties": [
- "tealium.com"
- ],
- "resources": [
- "tealiumiq.com"
- ]
- },
- "Technorati": {
- "properties": [
- "technorati.com"
- ],
- "resources": [
- "technorati.com",
- "technoratimedia.com"
- ]
- },
- "TechSolutions": {
- "properties": [
- "techsolutions.com.tw"
- ],
- "resources": [
- "techsolutions.com.tw"
- ]
- },
- "TellApart": {
- "properties": [
- "tellapart.com",
- "tellapt.com"
- ],
- "resources": [
- "tellapart.com",
- "tellapt.com"
- ]
- },
- "Telstra": {
- "properties": [
- "sensis.com.au",
- "sensisdata.com.au",
- "telstra.com.au"
- ],
- "resources": [
- "sensis.com.au",
- "sensisdata.com.au",
- "sensisdigitalmedia.com.au",
- "telstra.com.au"
- ]
- },
- "TENSQUARE": {
- "properties": [
- "tensquare.com"
- ],
- "resources": [
- "tensquare.com"
- ]
- },
- "Terra": {
- "properties": [
- "eztargetmedia.com",
- "terra.com.br",
- "www.terra.com.br"
- ],
- "resources": [
- "eztargetmedia.com",
- "terra.com.br",
- "www.terra.com.br"
- ]
- },
- "The Heron Partnership": {
- "properties": [
- "marinsm.com"
- ],
- "resources": [
- "heronpartners.com.au",
- "marinsm.com",
- "marinsoftware.com"
- ]
- },
- "The Numa Group": {
- "properties": [
- "hittail.com",
- "thenumagroup.com"
- ],
- "resources": [
- "hittail.com",
- "thenumagroup.com"
- ]
- },
- "The Search Agency": {
- "properties": [
- "thesearchagency.com"
- ],
- "resources": [
- "thesearchagency.com",
- "thesearchagency.net"
- ]
- },
- "The Trade Desk": {
- "properties": [
- "thetradedesk.com"
- ],
- "resources": [
- "adsrvr.org",
- "thetradedesk.com"
- ]
- },
- "ThingLink": {
- "properties": [
- "thinglink.com"
- ],
- "resources": [
- "thinglink.com"
- ]
- },
- "Think Realtime": {
- "properties": [
- "echosearch.com",
- "thinkrealtime.com"
- ],
- "resources": [
- "echosearch.com",
- "esm1.net",
- "thinkrealtime.com"
- ]
- },
- "Thismoment": {
- "properties": [
- "thismoment.com"
- ],
- "resources": [
- "thismoment.com"
- ]
- },
- "Thummit": {
- "properties": [
- "thummit.com"
- ],
- "resources": [
- "thummit.com"
- ]
- },
- "Tinder": {
- "properties": [
- "carbonads.com",
- "tinder.com"
- ],
- "resources": [
- "carbonads.com",
- "tinder.com"
- ]
- },
- "TiqIQ": {
- "properties": [
- "tiqiq.com"
- ],
- "resources": [
- "tiqiq.com"
- ]
- },
- "Tisoomi": {
- "properties": [
- "adternal.com",
- "tisoomi.com"
- ],
- "resources": [
- "adternal.com",
- "tisoomi.com"
- ]
- },
- "TLVMedia": {
- "properties": [
- "tlvmedia.com"
- ],
- "resources": [
- "tlvmedia.com"
- ]
- },
- "TNS": {
- "properties": [
- "statistik-gallup.net",
- "tns-counter.ru",
- "tns-cs.net",
- "tnsglobal.com"
- ],
- "resources": [
- "sesamestats.com",
- "statistik-gallup.net",
- "tns-counter.ru",
- "tns-cs.net",
- "tnsglobal.com"
- ]
- },
- "Todacell": {
- "properties": [
- "todacell.com"
- ],
- "resources": [
- "todacell.com"
- ]
- },
- "ToneFuse": {
- "properties": [
- "tonefuse.com"
- ],
- "resources": [
- "tonefuse.com"
- ]
- },
- "ToneMedia": {
- "properties": [
- "clickfuse.com"
- ],
- "resources": [
- "clickfuse.com",
- "tonemedia.com"
- ]
- },
- "tongdun.cn": {
- "properties": [
- "tongdun.cn"
- ],
- "resources": [
- "fraudmetrix.cn",
- "tongdun.net"
- ]
- },
- "Topsy": {
- "properties": [
- "topsy.com"
- ],
- "resources": [
- "topsy.com"
- ]
- },
- "TouchCommerce": {
- "properties": [
- "nuance.com"
- ],
- "resources": [
- "inq.com",
- "nuance.com",
- "touchcommerce.com"
- ]
- },
- "TraceMyIP.org": {
- "properties": [
- "tracemyip.org"
- ],
- "resources": [
- "tracemyip.org"
- ]
- },
- "TrackingSoft": {
- "properties": [
- "roia.biz",
- "trackingsoft.com"
- ],
- "resources": [
- "roia.biz",
- "trackingsoft.com"
- ]
- },
- "Trackset": {
- "properties": [
- "trackset.com"
- ],
- "resources": [
- "trackset.com"
- ]
- },
- "Tradedoubler": {
- "properties": [
- "tradedoubler.com"
- ],
- "resources": [
- "tradedoubler.com"
- ]
- },
- "TradeTracker": {
- "properties": [
- "tradetracker.com"
- ],
- "resources": [
- "tradetracker.com",
- "tradetracker.net"
- ]
- },
- "TrafficHaus": {
- "properties": [
- "traffichaus.com",
- "traffichouse.com"
- ],
- "resources": [
- "traffichaus.com",
- "traffichouse.com"
- ]
- },
- "TrafficRevenue": {
- "properties": [
- "trafficrevenue.net"
- ],
- "resources": [
- "trafficrevenue.net"
- ]
- },
- "TrafficScore": {
- "properties": [
- "trafficscore.com"
- ],
- "resources": [
- "trafficscore.com"
- ]
- },
- "Traffiq": {
- "properties": [
- "traffiq.com"
- ],
- "resources": [
- "traffiq.com"
- ]
- },
- "Trafmag": {
- "properties": [
- "trafmag.com"
- ],
- "resources": [
- "trafmag.com"
- ]
- },
- "Traverse": {
- "properties": [
- "traversedata.com"
- ],
- "resources": [
- "traversedlp.com"
- ]
- },
- "Travora Media": {
- "properties": [
- "travoramedia.com"
- ],
- "resources": [
- "traveladnetwork.com",
- "traveladvertising.com",
- "travoramedia.com"
- ]
- },
- "Tremor Video": {
- "properties": [
- "tremorvideo.com"
- ],
- "resources": [
- "scanscout.com",
- "tmnetads.com",
- "tremorhub.com",
- "tremormedia.com",
- "tremorvideo.com"
- ]
- },
- "Triggit": {
- "properties": [
- "triggit.com"
- ],
- "resources": [
- "triggit.com"
- ]
- },
- "TripleLift": {
- "properties": [
- "triplelift.com"
- ],
- "resources": [
- "3lift.com",
- "triplelift.com"
- ]
- },
- "Trovus": {
- "properties": [
- "trovus.co.uk",
- "www.trovus.co.uk"
- ],
- "resources": [
- "trovus.co.uk",
- "www.trovus.co.uk"
- ]
- },
- "TruEffect": {
- "properties": [
- "adlegend.com",
- "trueffect.com"
- ],
- "resources": [
- "adlegend.com",
- "trueffect.com"
- ]
- },
- "Trumba": {
- "properties": [
- "trumba.com"
- ],
- "resources": [
- "trumba.com"
- ]
- },
- "TRUSTe": {
- "properties": [
- "truste.com"
- ],
- "resources": [
- "truste.com"
- ]
- },
- "TrustX": {
- "properties": [
- "trustx.org"
- ],
- "resources": [
- "trustx.org"
- ]
- },
- "TubeMogul": {
- "properties": [
- "tmogul.com",
- "tubemogul.com"
- ],
- "resources": [
- "tmogul.com",
- "tubemogul.com"
- ]
- },
- "TurnTo": {
- "properties": [
- "turntonetworks.com"
- ],
- "resources": [
- "turnto.com",
- "turntonetworks.com"
- ]
- },
- "Tweetboard": {
- "properties": [
- "tweetboard.com"
- ],
- "resources": [
- "tweetboard.com"
- ]
- },
- "Twelvefold": {
- "properties": [
- "buzzlogic.com",
- "twelvefold.com"
- ],
- "resources": [
- "buzzlogic.com",
- "twelvefold.com"
- ]
- },
- "Twitter": {
- "properties": [
- "digits.com",
- "fabric.io",
- "tweetdeck.com",
- "twitter.com",
- "twitter.jp"
- ],
- "resources": [
- "ads-twitter.com",
- "fabric.io",
- "tweetdeck.com",
- "twimg.com",
- "twitter.com",
- "twitter.jp"
- ]
- },
- "Twitter Counter": {
- "properties": [
- "twittercounter.com"
- ],
- "resources": [
- "twittercounter.com"
- ]
- },
- "Twyn Group": {
- "properties": [
- "twyn-group.com",
- "twyn.com"
- ],
- "resources": [
- "twyn-group.com",
- "twyn.com"
- ]
- },
- "Tyroo": {
- "properties": [
- "tyroo.com"
- ],
- "resources": [
- "tyroo.com"
- ]
- },
- "UberMedia": {
- "properties": [
- "tweetup.com",
- "ubermedia.com"
- ],
- "resources": [
- "tweetup.com",
- "ubermedia.com"
- ]
- },
- "UberTags": {
- "properties": [
- "ubertags.com"
- ],
- "resources": [
- "ubertags.com"
- ]
- },
- "ucfunnel": {
- "properties": [
- "ucfunnel.com"
- ],
- "resources": [
- "aralego.com",
- "ucfunnel.com"
- ]
- },
- "uCoz": {
- "properties": [
- "ucoz.ae",
- "ucoz.com",
- "ucoz.fr",
- "ucoz.net",
- "ucoz.ru"
- ],
- "resources": [
- "ucoz.ae",
- "ucoz.br",
- "ucoz.com",
- "ucoz.du",
- "ucoz.fr",
- "ucoz.net",
- "ucoz.ru"
- ]
- },
- "Umbel": {
- "properties": [
- "umbel.com"
- ],
- "resources": [
- "umbel.com"
- ]
- },
- "Unanimis": {
- "properties": [
- "unanimis.co.uk",
- "www.unanimis.co.uk"
- ],
- "resources": [
- "unanimis.co.uk",
- "www.unanimis.co.uk"
- ]
- },
- "Unbounce": {
- "properties": [
- "unbounce.com"
- ],
- "resources": [
- "unbounce.com"
- ]
- },
- "Underdog Media": {
- "properties": [
- "udmserve.net",
- "underdogmedia.com"
- ],
- "resources": [
- "udmserve.net",
- "underdogmedia.com"
- ]
- },
- "Undertone": {
- "properties": [
- "undertone.com",
- "undertonevideo.com"
- ],
- "resources": [
- "undertone.com",
- "undertonenetworks.com",
- "undertonevideo.com"
- ]
- },
- "UniQlick": {
- "properties": [
- "51network.com",
- "uniqlick.com",
- "wanmo.com"
- ],
- "resources": [
- "51network.com",
- "uniqlick.com",
- "wanmo.com"
- ]
- },
- "Unruly": {
- "properties": [
- "unruly.co"
- ],
- "resources": [
- "unrulymedia.com"
- ]
- },
- "Upland": {
- "properties": [
- "uplandsoftware.com"
- ],
- "resources": [
- "leadlander.com",
- "sf14g.com",
- "trackalyzer.com",
- "uplandsoftware.com"
- ]
- },
- "Uptrends": {
- "properties": [
- "uptrends.com"
- ],
- "resources": [
- "uptrends.com"
- ]
- },
- "up-value": {
- "properties": [
- "up-value.de"
- ],
- "resources": [
- "up-value.de"
- ]
- },
- "Usability Sciences": {
- "properties": [
- "usabilitysciences.com"
- ],
- "resources": [
- "usabilitysciences.com",
- "webiqonline.com"
- ]
- },
- "User Local": {
- "properties": [
- "nakanohito.jp"
- ],
- "resources": [
- "nakanohito.jp"
- ]
- },
- "UserVoice": {
- "properties": [
- "uservoice.com"
- ],
- "resources": [
- "uservoice.com"
- ]
- },
- "V12 Data": {
- "properties": [
- "v12group.com"
- ],
- "resources": [
- "v12data.com",
- "v12group.com"
- ]
- },
- "Value Ad": {
- "properties": [
- "valuead.com"
- ],
- "resources": [
- "valuead.com"
- ]
- },
- "Various": {
- "properties": [
- "amigos.com",
- "getiton.com",
- "medley.com",
- "nostringsattached.com",
- "various.com"
- ],
- "resources": [
- "amigos.com",
- "getiton.com",
- "medley.com",
- "nostringsattached.com",
- "various.com"
- ]
- },
- "Vdopia": {
- "properties": [
- "ivdopia.com",
- "vdopia.com"
- ],
- "resources": [
- "ivdopia.com",
- "vdopia.com"
- ]
- },
- "Veeseo": {
- "properties": [
- "veeseo.com"
- ],
- "resources": [
- "veeseo.com"
- ]
- },
- "Velocity Media": {
- "properties": [
- "adsvelocity.com"
- ],
- "resources": [
- "adsvelocity.com"
- ]
- },
- "Velti": {
- "properties": [
- "mobclix.com",
- "velti.com"
- ],
- "resources": [
- "mobclix.com",
- "velti.com"
- ]
- },
- "Vemba": {
- "properties": [
- "vemba.com"
- ],
- "resources": [
- "vemba.com"
- ]
- },
- "Venatus Media": {
- "properties": [
- "venatusmedia.com"
- ],
- "resources": [
- "venatusmedia.com"
- ]
- },
- "Vendemore": {
- "properties": [
- "vendemore.com"
- ],
- "resources": [
- "vendemore.com"
- ]
- },
- "Vendio": {
- "properties": [
- "singlefeed.com",
- "vendio.com"
- ],
- "resources": [
- "singlefeed.com",
- "vendio.com"
- ]
- },
- "Veoxa": {
- "properties": [
- "veoxa.com"
- ],
- "resources": [
- "veoxa.com"
- ]
- },
- "Veremedia": {
- "properties": [
- "veremedia.com"
- ],
- "resources": [
- "veremedia.com"
- ]
- },
- "Vertical Acuity": {
- "properties": [
- "verticalacuity.com"
- ],
- "resources": [
- "verticalacuity.com"
- ]
- },
- "VerticalHealth": {
- "properties": [
- "verticalhealth.com"
- ],
- "resources": [
- "verticalhealth.net"
- ]
- },
- "VerticalResponse": {
- "properties": [
- "verticalresponse.com",
- "vresp.com"
- ],
- "resources": [
- "verticalresponse.com",
- "vresp.com"
- ]
- },
- "Vertster": {
- "properties": [
- "vertster.com"
- ],
- "resources": [
- "vertster.com"
- ]
- },
- "VG WORT": {
- "properties": [
- "vgwort.de"
- ],
- "resources": [
- "vgwort.de"
- ]
- },
- "Vibrant Media": {
- "properties": [
- "vibrantmedia.com"
- ],
- "resources": [
- "intellitxt.com",
- "picadmedia.com",
- "vibrantmedia.com"
- ]
- },
- "VideoIntelligence": {
- "properties": [
- "vi.ai"
- ],
- "resources": [
- "vi.ai"
- ]
- },
- "Videology": {
- "properties": [
- "tidaltv.com",
- "videologygroup.com"
- ],
- "resources": [
- "tidaltv.com",
- "videologygroup.com"
- ]
- },
- "Viewbix": {
- "properties": [
- "qoof.com",
- "viewbix.com"
- ],
- "resources": [
- "qoof.com",
- "viewbix.com"
- ]
- },
- "VigLink": {
- "properties": [
- "viglink.com"
- ],
- "resources": [
- "viglink.com"
- ]
- },
- "Vimeo": {
- "properties": [
- "vimeo.com",
- "vimeocdn.com"
- ],
- "resources": [
- "vimeo.com",
- "vimeocdn.com"
- ]
- },
- "VINDICO": {
- "properties": [
- "vindicogroup.com",
- "vindicosuite.com"
- ],
- "resources": [
- "vindicogroup.com",
- "vindicosuite.com"
- ]
- },
- "VisibleBrands": {
- "properties": [
- "visbrands.com"
- ],
- "resources": [
- "visbrands.com"
- ]
- },
- "Visible Measures": {
- "properties": [
- "visiblemeasures.com"
- ],
- "resources": [
- "viewablemedia.net",
- "visiblemeasures.com"
- ]
- },
- "VisiStat": {
- "properties": [
- "id.kickfire.com",
- "sa-as.com"
- ],
- "resources": [
- "d.kickfire.com",
- "sa-as.com",
- "visistat.com"
- ]
- },
- "Visit Streamer": {
- "properties": [
- "visitstreamer.com"
- ],
- "resources": [
- "visitstreamer.com"
- ]
- },
- "vistrac": {
- "properties": [
- "vistrac.com"
- ],
- "resources": [
- "vistrac.com"
- ]
- },
- "VisualDNA": {
- "properties": [
- "vdna-assets.com",
- "visualdna-stats.com",
- "visualdna.com"
- ],
- "resources": [
- "vdna-assets.com",
- "visualdna-stats.com",
- "visualdna.com"
- ]
- },
- "ViziSense": {
- "properties": [
- "vizisense.com",
- "vizisense.net"
- ],
- "resources": [
- "vizisense.com",
- "vizisense.net"
- ]
- },
- "Vizu": {
- "properties": [
- "vizu.com"
- ],
- "resources": [
- "vizu.com"
- ]
- },
- "Vizury": {
- "properties": [
- "vizury.com"
- ],
- "resources": [
- "vizury.com"
- ]
- },
- "VKontakte": {
- "properties": [
- "vk.com"
- ],
- "resources": [
- "userapi.com",
- "vk.com",
- "vkontakte.ru"
- ]
- },
- "Voice2Page": {
- "properties": [
- "voice2page.com"
- ],
- "resources": [
- "voice2page.com"
- ]
- },
- "Vserv": {
- "properties": [
- "vserv.com",
- "vserv.mobi"
- ],
- "resources": [
- "vserv.com",
- "vserv.mobi"
- ]
- },
- "Vuble": {
- "properties": [
- "vuble.tv"
- ],
- "resources": [
- "mediabong.com"
- ]
- },
- "Wahoha": {
- "properties": [
- "contentwidgets.net",
- "wahoha.com"
- ],
- "resources": [
- "contentwidgets.net",
- "wahoha.com"
- ]
- },
- "Wayfair": {
- "properties": [
- "wayfair.com"
- ],
- "resources": [
- "wayfair.com"
- ]
- },
- "WebAds": {
- "properties": [
- "webads.co.uk",
- "www.webads.co.uk"
- ],
- "resources": [
- "webads.co.uk",
- "www.webads.co.uk"
- ]
- },
- "Webclicktracker": {
- "properties": [
- "webclicktracker.com"
- ],
- "resources": [
- "webclicktracker.com"
- ]
- },
- "Web.com": {
- "properties": [
- "feedperfect.com",
- "web.com"
- ],
- "resources": [
- "feedperfect.com",
- "web.com"
- ]
- },
- "WebGozar.com": {
- "properties": [
- "webgozar.com",
- "webgozar.ir"
- ],
- "resources": [
- "webgozar.com",
- "webgozar.ir"
- ]
- },
- "Webmecanik": {
- "properties": [
- "webmecanik.com"
- ],
- "resources": [
- "webmecanik.com"
- ]
- },
- "WebMetro": {
- "properties": [
- "dsmmadvantage.com",
- "revanadigital.com"
- ],
- "resources": [
- "dsmmadvantage.com",
- "revanadigital.com",
- "webmetro.com"
- ]
- },
- "Webmine": {
- "properties": [
- "webmine.cz"
- ],
- "resources": [
- "authedwebmine.cz",
- "webmine.cz"
- ]
- },
- "WebminePool": {
- "properties": [
- "webminepool.com"
- ],
- "resources": [
- "webminepool.com"
- ]
- },
- "Webmining": {
- "properties": [
- "webmining.co"
- ],
- "resources": [
- "webmining.co"
- ]
- },
- "Weborama": {
- "properties": [
- "weborama.com"
- ],
- "resources": [
- "weborama.com",
- "weborama.fr"
- ]
- },
- "WebsiteAlive": {
- "properties": [
- "websitealive.com",
- "websitealive0.com",
- "websitealive1.com",
- "websitealive2.com",
- "websitealive3.com",
- "websitealive4.com",
- "websitealive5.com",
- "websitealive6.com",
- "websitealive7.com",
- "websitealive8.com",
- "websitealive9.com"
- ],
- "resources": [
- "websitealive.com"
- ]
- },
- "Web Stats": {
- "properties": [
- "onlinewebstats.com"
- ],
- "resources": [
- "onlinewebstats.com"
- ]
- },
- "Web Tracking Services": {
- "properties": [
- "web-stat.com",
- "webtrackingservices.com"
- ],
- "resources": [
- "web-stat.com",
- "webtrackingservices.com"
- ]
- },
- "Webtraffic": {
- "properties": [
- "webtraffic.no",
- "webtraffic.se"
- ],
- "resources": [
- "webtraffic.no",
- "webtraffic.se"
- ]
- },
- "Web Traxs": {
- "properties": [
- "webtraxs.com"
- ],
- "resources": [
- "webtraxs.com"
- ]
- },
- "Webtrekk": {
- "properties": [
- "webtrekk.com",
- "webtrekk.net"
- ],
- "resources": [
- "webtrekk.com",
- "webtrekk.net"
- ]
- },
- "Webtrends": {
- "properties": [
- "webtrends.com"
- ],
- "resources": [
- "reinvigorate.net",
- "webtrends.com",
- "webtrendslive.com"
- ]
- },
- "White Ops": {
- "properties": [
- "adzmath.com",
- "whiteops.com"
- ],
- "resources": [
- "adzmath.com",
- "whiteops.com"
- ]
- },
- "whos.amung.us": {
- "properties": [
- "amung.us"
- ],
- "resources": [
- "amung.us"
- ]
- },
- "WideOrbit": {
- "properties": [
- "wideorbit.com"
- ],
- "resources": [
- "dep-x.com"
- ]
- },
- "Wingify": {
- "properties": [
- "vwo.com",
- "wingify.com"
- ],
- "resources": [
- "visualwebsiteoptimizer.com",
- "vwo.com",
- "wingify.com"
- ]
- },
- "WiredMinds": {
- "properties": [
- "wiredminds.de"
- ],
- "resources": [
- "wiredminds.com",
- "wiredminds.de"
- ]
- },
- "Wishabi": {
- "properties": [
- "wishabi.com",
- "wishabi.net"
- ],
- "resources": [
- "flipp.com",
- "wishabi.com",
- "wishabi.net"
- ]
- },
- "Woopra": {
- "properties": [
- "woopra-ns.com",
- "woopra.com"
- ],
- "resources": [
- "woopra-ns.com",
- "woopra.com"
- ]
- },
- "WordStream": {
- "properties": [
- "wordstream.com"
- ],
- "resources": [
- "wordstream.com"
- ]
- },
- "WOW Analytics": {
- "properties": [
- "wowanalytics.co.uk"
- ],
- "resources": [
- "wowanalytics.co.uk"
- ]
- },
- "WPP": {
- "properties": [
- "compete.com",
- "decdna.net",
- "groupm.com",
- "kantarmedia.com",
- "mecglobal.com",
- "mindshareworld.com",
- "themig.com",
- "wpp.com",
- "xaxis.com"
- ],
- "resources": [
- "247realmedia.com",
- "accelerator-media.com",
- "acceleratorusa.com",
- "compete.com",
- "decdna.net",
- "decideinteractive.com",
- "gmads.net",
- "groupm.com",
- "kantarmedia.com",
- "mecglobal.com",
- "mindshare.nl",
- "mindshareworld.com",
- "mookie1.com",
- "pm14.com",
- "realmedia.com",
- "targ.ad",
- "themig.com",
- "wpp.com",
- "xaxis.com"
- ]
- },
- "Wysistat": {
- "properties": [
- "wysistat.net"
- ],
- "resources": [
- "wysistat.com",
- "wysistat.net"
- ]
- },
- "xAd": {
- "properties": [
- "xad.com"
- ],
- "resources": [
- "xad.com"
- ]
- },
- "Xertive Media": {
- "properties": [
- "xertivemedia.com"
- ],
- "resources": [
- "admanager-xertive.com",
- "xertivemedia.com"
- ]
- },
- "xplosion interactive": {
- "properties": [
- "xplosion.de"
- ],
- "resources": [
- "xplosion.de"
- ]
- },
- "Xrost DS": {
- "properties": [
- "adplan-ds.com"
- ],
- "resources": [
- "adplan-ds.com"
- ]
- },
- "Yabuka": {
- "properties": [
- "yabuka.com"
- ],
- "resources": [
- "yabuka.com"
- ]
- },
- "Yahoo!": {
- "properties": [
- "flickr.com",
- "flurry.com",
- "tumblr.com",
- "yahoo.co.jp",
- "yahoo.com",
- "yahoostudios.com",
- "yuilibrary.com"
- ],
- "resources": [
- "adinterax.com",
- "adrevolver.com",
- "bluelithium.com",
- "dapper.net",
- "flickr.com",
- "flurry.com",
- "interclick.com",
- "luminate.com",
- "mybloglog.com",
- "overture.com",
- "pixazza.com",
- "rightmedia.com",
- "rmxads.com",
- "rocketmail.com",
- "secure-adserver.com",
- "staticflickr.com",
- "tumblr.com",
- "yahoo.co.jp",
- "yahoo.com",
- "yahooapis.com",
- "yahooapis.jp",
- "yahoofs.com",
- "yieldmanager.com",
- "yieldmanager.net",
- "yimg.com",
- "yimg.jp",
- "yldmgrimg.net",
- "ymail.com",
- "yuilibrary.com",
- "zenfs.com"
- ]
- },
- "Yandex": {
- "properties": [
- "kinopoisk.ru",
- "moikrug.ru",
- "yadi.sk",
- "yandex.by",
- "yandex.com",
- "yandex.com.tr",
- "yandex.ru",
- "yandex.st",
- "yandex.ua"
- ],
- "resources": [
- "api-maps.yandex.ru",
- "moikrug.ru",
- "web-visor.com",
- "yandex.by",
- "yandex.com",
- "yandex.com.tr",
- "yandex.ru",
- "yandex.st",
- "yandex.ua"
- ]
- },
- "Ybrant Digital": {
- "properties": [
- "addynamix.com",
- "brightcom.com",
- "luj.sdsjweb.com"
- ],
- "resources": [
- "addynamix.com",
- "adserverplus.com",
- "brightcom.com",
- "oridian.com",
- "ybrantdigital.com"
- ]
- },
- "YD": {
- "properties": [
- "ydworld.com",
- "yieldivision.com"
- ],
- "resources": [
- "ydworld.com",
- "yieldivision.com"
- ]
- },
- "YellowHammer": {
- "properties": [
- "yhmg.com"
- ],
- "resources": [
- "attracto.com",
- "clickhype.com",
- "yellowhammermg.com",
- "yhmg.com"
- ]
- },
- "YellowTracker": {
- "properties": [
- "yellowtracker.com"
- ],
- "resources": [
- "yellowtracker.com"
- ]
- },
- "Yes Ads": {
- "properties": [
- "yesads.com"
- ],
- "resources": [
- "yesads.com"
- ]
- },
- "YieldAds": {
- "properties": [
- "yieldads.com"
- ],
- "resources": [
- "yieldads.com"
- ]
- },
- "YieldBids": {
- "properties": [
- "ybx.io"
- ],
- "resources": [
- "ybx.io"
- ]
- },
- "YieldBot": {
- "properties": [
- "yieldbot.com"
- ],
- "resources": [
- "yldbt.com"
- ]
- },
- "YieldBuild": {
- "properties": [
- "yieldbuild.com"
- ],
- "resources": [
- "yieldbuild.com"
- ]
- },
- "Yieldify": {
- "properties": [
- "yieldify.com"
- ],
- "resources": [
- "yieldify.com"
- ]
- },
- "Yieldlab": {
- "properties": [
- "yieldlab.de",
- "yieldlab.net"
- ],
- "resources": [
- "yieldlab.de",
- "yieldlab.net"
- ]
- },
- "Yieldmo": {
- "properties": [
- "yieldmo.com"
- ],
- "resources": [
- "yieldmo.com"
- ]
- },
- "YieldNexus": {
- "properties": [
- "ynxs.io"
- ],
- "resources": [
- "ynxs.io"
- ]
- },
- "YOC": {
- "properties": [
- "yoc.com"
- ],
- "resources": [
- "yoc.com"
- ]
- },
- "Yoggrt": {
- "properties": [
- "yoggrt.com"
- ],
- "resources": [
- "yoggrt.com"
- ]
- },
- "youknowbest": {
- "properties": [
- "youknowbest.com"
- ],
- "resources": [
- "youknowbest.com"
- ]
- },
- "YSance": {
- "properties": [
- "ysance.com"
- ],
- "resources": [
- "y-track.com"
- ]
- },
- "YuMe": {
- "properties": [
- "yume.com",
- "yumenetworks.com"
- ],
- "resources": [
- "yume.com",
- "yumenetworks.com"
- ]
- },
- "ZafulAffiliate": {
- "properties": [
- "zaful.com"
- ],
- "resources": [
- "zaful.com"
- ]
- },
- "Zango": {
- "properties": [
- "metricsdirect.com",
- "zango.com"
- ],
- "resources": [
- "metricsdirect.com",
- "zango.com"
- ]
- },
- "zanox": {
- "properties": [
- "buy.at",
- "zanox-affiliate.de",
- "zanox.com"
- ],
- "resources": [
- "buy.at",
- "zanox-affiliate.de",
- "zanox.com"
- ]
- },
- "zapunited": {
- "properties": [
- "zaparena.com",
- "zapunited.com"
- ],
- "resources": [
- "zaparena.com",
- "zapunited.com"
- ]
- },
- "ZEDO": {
- "properties": [
- "zedo.com",
- "zincx.com"
- ],
- "resources": [
- "zedo.com",
- "zincx.com"
- ]
- },
- "Zefir": {
- "properties": [
- "ze-fir.com"
- ],
- "resources": [
- "ze-fir.com"
- ]
- },
- "Zemanta": {
- "properties": [
- "zemanta.com"
- ],
- "resources": [
- "zemanta.com"
- ]
- },
- "Zendesk": {
- "properties": [
- "zendesk.com"
- ],
- "resources": [
- "zendesk.com"
- ]
- },
- "ZestAd": {
- "properties": [
- "zestad.com"
- ],
- "resources": [
- "zestad.com"
- ]
- },
- "Zeta Email Solutions": {
- "properties": [
- "insightgrit.com",
- "zetaemailsolutions.com"
- ],
- "resources": [
- "insightgrit.com",
- "zetaemailsolutions.com"
- ]
- },
- "Zopim": {
- "properties": [
- "zopim.com"
- ],
- "resources": [
- "zopim.com"
- ]
- },
- "Zumobi": {
- "properties": [
- "zumobi.com"
- ],
- "resources": [
- "zumobi.com"
- ]
- },
- "ZypMedia": {
- "properties": [
- "zypmedia.com"
- ],
- "resources": [
- "extend.tv",
- "zypmedia.com"
- ]
- }
+ "2leep.com": {
+ "properties": ["2leep.com"],
+ "resources": ["2leep.com"]
+ },
+ "33Across": {
+ "properties": ["33across.com", "tynt.com"],
+ "resources": ["33across.com", "tynt.com"]
+ },
+ "365Media": {
+ "properties": ["aggregateintelligence.com"],
+ "resources": ["365media.com", "aggregateintelligence.com"]
+ },
+ "4INFO": {
+ "properties": ["4info.com", "adhaven.com"],
+ "resources": ["4info.com", "adhaven.com"]
+ },
+ "4mads": {
+ "properties": ["4mads.com"],
+ "resources": ["4mads.com"]
+ },
+ "63 Squares": {
+ "properties": ["63labs.com"],
+ "resources": ["63labs.com", "63squares.com", "i-stats.com"]
+ },
+ "Abax Interactive": {
+ "properties": ["abaxinteractive.com"],
+ "resources": ["abaxinteractive.com"]
+ },
+ "Accelia": {
+ "properties": ["accelia.net", "durasite.net"],
+ "resources": ["accelia.net", "durasite.net"]
+ },
+ "Accordant Media": {
+ "properties": ["accordantmedia.com"],
+ "resources": ["accordantmedia.com"]
+ },
+ "Acquisio": {
+ "properties": ["acquisio.com", "clickequations.net"],
+ "resources": ["acquisio.com", "clickequations.net"]
+ },
+ "Actisens": {
+ "properties": ["actisens.com", "gestionpub.com"],
+ "resources": ["actisens.com", "gestionpub.com"]
+ },
+ "ActiveConversion": {
+ "properties": ["activeconversion.com", "activemeter.com"],
+ "resources": ["activeconversion.com", "activemeter.com"]
+ },
+ "ActivEngage": {
+ "properties": ["activengage.com"],
+ "resources": ["activengage.com"]
+ },
+ "Act-On": {
+ "properties": ["act-on.com", "actonsoftware.com"],
+ "resources": ["act-on.com", "actonsoftware.com"]
+ },
+ "Acuity": {
+ "properties": ["acuity.com", "acuityads.com", "acuityplatform.com"],
+ "resources": ["acuity.com", "acuityads.com", "acuityplatform.com"]
+ },
+ "Acxiom": {
+ "properties": ["acxiom.com", "mm7.net"],
+ "resources": ["acxiom.com", "acxiomapac.com", "mm7.net", "pippio.com"]
+ },
+ "AD2ONE": {
+ "properties": ["ad2onegroup.com"],
+ "resources": ["ad2onegroup.com"]
+ },
+ "Ad4Game": {
+ "properties": ["ad4game.com"],
+ "resources": ["ad4game.com"]
+ },
+ "ad6media": {
+ "properties": ["ad6media.fr"],
+ "resources": ["ad6media.fr"]
+ },
+ "Adabra": {
+ "properties": ["adabra.com"],
+ "resources": ["adabra.com"]
+ },
+ "Adality": {
+ "properties": ["adality.de"],
+ "resources": ["adality.de", "adrtx.net"]
+ },
+ "AdaptiveAds": {
+ "properties": ["adaptiveads.com"],
+ "resources": ["adaptiveads.com"]
+ },
+ "Adaptly": {
+ "properties": ["adaptly.com"],
+ "resources": ["adaptly.com"]
+ },
+ "Adap.tv": {
+ "properties": ["adap.tv"],
+ "resources": ["adap.tv"]
+ },
+ "Adara Media": {
+ "properties": ["adaramedia.com", "opinmind.com", "yieldoptimizer.com"],
+ "resources": ["adaramedia.com", "opinmind.com", "yieldoptimizer.com"]
+ },
+ "Adatus": {
+ "properties": ["adatus.com"],
+ "resources": ["adatus.com"]
+ },
+ "Adbot": {
+ "properties": ["adbot.tw"],
+ "resources": ["adbot.tw"]
+ },
+ "Adbrain": {
+ "properties": ["adbrain.com"],
+ "resources": ["adbrain.com", "adbrn.com"]
+ },
+ "adBrite": {
+ "properties": ["adbrite.com"],
+ "resources": ["adbrite.com"]
+ },
+ "Adbroker.de": {
+ "properties": ["adbroker.de"],
+ "resources": ["adbroker.de"]
+ },
+ "Adchemy": {
+ "properties": ["adchemy.com"],
+ "resources": ["adchemy.com"]
+ },
+ "AdCirrus": {
+ "properties": ["adcirrus.com"],
+ "resources": ["adcirrus.com"]
+ },
+ "Ad Decisive": {
+ "properties": ["a2dfp.net", "addecisive.com"],
+ "resources": ["a2dfp.net", "addecisive.com"]
+ },
+ "AddFreeStats": {
+ "properties": ["3dstats.com", "addfreestats.com"],
+ "resources": ["3dstats.com", "addfreestats.com"]
+ },
+ "addGloo": {
+ "properties": ["addgloo.com"],
+ "resources": ["addgloo.com"]
+ },
+ "AddThis": {
+ "properties": ["addthis.com"],
+ "resources": [
+ "addthis.com",
+ "addthiscdn.com",
+ "addthisedge.com",
+ "clearspring.com",
+ "connectedads.net",
+ "xgraph.com",
+ "xgraph.net"
+ ]
+ },
+ "Addvantage Media": {
+ "properties": ["addvantagemedia.com"],
+ "resources": ["addvantagemedia.com"]
+ },
+ "Ad Dynamo": {
+ "properties": ["addynamo.com"],
+ "resources": ["addynamo.com", "addynamo.net"]
+ },
+ "Adelphic": {
+ "properties": ["adelphic.com"],
+ "resources": ["adelphic.com", "ipredictive.com"]
+ },
+ "AdEngage": {
+ "properties": ["adengage.com"],
+ "resources": ["adengage.com"]
+ },
+ "AD Europe": {
+ "properties": ["adeurope.com"],
+ "resources": ["adeurope.com"]
+ },
+ "AdExtent": {
+ "properties": ["adextent.com"],
+ "resources": ["adextent.com"]
+ },
+ "AdF.ly": {
+ "properties": ["adf.ly"],
+ "resources": ["adf.ly"]
+ },
+ "Adfonic": {
+ "properties": ["adfonic.com"],
+ "resources": ["adfonic.com"]
+ },
+ "Adforge": {
+ "properties": ["adforgeinc.com"],
+ "resources": ["adforgeinc.com"]
+ },
+ "Adform": {
+ "properties": ["adform.com"],
+ "resources": ["adform.com", "adform.net", "adformdsp.net"]
+ },
+ "AdFox": {
+ "properties": ["adfox.ru"],
+ "resources": ["adfox.ru"]
+ },
+ "AdFrontiers": {
+ "properties": ["adfrontiers.com"],
+ "resources": ["adfrontiers.com"]
+ },
+ "Adfunky": {
+ "properties": ["adfunky.com", "adfunkyserver.com"],
+ "resources": ["adfunky.com", "adfunkyserver.com"]
+ },
+ "Adfusion": {
+ "properties": ["adfusion.com"],
+ "resources": ["adfusion.com"]
+ },
+ "AdGainerSolutions": {
+ "properties": ["adgainersolutions.com"],
+ "resources": ["adgainersolutions.com"]
+ },
+ "AdGent Digital": {
+ "properties": ["adgentdigital.com"],
+ "resources": ["adgentdigital.com", "shorttailmedia.com"]
+ },
+ "AdGibbon": {
+ "properties": ["adgibbon.com"],
+ "resources": ["adgibbon.com"]
+ },
+ "Adglare": {
+ "properties": ["adglare.com"],
+ "resources": ["adglare.com", "adglare.net"]
+ },
+ "adhood": {
+ "properties": ["adhood.com"],
+ "resources": ["adhood.com"]
+ },
+ "Adiant": {
+ "properties": ["adblade.com", "adiant.com"],
+ "resources": ["adblade.com", "adiant.com"]
+ },
+ "AdInsight": {
+ "properties": ["responsetap.com"],
+ "resources": ["adinsight.com", "adinsight.eu", "responsetap.com"]
+ },
+ "AdIQuity": {
+ "properties": ["adiquity.com"],
+ "resources": ["adiquity.com"]
+ },
+ "ADITION": {
+ "properties": ["adition.com"],
+ "resources": ["adition.com"]
+ },
+ "AdJug": {
+ "properties": ["adjug.com"],
+ "resources": ["adjug.com"]
+ },
+ "AdJuggler": {
+ "properties": ["adjuggler.com", "adjuggler.net"],
+ "resources": ["adjuggler.com", "adjuggler.net"]
+ },
+ "Adjust": {
+ "properties": ["adjust.com"],
+ "resources": ["adjust.com"]
+ },
+ "AdKeeper": {
+ "properties": ["keep.com"],
+ "resources": ["adkeeper.com", "akncdn.com", "keep.com"]
+ },
+ "AdKernel": {
+ "properties": ["adkernel.com"],
+ "resources": ["adkernel.com"]
+ },
+ "Ad Knife": {
+ "properties": ["adknife.com"],
+ "resources": ["adknife.com"]
+ },
+ "Adknowledge": {
+ "properties": [
+ "adknowledge.com",
+ "adparlor.com",
+ "bidsystem.com",
+ "cubics.com",
+ "lookery.com"
+ ],
+ "resources": [
+ "adknowledge.com",
+ "adparlor.com",
+ "bidsystem.com",
+ "cubics.com",
+ "lookery.com"
+ ]
+ },
+ "AdLantis": {
+ "properties": ["adimg.net", "adlantis.jp", "www.adlantis.jp"],
+ "resources": ["adimg.net", "adlantis.jp", "www.adlantis.jp"]
+ },
+ "AdLeave": {
+ "properties": ["adleave.com"],
+ "resources": ["adleave.com"]
+ },
+ "Adlibrium": {
+ "properties": ["adlibrium.com"],
+ "resources": ["adlibrium.com"]
+ },
+ "Adloox": {
+ "properties": ["adloox.com"],
+ "resources": ["adloox.com", "adlooxtracking.com"]
+ },
+ "Adlucent": {
+ "properties": ["adlucent.com"],
+ "resources": ["adlucent.com"]
+ },
+ "Ad Magnet": {
+ "properties": ["admagnet.com", "admagnet.net"],
+ "resources": ["admagnet.com", "admagnet.net"]
+ },
+ "Admarketplace": {
+ "properties": ["admarketplace.com"],
+ "resources": ["admarketplace.com", "admarketplace.net", "ampxchange.com"]
+ },
+ "AdMarvel": {
+ "properties": ["admarvel.com"],
+ "resources": ["admarvel.com"]
+ },
+ "AdMatrix": {
+ "properties": ["admatrix.jp"],
+ "resources": ["admatrix.jp"]
+ },
+ "AdMaven": {
+ "properties": ["ad-maven.com"],
+ "resources": [
+ "ad-maven.com",
+ "agreensdistra.info",
+ "boudja.com",
+ "rensovetors.info",
+ "wrethicap.info"
+ ]
+ },
+ "AdMaximizer Network": {
+ "properties": ["admaximizer.com"],
+ "resources": ["admaximizer.com"]
+ },
+ "AdMedia": {
+ "properties": ["admedia.com"],
+ "resources": ["admedia.com"]
+ },
+ "Admeta": {
+ "properties": ["admeta.com", "atemda.com"],
+ "resources": ["admeta.com", "atemda.com"]
+ },
+ "Admicro": {
+ "properties": ["admicro.vn"],
+ "resources": ["admicro.vn", "vcmedia.vn"]
+ },
+ "Admixer": {
+ "properties": ["admixer.co.kr"],
+ "resources": ["admixer.co.kr"]
+ },
+ "Admized": {
+ "properties": ["admized.com"],
+ "resources": ["admized.com"]
+ },
+ "Admobile": {
+ "properties": ["admobile.com"],
+ "resources": ["admobile.com"]
+ },
+ "Admotion": {
+ "properties": ["admotion.com"],
+ "resources": ["admotion.com", "nspmotion.com"]
+ },
+ "Adnetik": {
+ "properties": ["wtp101.com"],
+ "resources": ["adnetik.com", "wtp101.com"]
+ },
+ "AdNetwork.net": {
+ "properties": ["adnetwork.net"],
+ "resources": ["adnetwork.net"]
+ },
+ "Adnium": {
+ "properties": ["adnium.com"],
+ "resources": ["adnium.com", "montwam.top"]
+ },
+ "adnologies": {
+ "properties": ["adnologies.com", "heias.com"],
+ "resources": ["adnologies.com", "heias.com"]
+ },
+ "Adobe": {
+ "properties": ["adobe.com", "livefyre.com", "typekit.com"],
+ "resources": [
+ "2o7.net",
+ "adobe.com",
+ "auditude.com",
+ "demdex.com",
+ "demdex.net",
+ "dmtracker.com",
+ "efrontier.com",
+ "everestads.net",
+ "everestjs.net",
+ "everesttech.net",
+ "fyre.co",
+ "hitbox.com",
+ "livefyre.com",
+ "omniture.com",
+ "omtrdc.net",
+ "touchclarity.com",
+ "typekit.com"
+ ]
+ },
+ "AdOcean": {
+ "properties": ["adocean-global.com", "adocean.pl"],
+ "resources": ["adocean-global.com", "adocean.pl"]
+ },
+ "Adometry": {
+ "properties": ["adometry.com"],
+ "resources": ["adometry.com", "dmtry.com"]
+ },
+ "Adomik": {
+ "properties": ["adomik.com"],
+ "resources": ["adomik.com"]
+ },
+ "AdOnion": {
+ "properties": ["adonion.com"],
+ "resources": ["adonion.com"]
+ },
+ "Adorika": {
+ "properties": ["clickotmedia.com"],
+ "resources": ["clickotmedia.com"]
+ },
+ "Adotmob": {
+ "properties": ["adotmob.com"],
+ "resources": ["adotmob.com"]
+ },
+ "ADP Dealer Services": {
+ "properties": ["cdkglobal.com"],
+ "resources": [
+ "admission.net",
+ "adpdealerservices.com",
+ "cdkglobal.com",
+ "cobalt.com"
+ ]
+ },
+ "ad pepper media": {
+ "properties": ["adpepper.com", "adpepper.us"],
+ "resources": ["adpepper.com", "adpepper.us"]
+ },
+ "AdPerfect": {
+ "properties": ["adperfect.com"],
+ "resources": ["adperfect.com"]
+ },
+ "Adperium": {
+ "properties": ["adperium.com"],
+ "resources": ["adperium.com"]
+ },
+ "Adpersia": {
+ "properties": ["adpersia.com"],
+ "resources": ["adpersia.com"]
+ },
+ "adPrecision": {
+ "properties": ["adprecision.net", "adprs.net"],
+ "resources": ["adprecision.net", "adprs.net", "aprecision.net"]
+ },
+ "AdPredictive": {
+ "properties": ["adpredictive.com"],
+ "resources": ["adpredictive.com"]
+ },
+ "AdReactor": {
+ "properties": ["adreactor.com"],
+ "resources": ["adreactor.com"]
+ },
+ "AdReady": {
+ "properties": ["digitalremedy.com"],
+ "resources": ["adready.com", "adreadytractions.com", "digitalremedy"]
+ },
+ "AdRevolution": {
+ "properties": ["adrevolution.com"],
+ "resources": ["adrevolution.com"]
+ },
+ "AdRiver": {
+ "properties": ["adriver.ru"],
+ "resources": ["adriver.ru"]
+ },
+ "adrolays": {
+ "properties": ["contactimpact.de"],
+ "resources": ["adrolays.com", "adrolays.de", "contactimpact.de"]
+ },
+ "AdRoll": {
+ "properties": ["adroll.com"],
+ "resources": ["adroll.com"]
+ },
+ "adscale": {
+ "properties": ["stroeer.de"],
+ "resources": ["adscale.de", "stroeer.de"]
+ },
+ "Adscience": {
+ "properties": ["adscience.nl"],
+ "resources": ["adscience.nl"]
+ },
+ "AdScore": {
+ "properties": ["adscoremarketing.com"],
+ "resources": ["adsco.re"]
+ },
+ "AdServerPub": {
+ "properties": ["adserverpub.com"],
+ "resources": ["adserverpub.com"]
+ },
+ "AdShuffle": {
+ "properties": ["adshuffle.com"],
+ "resources": ["adshuffle.com"]
+ },
+ "AdSide": {
+ "properties": ["adside.com", "doclix.com"],
+ "resources": ["adside.com", "doclix.com"]
+ },
+ "AdSpeed": {
+ "properties": ["adspeed.com", "adspeed.net"],
+ "resources": ["adspeed.com", "adspeed.net"]
+ },
+ "Adsperity": {
+ "properties": ["adsperity.com"],
+ "resources": ["adsperity.com"]
+ },
+ "AdSpirit": {
+ "properties": ["adspirit.com", "adspirit.de", "adspirit.net"],
+ "resources": ["adspirit.com", "adspirit.de", "adspirit.net"]
+ },
+ "Adsrevenue.net": {
+ "properties": ["adsrevenue.net"],
+ "resources": ["adsrevenue.net"]
+ },
+ "AdStir": {
+ "properties": ["ad-stir.com"],
+ "resources": ["ad-stir.com"]
+ },
+ "AdsTours": {
+ "properties": ["adstours.com", "clickintext.net"],
+ "resources": ["adstours.com", "clickintext.net"]
+ },
+ "Adsty": {
+ "properties": ["adsty.com", "adx1.com"],
+ "resources": ["adsty.com", "adx1.com"]
+ },
+ "Adsupply": {
+ "properties": ["4dsply.com", "adsupply.com"],
+ "resources": ["4dsply.com", "adsupply.com"]
+ },
+ "Adswizz": {
+ "properties": ["adswizz.com"],
+ "resources": ["adswizz.com"]
+ },
+ "ADTECH": {
+ "properties": ["adtech.com", "adtech.de", "adtechus.com"],
+ "resources": ["adtech.com", "adtech.de", "adtechus.com"]
+ },
+ "Adtegrity.com": {
+ "properties": ["adtegrity.com", "adtegrity.net"],
+ "resources": ["adtegrity.com", "adtegrity.net"]
+ },
+ "ADTELLIGENCE": {
+ "properties": ["adtelligence.de"],
+ "resources": ["adtelligence.de"]
+ },
+ "Adthink": {
+ "properties": ["adthink.com"],
+ "resources": ["adthink.com", "audienceinsights.net"]
+ },
+ "AdTiger": {
+ "properties": ["adtiger.de"],
+ "resources": ["adtiger.de"]
+ },
+ "AdTruth": {
+ "properties": ["adtruth.com"],
+ "resources": ["adtruth.com"]
+ },
+ "Adult AdWorld": {
+ "properties": ["adultadworld.com"],
+ "resources": ["adultadworld.com"]
+ },
+ "Adultmoda": {
+ "properties": ["adultmoda.com"],
+ "resources": ["adultmoda.com"]
+ },
+ "Adventive": {
+ "properties": ["adventive.com"],
+ "resources": ["adventive.com"]
+ },
+ "Adventori": {
+ "properties": ["adventori.com"],
+ "resources": ["adventori.com"]
+ },
+ "Adverline": {
+ "properties": ["adnext.fr", "adverline.com"],
+ "resources": ["adnext.fr", "adverline.com"]
+ },
+ "Adversal.com": {
+ "properties": ["adv-adserver.com", "adversal.com"],
+ "resources": ["adv-adserver.com", "adversal.com"]
+ },
+ "Adverticum": {
+ "properties": ["adsmart.com", "adverticum.com", "adverticum.net"],
+ "resources": ["adsmart.com", "adverticum.com", "adverticum.net"]
+ },
+ "Advertise.com": {
+ "properties": ["advertise.com"],
+ "resources": ["advertise.com"]
+ },
+ "AdvertiseSpace": {
+ "properties": ["advertisespace.com"],
+ "resources": ["advertisespace.com"]
+ },
+ "Advert Stream": {
+ "properties": ["advertstream.com"],
+ "resources": ["advertstream.com"]
+ },
+ "Advisor Media": {
+ "properties": ["advisormedia.cz"],
+ "resources": ["advisormedia.cz"]
+ },
+ "Adworx": {
+ "properties": ["adworx.at", "adworx.be", "adworx.nl"],
+ "resources": ["adworx.at", "adworx.be", "adworx.nl"]
+ },
+ "AdXpansion": {
+ "properties": ["adxpansion.com"],
+ "resources": ["adxpansion.com"]
+ },
+ "Adxvalue": {
+ "properties": ["adxvalue.com", "adxvalue.de"],
+ "resources": ["adxvalue.com", "adxvalue.de"]
+ },
+ "adyard": {
+ "properties": ["adyard.de"],
+ "resources": ["adyard.de"]
+ },
+ "AdYield": {
+ "properties": ["adyield.com"],
+ "resources": ["adxyield.com", "adyield.com"]
+ },
+ "AdYouLike": {
+ "properties": ["adyoulike.com"],
+ "resources": ["adyoulike.com", "omnitagjs.com", "pulpix.com"]
+ },
+ "ADZ": {
+ "properties": ["adzcentral.com"],
+ "resources": ["adzcentral.com"]
+ },
+ "Adzerk": {
+ "properties": ["adzerk.com"],
+ "resources": ["adzerk.com", "adzerk.net"]
+ },
+ "adzly": {
+ "properties": ["adzly.com"],
+ "resources": ["adzly.com"]
+ },
+ "Aegis Group": {
+ "properties": ["aemedia.com", "bluestreak.com", "dentsuaegisnetwork.com"],
+ "resources": ["aemedia.com", "bluestreak.com", "dentsuaegisnetwork.com"]
+ },
+ "AERIFY MEDIA": {
+ "properties": ["aerifymedia.com", "anonymous-media.com"],
+ "resources": ["aerifymedia.com", "anonymous-media.com"]
+ },
+ "Affectv": {
+ "properties": ["affectv.co.uk"],
+ "resources": ["affectv.co.uk"]
+ },
+ "affilinet": {
+ "properties": ["affili.net", "affilinet-inside.de"],
+ "resources": [
+ "affili.net",
+ "affilinet-inside.de",
+ "banner-rotation.com",
+ "successfultogether.co.uk"
+ ]
+ },
+ "Affine": {
+ "properties": ["affine.tv", "affinesystems.com"],
+ "resources": ["affine.tv", "affinesystems.com"]
+ },
+ "Affinity": {
+ "properties": ["affinity.com"],
+ "resources": ["affinity.com"]
+ },
+ "AfterDownload": {
+ "properties": ["afdads.com", "afterdownload.com"],
+ "resources": ["afdads.com", "afterdownload.com"]
+ },
+ "AIData": {
+ "properties": ["advombat.ru", "aidata.me"],
+ "resources": ["advombat.ru", "aidata.me"]
+ },
+ "Aim4Media": {
+ "properties": ["aim4media.com"],
+ "resources": ["aim4media.com"]
+ },
+ "Airpush": {
+ "properties": ["airpush.com"],
+ "resources": ["airpush.com"]
+ },
+ "AivaLabs": {
+ "properties": ["aivalabs.com"],
+ "resources": ["aivalabs.com"]
+ },
+ "a.js": {
+ "properties": [
+ "alflying.date",
+ "alflying.win",
+ "anybest.site",
+ "flightsy.bid",
+ "flightsy.win",
+ "flightzy.bid",
+ "flightzy.date",
+ "flightzy.win",
+ "zymerget.bid",
+ "zymerget.faith"
+ ],
+ "resources": [
+ "alflying.date",
+ "alflying.win",
+ "anybest.site",
+ "flightsy.bid",
+ "flightsy.win",
+ "flightzy.bid",
+ "flightzy.date",
+ "flightzy.win",
+ "zymerget.bid",
+ "zymerget.faith"
+ ]
+ },
+ "AK": {
+ "properties": ["aggregateknowledge.com", "agkn.com"],
+ "resources": ["aggregateknowledge.com", "agkn.com"]
+ },
+ "Akamai": {
+ "properties": ["akamai.com"],
+ "resources": [
+ "abmr.net",
+ "akamai.com",
+ "edgesuite.net",
+ "go-mpulse.net",
+ "imiclk.com"
+ ]
+ },
+ "AKQA": {
+ "properties": ["akqa.com"],
+ "resources": ["akqa.com", "srtk.net"]
+ },
+ "Albacross": {
+ "properties": ["albacross.com"],
+ "resources": ["albacross.com"]
+ },
+ "AllStarMediaGroup": {
+ "properties": ["allstarmediagroup.com"],
+ "resources": ["allstarmediagroup.com"]
+ },
+ "Aloodo": {
+ "properties": ["aloodo.com"],
+ "resources": ["aloodo.com"]
+ },
+ "AlterGeo": {
+ "properties": ["altergeo.ru"],
+ "resources": ["altergeo.ru"]
+ },
+ "Amadesa": {
+ "properties": ["amadesa.com"],
+ "resources": ["amadesa.com"]
+ },
+ "Amazing Counters": {
+ "properties": ["amazingcounters.com"],
+ "resources": ["amazingcounters.com"]
+ },
+ "Amazon.com": {
+ "properties": [
+ "6pm.com",
+ "abebooks.co.uk",
+ "abebooks.com",
+ "abebooks.de",
+ "abebooks.fr",
+ "abebooks.it",
+ "acx.com",
+ "alexa.com",
+ "amazon.ae",
+ "amazon.ca",
+ "amazon.cn",
+ "amazon.co.jp",
+ "amazon.co.uk",
+ "amazon.com",
+ "amazon.com.au",
+ "amazon.com.br",
+ "amazon.com.mx",
+ "amazon.com.sg",
+ "amazon.com.tr",
+ "amazon.de",
+ "amazon.es",
+ "amazon.fr",
+ "amazon.in",
+ "amazon.it",
+ "amazon.nl",
+ "amazon.sa",
+ "amazonaws.com",
+ "amazoninspire.com",
+ "assoc-amazon.com",
+ "audible.co.jp",
+ "audible.co.uk",
+ "audible.com",
+ "audible.de",
+ "audible.fr",
+ "audible.in",
+ "audible.it",
+ "bookdepository.com",
+ "boxofficemojo.com",
+ "brilliancepublishing.com",
+ "comixology.com",
+ "createspace.com",
+ "dpreview.com",
+ "dpreview.in",
+ "eastdane.com",
+ "fabric.com",
+ "goodreads.com",
+ "iberlibro.com",
+ "imdb.com",
+ "imdb.de",
+ "junglee.com",
+ "look.com",
+ "pillpack.com",
+ "shopbop.com",
+ "souq.com",
+ "twitch.com",
+ "twitch.tv",
+ "wholefoodsmarket.com",
+ "withoutabox.com",
+ "woot.com",
+ "yoyo.com",
+ "zappos.com",
+ "zvab.com"
+ ],
+ "resources": [
+ "alexa.com",
+ "alexametrics.com",
+ "amazon-adsystem.com",
+ "amazon.ca",
+ "amazon.co.jp",
+ "amazon.co.uk",
+ "amazon.com",
+ "amazon.de",
+ "amazon.es",
+ "amazon.fr",
+ "amazon.it",
+ "amazonaws.com",
+ "assoc-amazon.com",
+ "cloudfront.net",
+ "ssl-images-amazon.com"
+ ]
+ },
+ "Ambient Digital": {
+ "properties": ["adnetwork.vn", "ambientdigital.com.vn"],
+ "resources": ["adnetwork.vn", "ambientdigital.com.vn"]
+ },
+ "Amobee": {
+ "properties": ["amobee.com", "smartclip.com"],
+ "resources": [
+ "adconion.com",
+ "amgdgt.com",
+ "amobee.com",
+ "euroclick.com",
+ "smartclip.com",
+ "turn.com"
+ ]
+ },
+ "Amplitude": {
+ "properties": ["amplitude.com"],
+ "resources": ["amplitude.com"]
+ },
+ "AndBeyond": {
+ "properties": ["andbeyond.media"],
+ "resources": ["andbeyond.media"]
+ },
+ "anormal-media.de": {
+ "properties": ["anormal-media.de", "primawebtools.de"],
+ "resources": ["anormal-media.de", "anormal-tracker.de", "primawebtools.de"]
+ },
+ "Answers.com": {
+ "properties": ["answers.com", "dsply.com"],
+ "resources": ["dsply.com"]
+ },
+ "AOL": {
+ "properties": [
+ "5min.com",
+ "adsonar.com",
+ "advertising.com",
+ "aim.com",
+ "aol.com",
+ "aolcdn.com",
+ "aoltechguru.com",
+ "atwola.com",
+ "autoblog.com",
+ "cambio.com",
+ "dailyfinance.com",
+ "editions.com",
+ "engadget.com",
+ "games.com",
+ "homesessive.com",
+ "huffingtonpost.com",
+ "leadback.com",
+ "makers.com",
+ "mandatory.com",
+ "mapquest.com",
+ "moviefone.com",
+ "noisecreep.com",
+ "patch.com",
+ "pawnation.com",
+ "shortcuts.com",
+ "shoutcast.com",
+ "spinner.com",
+ "stylelist.com",
+ "stylemepretty.com",
+ "surphace.com",
+ "tacoda.net",
+ "techcrunch.com",
+ "theboombox.com",
+ "theboot.com",
+ "userplane.com",
+ "winamp.com"
+ ],
+ "resources": [
+ "5min.com",
+ "adsonar.com",
+ "adtechjp.com",
+ "advertising.com",
+ "aim.com",
+ "aol.com",
+ "aolcdn.com",
+ "aolcloud.net",
+ "atwola.com",
+ "editions.com",
+ "leadback.com",
+ "mapquest.com",
+ "patch.com",
+ "shortcuts.com",
+ "shoutcast.com",
+ "spinner.com",
+ "surphace.com",
+ "tacoda.net",
+ "userplane.com",
+ "vidible.tv",
+ "winamp.com"
+ ]
+ },
+ "AppCast": {
+ "properties": ["appcast.io"],
+ "resources": ["appcast.io"]
+ },
+ "Appenda": {
+ "properties": ["appenda.com"],
+ "resources": ["appenda.com"]
+ },
+ "AppFlood": {
+ "properties": ["appflood.com"],
+ "resources": ["appflood.com"]
+ },
+ "Appier": {
+ "properties": ["appier.com"],
+ "resources": ["appier.com"]
+ },
+ "Applifier": {
+ "properties": ["applifier.com"],
+ "resources": ["applifier.com"]
+ },
+ "Applovin": {
+ "properties": ["applovin.com"],
+ "resources": ["applovin.com"]
+ },
+ "AppNexus": {
+ "properties": ["adlantic.nl", "adnxs.com", "adrdgt.com", "appnexus.com"],
+ "resources": ["adlantic.nl", "adnxs.com", "adrdgt.com", "appnexus.com"]
+ },
+ "AppsFlyer": {
+ "properties": ["appsflyer.com"],
+ "resources": ["appsflyer.com"]
+ },
+ "appssavvy": {
+ "properties": ["appssavvy.com"],
+ "resources": ["appssavvy.com"]
+ },
+ "Arkwrights Homebrew": {
+ "properties": ["whiskyandwines.com"],
+ "resources": ["arkwrightshomebrew.com", "ctasnet.com", "whiskyandwines.com"]
+ },
+ "AT Internet": {
+ "properties": ["atinternet.com", "xiti.com"],
+ "resources": ["at-o.net", "atinternet.com", "hit-parade.com", "xiti.com"]
+ },
+ "ATN": {
+ "properties": ["affiliatetracking.com"],
+ "resources": ["affiliatetracking.com"]
+ },
+ "Atoomic.com": {
+ "properties": ["atoomic.com"],
+ "resources": ["atoomic.com"]
+ },
+ "Atrinsic": {
+ "properties": ["atrinsic.com"],
+ "resources": ["atrinsic.com"]
+ },
+ "AT&T": {
+ "properties": ["att.com", "yp.com"],
+ "resources": ["att.com", "yp.com"]
+ },
+ "Attracta": {
+ "properties": ["attracta.com"],
+ "resources": ["attracta.com"]
+ },
+ "Audience2Media": {
+ "properties": ["audience2media.com"],
+ "resources": ["audience2media.com"]
+ },
+ "Audience Ad Network": {
+ "properties": ["audienceadnetwork.com"],
+ "resources": ["audienceadnetwork.com"]
+ },
+ "AudienceScience": {
+ "properties": ["audiencescience.com"],
+ "resources": [
+ "audiencescience.com",
+ "revsci.net",
+ "targetingmarketplace.com",
+ "wunderloop.net"
+ ]
+ },
+ "AuditedMedia": {
+ "properties": ["auditedmedia.com"],
+ "resources": ["aamapi.com", "aamsitecertifier.com", "auditedmedia.com"]
+ },
+ "Augme": {
+ "properties": ["hipcricket.com"],
+ "resources": ["augme.com", "hipcricket.com"]
+ },
+ "Augur": {
+ "properties": ["augur.io"],
+ "resources": ["augur.io"]
+ },
+ "AUTOCENTRE.UA": {
+ "properties": ["am.ua", "autocentre.ua"],
+ "resources": ["am.ua", "autocentre.ua"]
+ },
+ "Automattic": {
+ "properties": [
+ "automattic.com",
+ "gravatar.com",
+ "intensedebate.com",
+ "polldaddy.com"
+ ],
+ "resources": [
+ "automattic.com",
+ "gravatar.com",
+ "intensedebate.com",
+ "polldaddy.com",
+ "pubmine.com"
+ ]
+ },
+ "Avalanchers": {
+ "properties": ["avalanchers.com"],
+ "resources": ["avalanchers.com"]
+ },
+ "AvantLink": {
+ "properties": ["avantlink.com", "avantmetrics.com"],
+ "resources": ["avantlink.com", "avmws.com"]
+ },
+ "Avocet": {
+ "properties": ["avocet.io"],
+ "resources": ["avocet.io"]
+ },
+ "Avsads": {
+ "properties": ["avsads.com"],
+ "resources": ["avsads.com"]
+ },
+ "AWeber": {
+ "properties": ["aweber.com"],
+ "resources": ["aweber.com"]
+ },
+ "Awin": {
+ "properties": ["awin.com"],
+ "resources": [
+ "awin.com",
+ "digitalwindow.com",
+ "dwin1.com",
+ "perfiliate.com"
+ ]
+ },
+ "Awio": {
+ "properties": ["awio.com", "w3counter.com"],
+ "resources": ["awio.com", "w3counter.com", "w3roi.com"]
+ },
+ "Azet": {
+ "properties": ["azet.sk", "mediaimpact.sk"],
+ "resources": ["azet.sk", "azetklik.sk", "mediaimpact.sk", "rsz.sk"]
+ },
+ "BackBeat Media": {
+ "properties": ["backbeatmedia.com"],
+ "resources": ["backbeatmedia.com"]
+ },
+ "Bannerconnect": {
+ "properties": ["bannerconnect.net"],
+ "resources": ["bannerconnect.net"]
+ },
+ "Barilliance": {
+ "properties": ["barilliance.com"],
+ "resources": ["barilliance.com"]
+ },
+ "BaronsNetworks": {
+ "properties": ["baronsoffers.com"],
+ "resources": ["baronsoffers.com"]
+ },
+ "Batanga Network": {
+ "properties": ["batanga.com", "corp.vix.com", "vix.com"],
+ "resources": ["batanga.com", "batanganetwork.com", "vix.com"]
+ },
+ "Baynote": {
+ "properties": ["baynote.com"],
+ "resources": ["baynote.com", "baynote.net"]
+ },
+ "Bazaarvoice": {
+ "properties": ["bazaarvoice.com"],
+ "resources": ["bazaarvoice.com"]
+ },
+ "BeachFront": {
+ "properties": ["beachfront.com"],
+ "resources": ["beachfront.com"]
+ },
+ "Beanstock Media": {
+ "properties": ["beanstockmedia.com"],
+ "resources": ["beanstockmedia.com"]
+ },
+ "beencounter": {
+ "properties": ["beencounter.com"],
+ "resources": ["beencounter.com"]
+ },
+ "Begun": {
+ "properties": ["begun.ru"],
+ "resources": ["begun.ru"]
+ },
+ "belboon": {
+ "properties": ["belboon.com"],
+ "resources": ["adbutler.de", "belboon.com"]
+ },
+ "Belstat": {
+ "properties": [
+ "belstat.be",
+ "belstat.com",
+ "belstat.de",
+ "belstat.fr",
+ "belstat.nl"
+ ],
+ "resources": [
+ "belstat.be",
+ "belstat.com",
+ "belstat.de",
+ "belstat.fr",
+ "belstat.nl"
+ ]
+ },
+ "Betgenius": {
+ "properties": ["betgenius.com", "connextra.com"],
+ "resources": ["betgenius.com", "connextra.com"]
+ },
+ "BetssonPalantir": {
+ "properties": ["betssonpalantir.com"],
+ "resources": ["betssonpalantir.com"]
+ },
+ "BetweenDigital": {
+ "properties": ["betweendigital.com"],
+ "resources": ["betweendigital.com"]
+ },
+ "Bidfluence": {
+ "properties": ["bidfluence.com"],
+ "resources": ["bidfluence.com"]
+ },
+ "Bidr": {
+ "properties": ["bidr.io"],
+ "resources": ["bidr.io"]
+ },
+ "BidSwitch": {
+ "properties": ["bidswitch.com"],
+ "resources": ["bidswitch.net", "mfadsrvr.com"]
+ },
+ "Bidtellect": {
+ "properties": ["bidtellect.com", "bttrack.com"],
+ "resources": ["bidtellect.com", "bttrack.com"]
+ },
+ "BidVertiser": {
+ "properties": ["bidvertiser.com"],
+ "resources": ["bidvertiser.com"]
+ },
+ "BigClick": {
+ "properties": ["bigclick.me"],
+ "resources": ["bgclck.me", "xcvgdf.party"]
+ },
+ "BigDoor": {
+ "properties": ["bigdoor.com"],
+ "resources": ["bigdoor.com", "onetruefan.com"]
+ },
+ "bigmirnet": {
+ "properties": ["bigmir.net"],
+ "resources": ["bigmir.net"]
+ },
+ "BinLayer": {
+ "properties": ["binlayer.com"],
+ "resources": ["binlayer.com"]
+ },
+ "Bitcoin Plus": {
+ "properties": ["bitcoinplus.com"],
+ "resources": ["bitcoinplus.com"]
+ },
+ "BitMedia": {
+ "properties": ["bitmedia.io"],
+ "resources": ["bitmedia.io"]
+ },
+ "BittAds": {
+ "properties": ["bittads.com"],
+ "resources": ["bittads.com"]
+ },
+ "Bizo": {
+ "properties": ["bizo.com", "bizographics.com"],
+ "resources": ["bizo.com", "bizographics.com"]
+ },
+ "Black Label Ads": {
+ "properties": ["blacklabelads.com"],
+ "resources": ["blacklabelads.com"]
+ },
+ "BlogCatalog": {
+ "properties": ["blogcatalog.com"],
+ "resources": ["blogcatalog.com"]
+ },
+ "BlogCounter.com": {
+ "properties": ["blogcounter.de"],
+ "resources": ["blogcounter.de"]
+ },
+ "BlogFrog": {
+ "properties": ["theblogfrog.com"],
+ "resources": ["theblogfrog.com"]
+ },
+ "BlogHer": {
+ "properties": ["blogher.com", "blogherads.com"],
+ "resources": ["blogher.com", "blogherads.com"]
+ },
+ "BlogRollr": {
+ "properties": ["blogrollr.com"],
+ "resources": ["blogrollr.com"]
+ },
+ "BLOOM Digital Platforms": {
+ "properties": ["adgear.com", "bloom-hq.com"],
+ "resources": ["adgear.com", "adgrx.com", "bloom-hq.com"]
+ },
+ "BloomReach": {
+ "properties": ["bloomreach.com", "brcdn.com"],
+ "resources": ["bloomreach.com", "brcdn.com", "brsrvr.com"]
+ },
+ "BlueCava": {
+ "properties": ["bluecava.com"],
+ "resources": ["bluecava.com"]
+ },
+ "BlueKai": {
+ "properties": ["bluekai.com", "tracksimple.com"],
+ "resources": ["bkrtx.com", "bluekai.com", "tracksimple.com"]
+ },
+ "Bluemetrix": {
+ "properties": ["bluemetrix.com", "bmmetrix.com"],
+ "resources": ["bluemetrix.com", "bmmetrix.com"]
+ },
+ "Blu Trumpet": {
+ "properties": ["blutrumpet.com"],
+ "resources": ["blutrumpet.com"]
+ },
+ "Bombora": {
+ "properties": ["bombora.com"],
+ "resources": ["ml314.com"]
+ },
+ "Boo-Box": {
+ "properties": ["boo-box.com"],
+ "resources": ["boo-box.com"]
+ },
+ "BoostBox": {
+ "properties": ["boostbox.com.br"],
+ "resources": ["boostbox.com.br"]
+ },
+ "Bouncex": {
+ "properties": ["bouncex.com"],
+ "resources": ["bounceexchange.com", "bouncex.com", "bouncex.net"]
+ },
+ "Brainient": {
+ "properties": ["brainient.com"],
+ "resources": ["brainient.com"]
+ },
+ "Branch": {
+ "properties": ["branch.io"],
+ "resources": ["branch.io"]
+ },
+ "Brand Affinity Technologies": {
+ "properties": ["brandaffinity.net"],
+ "resources": ["brandaffinity.net"]
+ },
+ "Brandcrumb": {
+ "properties": ["brandcrumb.com"],
+ "resources": ["brandcrumb.com"]
+ },
+ "Brand.net": {
+ "properties": ["brand.net"],
+ "resources": ["brand.net"]
+ },
+ "Brandscreen": {
+ "properties": ["brandscreen.com", "rtbidder.net"],
+ "resources": ["brandscreen.com", "rtbidder.net"]
+ },
+ "Branica": {
+ "properties": ["branica.com"],
+ "resources": ["branica.com"]
+ },
+ "BreakTime": {
+ "properties": ["breaktime.com.tw"],
+ "resources": ["breaktime.com.tw"]
+ },
+ "Brightcove": {
+ "properties": ["brightcove.com"],
+ "resources": ["brightcove.com"]
+ },
+ "BrightEdge": {
+ "properties": ["brightedge.com"],
+ "resources": ["b0e8.com", "brightedge.com"]
+ },
+ "BrightRoll": {
+ "properties": ["brightroll.com"],
+ "resources": ["brightroll.com", "btrll.com"]
+ },
+ "BrightTag": {
+ "properties": ["brighttag.com", "btstatic.com", "thebrighttag.com"],
+ "resources": ["brighttag.com", "btstatic.com", "thebrighttag.com"]
+ },
+ "Brilig": {
+ "properties": ["brilig.com"],
+ "resources": ["brilig.com"]
+ },
+ "Browser-Update.org": {
+ "properties": ["browser-update.org"],
+ "resources": ["browser-update.org"]
+ },
+ "BTBuckets": {
+ "properties": ["btbuckets.com"],
+ "resources": ["btbuckets.com"]
+ },
+ "Bubblestat": {
+ "properties": ["bubblestat.com"],
+ "resources": ["bubblestat.com"]
+ },
+ "BuckSense": {
+ "properties": ["bucksense.com"],
+ "resources": ["bucksense.com"]
+ },
+ "Buffer": {
+ "properties": ["bufferapp.com"],
+ "resources": ["bufferapp.com"]
+ },
+ "Bunchball": {
+ "properties": ["bunchball.com"],
+ "resources": ["bunchball.com"]
+ },
+ "Burstly": {
+ "properties": ["burstly.com"],
+ "resources": ["burstly.com"]
+ },
+ "Burst Media": {
+ "properties": [
+ "burstbeacon.com",
+ "burstdirectads.com",
+ "burstmedia.com",
+ "burstnet.com",
+ "giantrealm.com"
+ ],
+ "resources": [
+ "burstbeacon.com",
+ "burstdirectads.com",
+ "burstmedia.com",
+ "burstnet.com",
+ "giantrealm.com"
+ ]
+ },
+ "BusinessOnline": {
+ "properties": ["businessol.com"],
+ "resources": ["businessol.com"]
+ },
+ "Button": {
+ "properties": ["usebutton.com"],
+ "resources": ["usebutton.com"]
+ },
+ "buySAFE": {
+ "properties": ["buysafe.com"],
+ "resources": ["buysafe.com"]
+ },
+ "BuySellAds": {
+ "properties": ["beaconads.com", "buysellads.com"],
+ "resources": ["beaconads.com", "buysellads.com"]
+ },
+ "Buysight": {
+ "properties": ["buysight.com", "permuto.com", "pulsemgr.com"],
+ "resources": ["buysight.com", "permuto.com", "pulsemgr.com"]
+ },
+ "BuzzFeed": {
+ "properties": ["buzzfeed.com"],
+ "resources": ["buzzfed.com", "buzzfeed.com"]
+ },
+ "BuzzParadise": {
+ "properties": ["buzzparadise.com"],
+ "resources": ["buzzparadise.com"]
+ },
+ "BV! MEDIA": {
+ "properties": ["branchez-vous.com", "bvmedia.ca"],
+ "resources": [
+ "branchez-vous.com",
+ "bvmedia.ca",
+ "networldmedia.com",
+ "networldmedia.net"
+ ]
+ },
+ "c1exchange": {
+ "properties": ["c1exchange.com"],
+ "resources": ["c1exchange.com"]
+ },
+ "C3 Metrics": {
+ "properties": ["attributionmodel.com", "c3metrics.com", "c3tag.com"],
+ "resources": ["attributionmodel.com", "c3metrics.com", "c3tag.com"]
+ },
+ "Cadreon": {
+ "properties": ["cadreon.com"],
+ "resources": ["cadreon.com"]
+ },
+ "CallSource": {
+ "properties": ["callsource.com"],
+ "resources": ["leadtrackingdata.com"]
+ },
+ "CampaignGrid": {
+ "properties": ["campaigngrid.com"],
+ "resources": ["campaigngrid.com"]
+ },
+ "CAPITALDATA": {
+ "properties": ["capitaldata.fr"],
+ "resources": ["capitaldata.fr"]
+ },
+ "Carambola": {
+ "properties": ["carambola.com"],
+ "resources": ["carambo.la"]
+ },
+ "Caraytech": {
+ "properties": [
+ "caraytech.com.ar",
+ "e-planning.net",
+ "www.caraytech.com.ar"
+ ],
+ "resources": ["caraytech.com.ar", "e-planning.net", "www.caraytech.com.ar"]
+ },
+ "Cardlytics": {
+ "properties": ["cardlytics.com"],
+ "resources": ["cardlytics.com"]
+ },
+ "Cart.ro": {
+ "properties": ["cart.ro"],
+ "resources": ["cart.ro", "statistics.ro"]
+ },
+ "CartsGuru": {
+ "properties": ["carts.guru"],
+ "resources": ["carts.guru"]
+ },
+ "Casale Media": {
+ "properties": ["casalemedia.com", "medianet.com"],
+ "resources": ["casalemedia.com", "medianet.com"]
+ },
+ "CashBeet": {
+ "properties": ["cashbeet.com"],
+ "resources": ["cashbeet.com", "serv1swork.com"]
+ },
+ "Causes": {
+ "properties": ["causes.com"],
+ "resources": ["causes.com"]
+ },
+ "Cbox": {
+ "properties": ["cbox.ws"],
+ "resources": ["cbox.ws"]
+ },
+ "CBproADS": {
+ "properties": ["cbproads.com"],
+ "resources": ["cbproads.com"]
+ },
+ "CBS Interactive": {
+ "properties": ["cbsinteractive.com", "com.com"],
+ "resources": ["cbsinteractive.com", "com.com"]
+ },
+ "Cedato": {
+ "properties": ["cedato.com"],
+ "resources": ["cedato.com"]
+ },
+ "Cedexis": {
+ "properties": ["cedexis.com"],
+ "resources": ["cedexis.com", "cedexis.net"]
+ },
+ "Certona": {
+ "properties": ["certona.com", "res-x.com"],
+ "resources": ["certona.com", "res-x.com"]
+ },
+ "Chango": {
+ "properties": ["chango.ca", "chango.com"],
+ "resources": ["chango.ca", "chango.com"]
+ },
+ "ChannelAdvisor": {
+ "properties": ["channeladvisor.com", "searchmarketing.com"],
+ "resources": ["channeladvisor.com", "searchmarketing.com"]
+ },
+ "Channel Intelligence": {
+ "properties": ["channelintelligence.com"],
+ "resources": ["channelintelligence.com"]
+ },
+ "Chartbeat": {
+ "properties": ["chartbeat.com", "chartbeat.net"],
+ "resources": ["chartbeat.com", "chartbeat.net"]
+ },
+ "Chartboost": {
+ "properties": ["chartboost.com"],
+ "resources": ["chartboost.com"]
+ },
+ "CheckM8": {
+ "properties": ["checkm8.com"],
+ "resources": ["checkm8.com"]
+ },
+ "Chitika": {
+ "properties": ["chitika.com"],
+ "resources": ["chitika.com", "chitika.net"]
+ },
+ "ChoiceStream": {
+ "properties": ["choicestream.com"],
+ "resources": ["choicestream.com"]
+ },
+ "ClearLink": {
+ "properties": ["clearlink.com"],
+ "resources": ["clearlink.com"]
+ },
+ "ClearSaleing": {
+ "properties": ["clearsaleing.com"],
+ "resources": [
+ "clearsaleing.com",
+ "csdata1.com",
+ "csdata2.com",
+ "csdata3.com"
+ ]
+ },
+ "Clearsearch Media": {
+ "properties": ["pathinteractive.com"],
+ "resources": [
+ "clearsearchmedia.com",
+ "csm-secure.com",
+ "pathinteractive.com"
+ ]
+ },
+ "ClearSight Interactive": {
+ "properties": ["clearsightinteractive.com", "csi-tracking.com"],
+ "resources": ["clearsightinteractive.com", "csi-tracking.com"]
+ },
+ "ClickAider": {
+ "properties": ["clickaider.com"],
+ "resources": ["clickaider.com"]
+ },
+ "Clickayab": {
+ "properties": ["clickyab.com"],
+ "resources": ["clickyab.com"]
+ },
+ "Clickbooth": {
+ "properties": ["clickbooth.com"],
+ "resources": ["adtoll.com", "clickbooth.com"]
+ },
+ "Clickdensity": {
+ "properties": ["clickdensity.com"],
+ "resources": ["clickdensity.com"]
+ },
+ "ClickDimensions": {
+ "properties": ["clickdimensions.com"],
+ "resources": ["clickdimensions.com"]
+ },
+ "ClickDistrict": {
+ "properties": ["clickdistrict.com", "creative-serving.com"],
+ "resources": ["clickdistrict.com", "creative-serving.com"]
+ },
+ "ClickFrog": {
+ "properties": ["clickfrog.ru"],
+ "resources": [
+ "bashirian.biz",
+ "buckridge.link",
+ "clickfrog.ru",
+ "franecki.net",
+ "quitzon.net",
+ "reichelcormier.bid",
+ "wisokykulas.bid"
+ ]
+ },
+ "ClickFuel": {
+ "properties": ["clickfuel.com", "myconversionlab.com"],
+ "resources": [
+ "clickfuel.com",
+ "conversiondashboard.com",
+ "myconversionlab.com"
+ ]
+ },
+ "ClickGuard": {
+ "properties": ["clickguard.com"],
+ "resources": ["clickguard.com"]
+ },
+ "ClickInc": {
+ "properties": ["clickinc.com"],
+ "resources": ["clickinc.com"]
+ },
+ "Clicksor": {
+ "properties": ["clicksor.com", "clicksor.net"],
+ "resources": ["clicksor.com", "clicksor.net"]
+ },
+ "ClickTale": {
+ "properties": ["clicktale.com"],
+ "resources": ["clicktale.com", "clicktale.net", "pantherssl.com"]
+ },
+ "Clickwinks": {
+ "properties": ["clickwinks.com"],
+ "resources": ["clickwinks.com"]
+ },
+ "ClicManager": {
+ "properties": ["clicmanager.fr"],
+ "resources": ["clicmanager.fr"]
+ },
+ "ClipSyndicate": {
+ "properties": ["clipsyndicate.com"],
+ "resources": ["clipsyndicate.com"]
+ },
+ "ClixMetrix": {
+ "properties": ["clixmetrix.com"],
+ "resources": ["clixmetrix.com"]
+ },
+ "Clixpy": {
+ "properties": ["clixpy.com"],
+ "resources": ["clixpy.com"]
+ },
+ "Clixtell": {
+ "properties": ["clixtell.com"],
+ "resources": ["clixtell.com"]
+ },
+ "Clove Network": {
+ "properties": ["clovenetwork.com"],
+ "resources": ["clovenetwork.com"]
+ },
+ "ClustrMaps": {
+ "properties": ["clustrmaps.com"],
+ "resources": ["clustrmaps.com"]
+ },
+ "CNZZ": {
+ "properties": ["cnzz.com"],
+ "resources": ["cnzz.com"]
+ },
+ "Cognitive Match": {
+ "properties": [
+ "cmads.com.tw",
+ "cmadsasia.com",
+ "cmadseu.com",
+ "cmmeglobal.com",
+ "cognitivematch.com"
+ ],
+ "resources": [
+ "cmads.com.tw",
+ "cmadsasia.com",
+ "cmadseu.com",
+ "cmmeglobal.com",
+ "cognitivematch.com"
+ ]
+ },
+ "CoinHive": {
+ "properties": ["authedmine.com", "coinhive.com"],
+ "resources": [
+ "ad-miner.com",
+ "authedmine.com",
+ "bmst.pw",
+ "cnhv.co",
+ "coin-hive.com",
+ "coinhive.com",
+ "wsservices.org"
+ ]
+ },
+ "CoinPot": {
+ "properties": ["coinpot.co"],
+ "resources": ["coinpot.co"]
+ },
+ "Collarity": {
+ "properties": ["collarity.com"],
+ "resources": ["collarity.com"]
+ },
+ "Collective": {
+ "properties": ["collective.com"],
+ "resources": [
+ "collective-media.net",
+ "collective.com",
+ "oggifinogi.com",
+ "tumri.com",
+ "tumri.net",
+ "yt1187.net"
+ ]
+ },
+ "Commission Junction": {
+ "properties": ["cj.com"],
+ "resources": [
+ "apmebf.com",
+ "awltovhc.com",
+ "cj.com",
+ "ftjcfx.com",
+ "kcdwa.com",
+ "qksz.com",
+ "qksz.net",
+ "tqlkg.com",
+ "yceml.net"
+ ]
+ },
+ "Communicator Corp": {
+ "properties": ["communicatorcorp.com"],
+ "resources": ["communicatorcorp.com"]
+ },
+ "Compass Labs": {
+ "properties": ["compasslabs.com"],
+ "resources": ["compasslabs.com"]
+ },
+ "Complex Media": {
+ "properties": [
+ "collider.com",
+ "complex.com",
+ "complexmedianetwork.com",
+ "firstwefeast.com",
+ "pigeonsandplanes.com",
+ "solecollector.com",
+ "theridechannel.com"
+ ],
+ "resources": ["complex.com", "complexmedianetwork.com"]
+ },
+ "Compuware": {
+ "properties": ["axf8.net", "compuware.com", "dynatrace.com"],
+ "resources": ["axf8.net", "compuware.com", "dynatrace.com", "gomez.com"]
+ },
+ "comScore": {
+ "properties": [
+ "adxpose.com",
+ "comscore.com",
+ "scorecardresearch.com",
+ "sitestat.com",
+ "voicefive.com"
+ ],
+ "resources": [
+ "adxpose.com",
+ "certifica.com",
+ "comscore.com",
+ "mdotlabs.com",
+ "proxilinks.com",
+ "proximic.com",
+ "proximic.net",
+ "scorecardresearch.com",
+ "sitestat.com",
+ "voicefive.com"
+ ]
+ },
+ "Conduit": {
+ "properties": ["conduit-banners.com", "conduit.com"],
+ "resources": [
+ "conduit-banners.com",
+ "conduit-services.com",
+ "conduit.com",
+ "wibiya.com"
+ ]
+ },
+ "Congoo": {
+ "properties": ["congoo.com"],
+ "resources": ["congoo.com"]
+ },
+ "Connatix.com": {
+ "properties": ["connatix.com"],
+ "resources": ["connatix.com"]
+ },
+ "Connexity": {
+ "properties": ["connexity.com", "pricegrabber.com"],
+ "resources": ["connexity.com", "connexity.net", "pricegrabber.com"]
+ },
+ "Consilium Media": {
+ "properties": ["consiliummedia.com"],
+ "resources": ["consiliummedia.com"]
+ },
+ "Consumable": {
+ "properties": ["consumable.com"],
+ "resources": ["consumable.com"]
+ },
+ "Contact At Once!": {
+ "properties": ["contactatonce.com"],
+ "resources": ["contactatonce.com"]
+ },
+ "CONTAXE": {
+ "properties": ["contaxe.com"],
+ "resources": ["contaxe.com"]
+ },
+ "ContentABC": {
+ "properties": ["contentabc.com"],
+ "resources": ["contentabc.com"]
+ },
+ "CONTEXTin": {
+ "properties": ["admailtiser.com", "contextin.com"],
+ "resources": ["admailtiser.com", "contextin.com"]
+ },
+ "ContextuAds": {
+ "properties": ["agencytradingdesk.net", "contextuads.com"],
+ "resources": ["agencytradingdesk.net", "contextuads.com"]
+ },
+ "CONTEXTWEB": {
+ "properties": ["contextweb.com"],
+ "resources": ["contextweb.com"]
+ },
+ "ConvergeDirect": {
+ "properties": ["convergedirect.com", "convergetrack.com"],
+ "resources": ["convergedirect.com", "convergetrack.com"]
+ },
+ "ConversantMedia": {
+ "properties": ["conversantmedia.com"],
+ "resources": [
+ "adserver.com",
+ "conversantmedia.com",
+ "dotomi.com",
+ "dtmpub.com",
+ "emjcd.com",
+ "fastclick.com",
+ "fastclick.net",
+ "greystripe.com",
+ "lduhtrp.net",
+ "mediaplex.com",
+ "valueclick.com",
+ "valueclick.net",
+ "valueclickmedia.com"
+ ]
+ },
+ "ConversionRuler": {
+ "properties": ["conversionruler.com"],
+ "resources": ["conversionruler.com"]
+ },
+ "Conversive": {
+ "properties": ["conversive.nl"],
+ "resources": ["conversive.nl"]
+ },
+ "Convert Insights": {
+ "properties": ["convert.com", "reedge.com"],
+ "resources": ["convert.com", "reedge.com"]
+ },
+ "Convertro": {
+ "properties": ["convertro.com"],
+ "resources": ["convertro.com"]
+ },
+ "Conviva": {
+ "properties": ["conviva.com"],
+ "resources": ["conviva.com"]
+ },
+ "CoreMotives": {
+ "properties": ["coremotives.com"],
+ "resources": ["coremotives.com"]
+ },
+ "Cox Digital Solutions": {
+ "properties": ["adify.com", "coxdigitalsolutions.com", "novomotus.com"],
+ "resources": [
+ "adify.com",
+ "afy11.net",
+ "coxdigitalsolutions.com",
+ "novomotus.com"
+ ]
+ },
+ "CPMStar": {
+ "properties": ["cpmstar.com"],
+ "resources": ["cpmstar.com"]
+ },
+ "CPX Interactive": {
+ "properties": ["cpxadroit.com"],
+ "resources": ["adreadypixels.com", "cpxadroit.com", "cpxinteractive.com"]
+ },
+ "Crazy Egg": {
+ "properties": ["cetrk.com", "crazyegg.com"],
+ "resources": ["cetrk.com", "crazyegg.com"]
+ },
+ "Creafi": {
+ "properties": ["creafi.com"],
+ "resources": ["creafi.com"]
+ },
+ "Crimtan": {
+ "properties": ["crimtan.com"],
+ "resources": ["crimtan.com"]
+ },
+ "Crisp Media": {
+ "properties": ["crispmedia.com"],
+ "resources": ["crispmedia.com"]
+ },
+ "Criteo": {
+ "properties": ["criteo.com", "criteo.net"],
+ "resources": [
+ "criteo.com",
+ "criteo.net",
+ "hlserve.com",
+ "hooklogic.com",
+ "storetail.io"
+ ]
+ },
+ "Cross Pixel": {
+ "properties": ["crosspixel.net"],
+ "resources": ["crosspixel.net", "crosspixelmedia.com", "crsspxl.com"]
+ },
+ "Crowd Science": {
+ "properties": ["crowdscience.com"],
+ "resources": ["crowdscience.com"]
+ },
+ "CryptoLoot": {
+ "properties": ["crypto-loot.com"],
+ "resources": [
+ "cryptaloot.pro",
+ "crypto-loot.com",
+ "cryptolootminer.com",
+ "flashx.pw",
+ "gitgrub.pro",
+ "reauthenticator.com",
+ "statdynamic.com",
+ "webmine.pro"
+ ]
+ },
+ "CryptoWebMiner": {
+ "properties": ["crypto-webminer.com"],
+ "resources": [
+ "bitcoin-pay.eu",
+ "crypto-webminer.com",
+ "ethpocket.de",
+ "ethtrader.de"
+ ]
+ },
+ "cXense": {
+ "properties": ["cxense.com"],
+ "resources": [
+ "cxense.com",
+ "emediate.biz",
+ "emediate.com",
+ "emediate.dk",
+ "emediate.eu"
+ ]
+ },
+ "Cya2": {
+ "properties": ["cya2.net"],
+ "resources": ["cya2.net"]
+ },
+ "Cyberplex": {
+ "properties": ["cyberplex.com"],
+ "resources": ["cyberplex.com"]
+ },
+ "Dada": {
+ "properties": ["dada.eu", "dada.pro", "simply.com"],
+ "resources": ["dada.eu", "dada.pro", "simply.com"]
+ },
+ "DailyMe": {
+ "properties": ["dailyme.com", "newstogram.com"],
+ "resources": ["dailyme.com", "newstogram.com"]
+ },
+ "Dataium": {
+ "properties": ["collserve.com", "ihs.com"],
+ "resources": ["collserve.com", "dataium.com", "ihs.com"]
+ },
+ "Datalogix": {
+ "properties": ["datalogix.com", "nexac.com"],
+ "resources": ["datalogix.com", "nexac.com", "nextaction.net"]
+ },
+ "DataSift": {
+ "properties": ["datasift.com", "tweetmeme.com"],
+ "resources": ["datasift.com", "tweetmeme.com"]
+ },
+ "DataXu": {
+ "properties": ["dataxu.com", "mexad.com", "w55c.net"],
+ "resources": ["dataxu.com", "dataxu.net", "mexad.com", "w55c.net"]
+ },
+ "Datonics": {
+ "properties": ["datonics.com"],
+ "resources": ["datonics.com", "pro-market.net"]
+ },
+ "Datran Media": {
+ "properties": ["datranmedia.com", "displaymarketplace.com"],
+ "resources": ["datranmedia.com", "displaymarketplace.com"]
+ },
+ "Datvantage": {
+ "properties": ["datvantage.com"],
+ "resources": ["datvantage.com"]
+ },
+ "DC Storm": {
+ "properties": ["dc-storm.com", "stormiq.com"],
+ "resources": ["dc-storm.com", "stormiq.com"]
+ },
+ "Dedicated Media": {
+ "properties": ["dedicatedmedia.com", "dedicatednetworks.com"],
+ "resources": ["dedicatedmedia.com", "dedicatednetworks.com"]
+ },
+ "Deep Intent": {
+ "properties": ["deepintent.com"],
+ "resources": ["deepintent.com"]
+ },
+ "Delivr": {
+ "properties": ["delivr.com"],
+ "resources": ["delivr.com", "percentmobile.com"]
+ },
+ "Delta Projects": {
+ "properties": ["deltaprojects.com"],
+ "resources": [
+ "adaction.se",
+ "de17a.com",
+ "deltaprojects.com",
+ "deltaprojects.se"
+ ]
+ },
+ "Demandbase": {
+ "properties": ["demandbase.com"],
+ "resources": ["company-target.com", "demandbase.com"]
+ },
+ "Demand Media": {
+ "properties": ["leafgroup.com"],
+ "resources": ["demandmedia.com", "indieclick.com"]
+ },
+ "Deutsche Post DHL": {
+ "properties": ["dpdhl.com"],
+ "resources": ["adcloud.com", "adcloud.net", "dp-dhl.com", "dpdhl.com"]
+ },
+ "Developer Media": {
+ "properties": ["developermedia.com"],
+ "resources": ["developermedia.com", "lqcdn.com"]
+ },
+ "DG": {
+ "properties": ["dgit.com", "sizmek.com"],
+ "resources": [
+ "dgit.com",
+ "eyeblaster.com",
+ "eyewonder.com",
+ "mdadx.com",
+ "serving-sys.com",
+ "unicast.com"
+ ]
+ },
+ "dianomi": {
+ "properties": ["dianomi.com"],
+ "resources": ["dianomi.com"]
+ },
+ "Didit": {
+ "properties": ["didit.com"],
+ "resources": ["did-it.com", "didit.com"]
+ },
+ "Digg": {
+ "properties": ["digg.com"],
+ "resources": ["digg.com"]
+ },
+ "DigitalAdConsortium": {
+ "properties": ["dac.co.jp"],
+ "resources": ["impact-ad.jp"]
+ },
+ "Digital River": {
+ "properties": ["digitalriver.com", "keywordmax.com", "netflame.cc"],
+ "resources": ["digitalriver.com", "keywordmax.com", "netflame.cc"]
+ },
+ "Digital Target": {
+ "properties": ["digitaltarget.ru"],
+ "resources": ["digitaltarget.ru"]
+ },
+ "Digitize": {
+ "properties": ["digitize.ie"],
+ "resources": ["digitize.ie"]
+ },
+ "DirectAdvert": {
+ "properties": ["directadvert.ru"],
+ "resources": ["directadvert.ru"]
+ },
+ "DirectCORP": {
+ "properties": ["directcorp.de", "ipcounter.de"],
+ "resources": ["directcorp.de", "ipcounter.de"]
+ },
+ "Direct Response Group": {
+ "properties": ["directresponsegroup.com"],
+ "resources": ["directresponsegroup.com", "ppctracking.net"]
+ },
+ "Directtrack": {
+ "properties": ["directtrack.com"],
+ "resources": ["directtrack.com"]
+ },
+ "Disqus": {
+ "properties": ["disqus.com", "disqusads.com"],
+ "resources": ["disqus.com", "disqusads.com"]
+ },
+ "DistilNetworks": {
+ "properties": ["distilnetworks.com"],
+ "resources": ["distilnetworks.com", "distiltag.com"]
+ },
+ "DistrictM": {
+ "properties": ["districtm.net"],
+ "resources": ["districtm.io"]
+ },
+ "dmpxs": {
+ "properties": ["dmpxs.com"],
+ "resources": ["dmpxs.com"]
+ },
+ "DoublePimp": {
+ "properties": ["doublepimp.com"],
+ "resources": ["doublepimp.com"]
+ },
+ "DoublePositive": {
+ "properties": ["doublepositive.com"],
+ "resources": ["bid-tag.com", "doublepositive.com"]
+ },
+ "DoubleVerify": {
+ "properties": ["doubleverify.com"],
+ "resources": ["doubleverify.com"]
+ },
+ "Drawbridge": {
+ "properties": ["drawbridge.com"],
+ "resources": ["adsymptotic.com", "drawbrid.ge", "drawbridge.com"]
+ },
+ "DS-IQ": {
+ "properties": ["ds-iq.com"],
+ "resources": ["ds-iq.com"]
+ },
+ "DSNR Group": {
+ "properties": ["dsnrgroup.com", "dsnrmg.com", "traffiliate.com", "z5x.net"],
+ "resources": [
+ "dsnrgroup.com",
+ "dsnrmg.com",
+ "traffiliate.com",
+ "z5x.com",
+ "z5x.net"
+ ]
+ },
+ "dwstat.com": {
+ "properties": ["dwstat.cn"],
+ "resources": ["dwstat.cn"]
+ },
+ "DynAdmic": {
+ "properties": ["dynadmic.com"],
+ "resources": ["dynadmic.com", "dyntrk.com"]
+ },
+ "DynamicOxygen": {
+ "properties": ["dynamicoxygen.com", "exitjunction.com"],
+ "resources": ["dynamicoxygen.com", "exitjunction.com"]
+ },
+ "DynamicYield": {
+ "properties": ["dynamicyield.com"],
+ "resources": ["dynamicyield.com"]
+ },
+ "Earnify": {
+ "properties": ["earnify.com"],
+ "resources": ["earnify.com"]
+ },
+ "eBay": {
+ "properties": [
+ "ebay.at",
+ "ebay.ba",
+ "ebay.be",
+ "ebay.ca",
+ "ebay.ch",
+ "ebay.cn",
+ "ebay.co.jp",
+ "ebay.co.kr",
+ "ebay.co.uk",
+ "ebay.com",
+ "ebay.com.au",
+ "ebay.com.hk",
+ "ebay.com.my",
+ "ebay.com.ph",
+ "ebay.com.sg",
+ "ebay.com.tw",
+ "ebay.de",
+ "ebay.es",
+ "ebay.fr",
+ "ebay.ie",
+ "ebay.in",
+ "ebay.it",
+ "ebay.nl",
+ "ebay.pl"
+ ],
+ "resources": ["ebay.com"]
+ },
+ "Echo": {
+ "properties": ["aboutecho.com", "haloscan.com", "js-kit.com"],
+ "resources": ["aboutecho.com", "haloscan.com", "js-kit.com"]
+ },
+ "ECSAnalytics": {
+ "properties": ["ecsanalytics.com", "theecsinc.com"],
+ "resources": ["ecsanalytics.com"]
+ },
+ "EFF": {
+ "properties": [
+ "do-not-tracker.org",
+ "eff.org",
+ "eviltracker.net",
+ "trackersimulator.org"
+ ],
+ "resources": [
+ "do-not-tracker.org",
+ "eff.org",
+ "eviltracker.net",
+ "trackersimulator.org"
+ ]
+ },
+ "Effective Measure": {
+ "properties": ["effectivemeasure.com", "effectivemeasure.net"],
+ "resources": ["effectivemeasure.com", "effectivemeasure.net"]
+ },
+ "ekolay": {
+ "properties": ["hurriyet.com.tr"],
+ "resources": ["e-kolay.net", "ekolay.net", "hurriyet.com.tr"]
+ },
+ "Eleavers": {
+ "properties": ["eleavers.com"],
+ "resources": ["eleavers.com"]
+ },
+ "Emego": {
+ "properties": ["usemax.de"],
+ "resources": ["usemax.de"]
+ },
+ "Emerse": {
+ "properties": ["emerse.com"],
+ "resources": ["emerse.com"]
+ },
+ "EMX": {
+ "properties": ["emxdigital.com"],
+ "resources": [
+ "brealtime.com",
+ "clearstream.tv",
+ "emxdgt.com",
+ "emxdigital.com"
+ ]
+ },
+ "Enecto": {
+ "properties": ["enecto.com"],
+ "resources": ["enecto.com"]
+ },
+ "engage:BDR": {
+ "properties": ["engagebdr.com"],
+ "resources": ["bnmla.com", "engagebdr.com"]
+ },
+ "Engago Technology": {
+ "properties": ["engago.com"],
+ "resources": ["appmetrx.com", "engago.com"]
+ },
+ "Engine Network": {
+ "properties": ["enginenetwork.com"],
+ "resources": ["enginenetwork.com"]
+ },
+ "Ensighten": {
+ "properties": ["ensighten.com"],
+ "resources": ["ensighten.com"]
+ },
+ "Entireweb": {
+ "properties": ["entireweb.com"],
+ "resources": ["entireweb.com"]
+ },
+ "Epic Media Group": {
+ "properties": [
+ "epicadvertising.com",
+ "epicmarketplace.com",
+ "theepicmediagroup.com"
+ ],
+ "resources": [
+ "epicadvertising.com",
+ "epicmarketplace.com",
+ "epicmobileads.com",
+ "theepicmediagroup.com",
+ "trafficmp.com"
+ ]
+ },
+ "eProof.com": {
+ "properties": ["eproof.com"],
+ "resources": ["eproof.com"]
+ },
+ "Epsilon": {
+ "properties": ["epsilon.com"],
+ "resources": ["epsilon.com"]
+ },
+ "EQ Ads": {
+ "properties": ["eqads.com"],
+ "resources": ["eqads.com"]
+ },
+ "EroAdvertising": {
+ "properties": ["ero-advertising.com"],
+ "resources": ["ero-advertising.com"]
+ },
+ "Etarget": {
+ "properties": ["etarget.net", "etargetnet.com"],
+ "resources": ["etarget.net", "etargetnet.com"]
+ },
+ "Etineria": {
+ "properties": ["adwitserver.com", "etineria.com"],
+ "resources": ["adwitserver.com", "etineria.com"]
+ },
+ "etracker": {
+ "properties": ["etracker.com", "etracker.de"],
+ "resources": [
+ "etracker.com",
+ "etracker.de",
+ "sedotracker.com",
+ "sedotracker.de"
+ ]
+ },
+ "eTrigue": {
+ "properties": ["etrigue.com"],
+ "resources": ["etrigue.com"]
+ },
+ "Eulerian Technologies": {
+ "properties": ["eulerian.com"],
+ "resources": ["eulerian.com", "eulerian.net"]
+ },
+ "Evergage": {
+ "properties": ["evergage.com"],
+ "resources": ["mybuys.com", "veruta.com"]
+ },
+ "Everyday Health": {
+ "properties": ["everydayhealth.com", "waterfrontmedia.com"],
+ "resources": ["everydayhealth.com", "waterfrontmedia.com"]
+ },
+ "Evisions Marketing": {
+ "properties": ["engineseeker.com", "evisionsmarketing.com"],
+ "resources": ["engineseeker.com", "evisionsmarketing.com"]
+ },
+ "Evolve": {
+ "properties": ["evolvemediacorp.com", "gorillanation.com"],
+ "resources": [
+ "evolvemediacorp.com",
+ "evolvemediametrics.com",
+ "gorillanation.com"
+ ]
+ },
+ "eWayDirect": {
+ "properties": ["ewaydirect.com"],
+ "resources": ["ewaydirect.com", "ixs1.net"]
+ },
+ "ewebse": {
+ "properties": ["777seo.com", "ewebse.com"],
+ "resources": ["777seo.com", "ewebse.com"]
+ },
+ "excitad": {
+ "properties": ["excitad.com"],
+ "resources": ["excitad.com"]
+ },
+ "eXelate": {
+ "properties": ["exelate.com"],
+ "resources": ["exelate.com", "exelator.com"]
+ },
+ "ExoClick": {
+ "properties": ["exoclick.com"],
+ "resources": ["exoclick.com"]
+ },
+ "Exosrv": {
+ "properties": ["exosrv.com"],
+ "resources": ["exosrv.com"]
+ },
+ "Experian": {
+ "properties": ["experian.com"],
+ "resources": ["audienceiq.com", "experian.com"]
+ },
+ "expo-MAX": {
+ "properties": ["expo-max.com"],
+ "resources": ["expo-max.com"]
+ },
+ "Exponential Interactive": {
+ "properties": ["exponential.com", "fulltango.com"],
+ "resources": [
+ "adotube.com",
+ "exponential.com",
+ "fulltango.com",
+ "tribalfusion.com"
+ ]
+ },
+ "Extension Factory": {
+ "properties": ["extensionfactory.com"],
+ "resources": ["extensionfactory.com"]
+ },
+ "EXTENSIONS.RU": {
+ "properties": ["extensions.ru"],
+ "resources": ["extensions.ru"]
+ },
+ "eXTReMe digital": {
+ "properties": ["extremetracking.com"],
+ "resources": ["extreme-dm.com", "extremetracking.com"]
+ },
+ "Eyeconomy": {
+ "properties": ["eyeconomy.co.uk"],
+ "resources": [
+ "eyeconomy.co.uk",
+ "eyeconomy.com",
+ "sublimemedia.net",
+ "www.eyeconomy.co.uk"
+ ]
+ },
+ "EyeNewton": {
+ "properties": ["eyenewton.ru"],
+ "resources": ["eyenewton.ru"]
+ },
+ "Eyeota": {
+ "properties": ["eyeota.net"],
+ "resources": ["eyeota.net"]
+ },
+ "eyeReturn Marketing": {
+ "properties": ["eyereturnmarketing.com"],
+ "resources": ["eyereturn.com", "eyereturnmarketing.com"]
+ },
+ "Eyeviewdigital": {
+ "properties": ["eyeviewdigital.com"],
+ "resources": ["eyeviewads.com", "eyeviewdigital.com"]
+ },
+ "Facebook": {
+ "properties": [
+ "atlassolutions.com",
+ "facebook.com",
+ "facebook.de",
+ "facebook.fr",
+ "facebook.net",
+ "fb.com",
+ "fb.me",
+ "fbcdn.net",
+ "friendfeed.com",
+ "instagram.com",
+ "internalfb.com",
+ "messenger.com",
+ "oculus.com",
+ "whatsapp.com",
+ "workplace.com"
+ ],
+ "resources": [
+ "apps.fbsbx.com",
+ "atdmt.com",
+ "atlassolutions.com",
+ "facebook.com",
+ "facebook.de",
+ "facebook.fr",
+ "facebook.net",
+ "fb.com",
+ "fb.me",
+ "fbcdn.net",
+ "fbsbx.com",
+ "friendfeed.com",
+ "instagram.com",
+ "messenger.com"
+ ]
+ },
+ "Facilitate Digital": {
+ "properties": [
+ "adsfac.eu",
+ "adsfac.net",
+ "adsfac.us",
+ "facilitatedigital.com"
+ ],
+ "resources": [
+ "adsfac.eu",
+ "adsfac.info",
+ "adsfac.net",
+ "adsfac.sg",
+ "adsfac.us",
+ "facilitatedigital.com"
+ ]
+ },
+ "Fairfax Media": {
+ "properties": ["fairfax.com.au", "fxj.com.au", "www.fxj.com.au"],
+ "resources": ["fairfax.com.au", "fxj.com.au", "www.fxj.com.au"]
+ },
+ "faithadnet": {
+ "properties": ["faithadnet.com"],
+ "resources": ["faithadnet.com"]
+ },
+ "Fanplayr": {
+ "properties": ["fanplayr.com"],
+ "resources": ["fanplayr.com"]
+ },
+ "Fathom": {
+ "properties": ["fathomdelivers.com", "fathomseo.com"],
+ "resources": ["fathomdelivers.com", "fathomseo.com"]
+ },
+ "Federated Media": {
+ "properties": ["hyfn.com", "lijit.com"],
+ "resources": ["federatedmedia.net", "fmpub.net", "hyfn.com", "lijit.com"]
+ },
+ "Feedjit": {
+ "properties": ["feedjit.com"],
+ "resources": ["feedjit.com"]
+ },
+ "FetchBack": {
+ "properties": ["fetchback.com"],
+ "resources": ["fetchback.com"]
+ },
+ "Fiksu": {
+ "properties": ["fiksu.com"],
+ "resources": ["fiksu.com"]
+ },
+ "FinancialContent": {
+ "properties": ["financialcontent.com"],
+ "resources": ["financialcontent.com"]
+ },
+ "Fizz-Buzz Media": {
+ "properties": ["fizzbuzzmedia.com", "fizzbuzzmedia.net"],
+ "resources": ["fizzbuzzmedia.com", "fizzbuzzmedia.net"]
+ },
+ "Flashtalking": {
+ "properties": ["flashtalking.com"],
+ "resources": ["encoremetrics.com", "flashtalking.com", "sitecompass.com"]
+ },
+ "Flattr": {
+ "properties": ["flattr.com"],
+ "resources": ["flattr.com"]
+ },
+ "Flite": {
+ "properties": ["flite.com", "widgetserver.com"],
+ "resources": ["flite.com", "widgetserver.com"]
+ },
+ "Fluct": {
+ "properties": ["adingo.jp", "fluct.jp"],
+ "resources": ["adingo.jp", "fluct.jp"]
+ },
+ "Flytxt": {
+ "properties": ["flytxt.com"],
+ "resources": ["flytxt.com"]
+ },
+ "Footprint": {
+ "properties": ["footprintlive.com"],
+ "resources": ["footprintlive.com"]
+ },
+ "Forbes": {
+ "properties": ["brandsideplatform.com", "forbes.com"],
+ "resources": ["brandsideplatform.com", "forbes.com"]
+ },
+ "Foresee": {
+ "properties": ["foresee.com"],
+ "resources": ["answerscloud.com"]
+ },
+ "Fox One Stop Media": {
+ "properties": [
+ "fimserve.com",
+ "foxnetworks.com",
+ "foxonestop.com",
+ "mobsmith.com",
+ "myads.com",
+ "othersonline.com"
+ ],
+ "resources": [
+ "fimserve.com",
+ "foxnetworks.com",
+ "foxonestop.com",
+ "mobsmith.com",
+ "myads.com",
+ "othersonline.com"
+ ]
+ },
+ "FreakOut": {
+ "properties": ["fout.jp"],
+ "resources": ["fout.jp"]
+ },
+ "Freedom Communications": {
+ "properties": ["freedom.com"],
+ "resources": ["freedom.com"]
+ },
+ "Free Online Users": {
+ "properties": ["freeonlineusers.com"],
+ "resources": ["freeonlineusers.com"]
+ },
+ "Free-PageRank.com": {
+ "properties": ["free-pagerank.com"],
+ "resources": ["free-pagerank.com"]
+ },
+ "FreeWheel": {
+ "properties": ["freewheel.tv", "fwmrm.net"],
+ "resources": ["freewheel.tv", "fwmrm.net", "stickyadstv.com"]
+ },
+ "FriendFinder Networks": {
+ "properties": ["adultfriendfinder.com", "ffn.com", "pop6.com"],
+ "resources": ["adultfriendfinder.com", "ffn.com", "pop6.com"]
+ },
+ "Friends2Follow": {
+ "properties": ["friends2follow.com"],
+ "resources": ["friends2follow.com"]
+ },
+ "Frog Sex": {
+ "properties": ["double-check.com", "frogsex.com"],
+ "resources": ["double-check.com", "frogsex.com"]
+ },
+ "FuelX": {
+ "properties": ["fuelx.com"],
+ "resources": ["fuel451.com"]
+ },
+ "Fullstory": {
+ "properties": ["fullstory.com"],
+ "resources": ["fullstory.com"]
+ },
+ "Future Ads": {
+ "properties": ["futureads.com", "resultlinks.com"],
+ "resources": ["futureads.com", "resultlinks.com"]
+ },
+ "Fyber": {
+ "properties": ["fyber.com"],
+ "resources": ["fyber.com"]
+ },
+ "Game Advertising Online": {
+ "properties": ["game-advertising-online.com"],
+ "resources": ["game-advertising-online.com"]
+ },
+ "Games2win": {
+ "properties": ["games2win.com", "inviziads.com"],
+ "resources": ["games2win.com", "inviziads.com"]
+ },
+ "Gamned": {
+ "properties": ["gamned.com"],
+ "resources": ["gamned.com"]
+ },
+ "Gannett": {
+ "properties": ["gannett.com", "pointroll.com"],
+ "resources": ["gannett.com", "pointroll.com"]
+ },
+ "GB-World": {
+ "properties": ["gb-world.net"],
+ "resources": ["gb-world.net"]
+ },
+ "Gemius": {
+ "properties": ["gemius.com", "gemius.pl"],
+ "resources": ["gemius.com", "gemius.pl"]
+ },
+ "Genesis Media": {
+ "properties": ["genesismedia.com"],
+ "resources": ["genesismedia.com", "genesismediaus.com"]
+ },
+ "GENIEE": {
+ "properties": ["geniee.co.jp"],
+ "resources": ["geniee.co.jp", "gssprt.jp"]
+ },
+ "GENIE GROUP": {
+ "properties": ["geniegroupltd.co.uk", "www.geniegroupltd.co.uk"],
+ "resources": ["geniegroupltd.co.uk", "www.geniegroupltd.co.uk"]
+ },
+ "Genius.com": {
+ "properties": ["genius.com", "rsvpgenius.com"],
+ "resources": ["genius.com", "rsvpgenius.com"]
+ },
+ "GeoAds": {
+ "properties": ["geoads.com"],
+ "resources": ["geoads.com"]
+ },
+ "GetGlue": {
+ "properties": ["elfie.com", "smrtlnks.com"],
+ "resources": ["getglue.com", "smrtlnks.com"]
+ },
+ "GetIntent": {
+ "properties": ["adhigh.net", "getintent.com"],
+ "resources": ["adhigh.net", "getintent.com"]
+ },
+ "Get Satisfaction": {
+ "properties": ["getsatisfaction.com"],
+ "resources": ["getsatisfaction.com"]
+ },
+ "GetSiteControl": {
+ "properties": ["getsitecontrol.com"],
+ "resources": ["getsitecontrol.com"]
+ },
+ "GfK Group": {
+ "properties": ["gfk.com"],
+ "resources": ["daphnecm.com", "gfk.com", "gfkdaphne.com"]
+ },
+ "Gigya": {
+ "properties": ["gigya.com"],
+ "resources": ["gigcount.com", "gigya.com"]
+ },
+ "GISMAds": {
+ "properties": ["gismads.jp"],
+ "resources": ["gismads.jp"]
+ },
+ "GitHub": {
+ "properties": ["gaug.es", "github.com"],
+ "resources": ["gaug.es", "github.com"]
+ },
+ "Glam Media": {
+ "properties": ["glam.com", "glammedia.com"],
+ "resources": ["glam.com", "glammedia.com"]
+ },
+ "Gleam": {
+ "properties": ["gleam.io"],
+ "resources": ["fraudjs.io", "gleam.io"]
+ },
+ "Global Takeoff": {
+ "properties": ["globaltakeoff.com", "globaltakeoff.net"],
+ "resources": ["globaltakeoff.com", "globaltakeoff.net"]
+ },
+ "Globe7": {
+ "properties": ["globe7.com"],
+ "resources": ["globe7.com"]
+ },
+ "Go Daddy": {
+ "properties": ["godaddy.com", "trafficfacts.com"],
+ "resources": ["godaddy.com", "trafficfacts.com"]
+ },
+ "GoDataFeed": {
+ "properties": ["godatafeed.com"],
+ "resources": ["godatafeed.com"]
+ },
+ "GoGrid": {
+ "properties": ["datapipe.com", "formalyzer.com"],
+ "resources": ["datapipe.com", "formalyzer.com", "gogrid.com", "komli.net"]
+ },
+ "Goldbach": {
+ "properties": ["goldbachgroup.com"],
+ "resources": ["goldbach.com", "goldbachgroup.com"]
+ },
+ "GoldSpot Media": {
+ "properties": ["goldspotmedia.com"],
+ "resources": ["goldspotmedia.com"]
+ },
+ "Google": {
+ "properties": [
+ "abc.xyz",
+ "admeld.com",
+ "blogger.com",
+ "blogspot.com",
+ "crashlytics.com",
+ "google-melange.com",
+ "google.ac",
+ "google.ad",
+ "google.ae",
+ "google.al",
+ "google.am",
+ "google.as",
+ "google.at",
+ "google.az",
+ "google.ba",
+ "google.be",
+ "google.bf",
+ "google.bg",
+ "google.bi",
+ "google.bj",
+ "google.bs",
+ "google.bt",
+ "google.by",
+ "google.ca",
+ "google.cat",
+ "google.cd",
+ "google.cf",
+ "google.cg",
+ "google.ch",
+ "google.ci",
+ "google.cl",
+ "google.cm",
+ "google.cn",
+ "google.co.ao",
+ "google.co.bw",
+ "google.co.ck",
+ "google.co.cr",
+ "google.co.id",
+ "google.co.il",
+ "google.co.in",
+ "google.co.jp",
+ "google.co.ke",
+ "google.co.kr",
+ "google.co.ls",
+ "google.co.ma",
+ "google.co.mz",
+ "google.co.nz",
+ "google.co.th",
+ "google.co.tz",
+ "google.co.ug",
+ "google.co.uk",
+ "google.co.uz",
+ "google.co.ve",
+ "google.co.vi",
+ "google.co.za",
+ "google.co.zm",
+ "google.co.zw",
+ "google.com",
+ "google.com.af",
+ "google.com.ag",
+ "google.com.ai",
+ "google.com.ar",
+ "google.com.au",
+ "google.com.bd",
+ "google.com.bh",
+ "google.com.bn",
+ "google.com.bo",
+ "google.com.br",
+ "google.com.bz",
+ "google.com.co",
+ "google.com.cu",
+ "google.com.cy",
+ "google.com.do",
+ "google.com.ec",
+ "google.com.eg",
+ "google.com.et",
+ "google.com.fj",
+ "google.com.gh",
+ "google.com.gi",
+ "google.com.gt",
+ "google.com.hk",
+ "google.com.jm",
+ "google.com.kh",
+ "google.com.kw",
+ "google.com.lb",
+ "google.com.ly",
+ "google.com.mm",
+ "google.com.mt",
+ "google.com.mx",
+ "google.com.my",
+ "google.com.na",
+ "google.com.nf",
+ "google.com.ng",
+ "google.com.ni",
+ "google.com.np",
+ "google.com.om",
+ "google.com.pa",
+ "google.com.pe",
+ "google.com.pg",
+ "google.com.ph",
+ "google.com.pk",
+ "google.com.pr",
+ "google.com.py",
+ "google.com.qa",
+ "google.com.sa",
+ "google.com.sb",
+ "google.com.sg",
+ "google.com.sl",
+ "google.com.sv",
+ "google.com.tj",
+ "google.com.tr",
+ "google.com.tw",
+ "google.com.ua",
+ "google.com.uy",
+ "google.com.vc",
+ "google.com.vn",
+ "google.cv",
+ "google.cz",
+ "google.de",
+ "google.dj",
+ "google.dk",
+ "google.dm",
+ "google.dz",
+ "google.ee",
+ "google.es",
+ "google.fi",
+ "google.fm",
+ "google.fr",
+ "google.ga",
+ "google.ge",
+ "google.gg",
+ "google.gl",
+ "google.gm",
+ "google.gp",
+ "google.gr",
+ "google.gy",
+ "google.hn",
+ "google.hr",
+ "google.ht",
+ "google.hu",
+ "google.ie",
+ "google.im",
+ "google.iq",
+ "google.is",
+ "google.it",
+ "google.je",
+ "google.jo",
+ "google.kg",
+ "google.ki",
+ "google.kz",
+ "google.la",
+ "google.li",
+ "google.lk",
+ "google.lt",
+ "google.lu",
+ "google.lv",
+ "google.md",
+ "google.me",
+ "google.mg",
+ "google.mk",
+ "google.ml",
+ "google.mn",
+ "google.ms",
+ "google.mu",
+ "google.mv",
+ "google.mw",
+ "google.ne",
+ "google.nl",
+ "google.no",
+ "google.nr",
+ "google.nu",
+ "google.pl",
+ "google.pn",
+ "google.ps",
+ "google.pt",
+ "google.ro",
+ "google.rs",
+ "google.ru",
+ "google.rw",
+ "google.sc",
+ "google.se",
+ "google.sh",
+ "google.si",
+ "google.sk",
+ "google.sm",
+ "google.sn",
+ "google.so",
+ "google.st",
+ "google.td",
+ "google.tg",
+ "google.tk",
+ "google.tl",
+ "google.tm",
+ "google.tn",
+ "google.to",
+ "google.tt",
+ "google.vg",
+ "google.vu",
+ "google.ws",
+ "googlesource.com",
+ "ingress.com",
+ "nest.com",
+ "panoramio.com",
+ "pinpoint-dot-chromeperf.appspot.com",
+ "youtube.com"
+ ],
+ "resources": [
+ "2mdn.net",
+ "admeld.com",
+ "admob.com",
+ "apture.com",
+ "blogger.com",
+ "cc-dt.com",
+ "crashlytics.com",
+ "destinationurl.com",
+ "doubleclick.net",
+ "ggpht.com",
+ "gmail.com",
+ "gmodules.com",
+ "google-analytics.com",
+ "google.ac",
+ "google.ad",
+ "google.ae",
+ "google.al",
+ "google.am",
+ "google.as",
+ "google.at",
+ "google.az",
+ "google.ba",
+ "google.be",
+ "google.bf",
+ "google.bg",
+ "google.bi",
+ "google.bj",
+ "google.bs",
+ "google.bt",
+ "google.by",
+ "google.ca",
+ "google.cat",
+ "google.cc",
+ "google.cd",
+ "google.cf",
+ "google.cg",
+ "google.ch",
+ "google.ci",
+ "google.cl",
+ "google.cm",
+ "google.cn",
+ "google.co.ao",
+ "google.co.bw",
+ "google.co.ck",
+ "google.co.cr",
+ "google.co.id",
+ "google.co.il",
+ "google.co.in",
+ "google.co.jp",
+ "google.co.ke",
+ "google.co.kr",
+ "google.co.ls",
+ "google.co.ma",
+ "google.co.mz",
+ "google.co.nz",
+ "google.co.th",
+ "google.co.tz",
+ "google.co.ug",
+ "google.co.uk",
+ "google.co.uz",
+ "google.co.ve",
+ "google.co.vi",
+ "google.co.za",
+ "google.co.zm",
+ "google.co.zw",
+ "google.com",
+ "google.com.af",
+ "google.com.ag",
+ "google.com.ai",
+ "google.com.ar",
+ "google.com.au",
+ "google.com.bd",
+ "google.com.bh",
+ "google.com.bn",
+ "google.com.bo",
+ "google.com.br",
+ "google.com.bz",
+ "google.com.co",
+ "google.com.cu",
+ "google.com.cy",
+ "google.com.do",
+ "google.com.ec",
+ "google.com.eg",
+ "google.com.et",
+ "google.com.fj",
+ "google.com.gh",
+ "google.com.gi",
+ "google.com.gt",
+ "google.com.hk",
+ "google.com.jm",
+ "google.com.kh",
+ "google.com.kw",
+ "google.com.lb",
+ "google.com.lc",
+ "google.com.ly",
+ "google.com.mm",
+ "google.com.mt",
+ "google.com.mx",
+ "google.com.my",
+ "google.com.na",
+ "google.com.nf",
+ "google.com.ng",
+ "google.com.ni",
+ "google.com.np",
+ "google.com.om",
+ "google.com.pa",
+ "google.com.pe",
+ "google.com.pg",
+ "google.com.ph",
+ "google.com.pk",
+ "google.com.pr",
+ "google.com.py",
+ "google.com.qa",
+ "google.com.sa",
+ "google.com.sb",
+ "google.com.sg",
+ "google.com.sl",
+ "google.com.sv",
+ "google.com.tj",
+ "google.com.tn",
+ "google.com.tr",
+ "google.com.tw",
+ "google.com.ua",
+ "google.com.uy",
+ "google.com.vc",
+ "google.com.vn",
+ "google.cv",
+ "google.cz",
+ "google.de",
+ "google.dj",
+ "google.dk",
+ "google.dm",
+ "google.dz",
+ "google.ee",
+ "google.es",
+ "google.fi",
+ "google.fm",
+ "google.fr",
+ "google.ga",
+ "google.ge",
+ "google.gf",
+ "google.gg",
+ "google.gl",
+ "google.gm",
+ "google.gp",
+ "google.gr",
+ "google.gy",
+ "google.hn",
+ "google.hr",
+ "google.ht",
+ "google.hu",
+ "google.ie",
+ "google.im",
+ "google.io",
+ "google.iq",
+ "google.is",
+ "google.it",
+ "google.je",
+ "google.jo",
+ "google.kg",
+ "google.ki",
+ "google.kz",
+ "google.la",
+ "google.li",
+ "google.lk",
+ "google.lt",
+ "google.lu",
+ "google.lv",
+ "google.md",
+ "google.me",
+ "google.mg",
+ "google.mk",
+ "google.ml",
+ "google.mn",
+ "google.ms",
+ "google.mu",
+ "google.mv",
+ "google.mw",
+ "google.ne",
+ "google.nl",
+ "google.no",
+ "google.nr",
+ "google.nu",
+ "google.pl",
+ "google.pn",
+ "google.ps",
+ "google.pt",
+ "google.ro",
+ "google.rs",
+ "google.ru",
+ "google.rw",
+ "google.sc",
+ "google.se",
+ "google.sh",
+ "google.si",
+ "google.sk",
+ "google.sm",
+ "google.sn",
+ "google.so",
+ "google.st",
+ "google.td",
+ "google.tg",
+ "google.tk",
+ "google.tl",
+ "google.tm",
+ "google.tn",
+ "google.to",
+ "google.tt",
+ "google.vg",
+ "google.vu",
+ "google.ws",
+ "googleadservices.com",
+ "googleapis.com",
+ "googlemail.com",
+ "googlesyndication.com",
+ "googletagservices.com",
+ "googleusercontent.com",
+ "googlevideo.com",
+ "gstatic.com",
+ "invitemedia.com",
+ "postrank.com",
+ "recaptcha.net",
+ "smtad.net",
+ "youtube.com"
+ ]
+ },
+ "GoSquared": {
+ "properties": ["gosquared.com"],
+ "resources": ["gosquared.com"]
+ },
+ "GoStats": {
+ "properties": ["gostats.com"],
+ "resources": ["gostats.com"]
+ },
+ "Grapeshot": {
+ "properties": ["grapeshot.co.uk", "www.grapeshot.co.uk"],
+ "resources": ["grapeshot.co.uk", "www.grapeshot.co.uk"]
+ },
+ "GrapheneMedia": {
+ "properties": ["graphenemedia.in"],
+ "resources": ["graphenedigitalanalytics.in"]
+ },
+ "Graphnium": {
+ "properties": ["graphinium.com"],
+ "resources": ["crm4d.com"]
+ },
+ "Gravity": {
+ "properties": ["gravity.com", "grvcdn.com"],
+ "resources": ["gravity.com", "grvcdn.com"]
+ },
+ "Gridcash": {
+ "properties": ["adless.io", "gridcash.net"],
+ "resources": ["adless.io", "gridcash.net"]
+ },
+ "Grocery Shopping Network": {
+ "properties": ["groceryshopping.net"],
+ "resources": ["groceryshopping.net"]
+ },
+ "GroovinAds": {
+ "properties": ["groovinads.com"],
+ "resources": ["groovinads.com"]
+ },
+ "Gruner + Jahr": {
+ "properties": ["guj.de", "ligatus.com"],
+ "resources": ["guj.de", "ligatus.com"]
+ },
+ "GTop": {
+ "properties": ["arenaweb.ro"],
+ "resources": ["arenaweb.ro", "gtop.ro", "gtopstats.com"]
+ },
+ "GumGum": {
+ "properties": ["gumgum.com"],
+ "resources": ["gumgum.com"]
+ },
+ "Gunggo": {
+ "properties": ["gunggo.com"],
+ "resources": ["gunggo.com"]
+ },
+ "Hands Mobile": {
+ "properties": ["hands.com.br", "www.hands.com.br"],
+ "resources": ["hands.com.br", "www.hands.com.br"]
+ },
+ "Harrenmedia": {
+ "properties": ["harrenmedia.com", "harrenmedianetwork.com"],
+ "resources": ["harrenmedia.com", "harrenmedianetwork.com"]
+ },
+ "HealthPricer": {
+ "properties": ["adacado.com", "healthpricer.com"],
+ "resources": ["adacado.com", "healthpricer.com"]
+ },
+ "Hearst": {
+ "properties": [
+ "hearst.com",
+ "ic-live.com",
+ "iclive.com",
+ "icrossing.com",
+ "raasnet.com"
+ ],
+ "resources": [
+ "hearst.com",
+ "ic-live.com",
+ "iclive.com",
+ "icrossing.com",
+ "raasnet.com",
+ "redaril.com",
+ "sptag.com",
+ "sptag1.com",
+ "sptag2.com",
+ "sptag3.com"
+ ]
+ },
+ "Heyzap": {
+ "properties": ["heyzap.com"],
+ "resources": ["heyzap.com"]
+ },
+ "HilltopAds": {
+ "properties": ["hilltopads.com"],
+ "resources": ["hilltopads.com", "hilltopads.net", "shoporielder.pro"]
+ },
+ "Hi-media": {
+ "properties": ["himediagroup.com"],
+ "resources": ["comclick.com", "hi-media.com", "himediagroup.com"]
+ },
+ "Histats": {
+ "properties": ["histats.com"],
+ "resources": ["histats.com"]
+ },
+ "HitsLink": {
+ "properties": ["hitslink.com"],
+ "resources": ["hitslink.com"]
+ },
+ "Hit Sniffer": {
+ "properties": ["hitsniffer.com"],
+ "resources": ["hitsniffer.com"]
+ },
+ "Horyzon Media": {
+ "properties": ["horyzon-media.com"],
+ "resources": ["horyzon-media.com"]
+ },
+ "HotelChamp": {
+ "properties": ["hotelchamp.com"],
+ "resources": ["hotelchamp.com"]
+ },
+ "Hotjar": {
+ "properties": ["hotjar.com"],
+ "resources": ["hotjar.com"]
+ },
+ "HotMart": {
+ "properties": ["hotmart.com"],
+ "resources": ["hotmart.com"]
+ },
+ "HOTWords": {
+ "properties": ["hotwords.com", "hotwords.es"],
+ "resources": ["hotwords.com", "hotwords.es"]
+ },
+ "HP": {
+ "properties": ["hp.com", "opentext.com", "optimost.com"],
+ "resources": ["hp.com", "optimost.com"]
+ },
+ "Httpool": {
+ "properties": ["httpool.com"],
+ "resources": ["httpool.com"]
+ },
+ "HubSpot": {
+ "properties": ["hubspot.com"],
+ "resources": ["hs-analytics.net", "hubspot.com"]
+ },
+ "HUNT Mobile Ads": {
+ "properties": ["huntmads.com"],
+ "resources": ["huntmads.com"]
+ },
+ "Hurra.com": {
+ "properties": ["hurra.com"],
+ "resources": ["hurra.com"]
+ },
+ "IAB": {
+ "properties": ["digitru.st", "iabtechlab.com"],
+ "resources": ["digitru.st"]
+ },
+ "IAC": {
+ "properties": ["iac.com", "iacadvertising.com"],
+ "resources": ["iac.com", "iacadvertising.com"]
+ },
+ "iBehavior": {
+ "properties": ["i-behavior.com", "ib-ibi.com"],
+ "resources": ["i-behavior.com", "ib-ibi.com"]
+ },
+ "IBM": {
+ "properties": ["ibm.com", "multicloud-ibm.com"],
+ "resources": [
+ "cmcore.com",
+ "coremetrics.com",
+ "ibm.com",
+ "unica.com",
+ "xtify.com"
+ ]
+ },
+ "ID5": {
+ "properties": ["id5.io"],
+ "resources": ["id5-sync.com"]
+ },
+ "IDG": {
+ "properties": ["idg.com", "idgtechnetwork.com"],
+ "resources": ["idg.com", "idgtechnetwork.com"]
+ },
+ "iEntry": {
+ "properties": ["600z.com", "ientry.com"],
+ "resources": ["600z.com", "ientry.com"]
+ },
+ "IgnitAd": {
+ "properties": ["ignitad.com"],
+ "resources": ["ignitad.com"]
+ },
+ "IgnitionOne": {
+ "properties": ["ignitionone.com", "ignitionone.net", "searchignite.com"],
+ "resources": ["ignitionone.com", "ignitionone.net", "searchignite.com"]
+ },
+ "iMedia": {
+ "properties": ["imedia.cz"],
+ "resources": ["imedia.cz"]
+ },
+ "Improve Digital": {
+ "properties": ["360yield.com", "improvedigital.com"],
+ "resources": ["360yield.com", "improvedigital.com"]
+ },
+ "Inadco": {
+ "properties": ["inadco.com"],
+ "resources": ["anadcoads.com", "inadco.com", "inadcoads.com"]
+ },
+ "InboundWriter": {
+ "properties": ["enquisite.com", "inboundwriter.com"],
+ "resources": ["enquisite.com", "inboundwriter.com"]
+ },
+ "IndexExchange": {
+ "properties": ["indexexchange.com"],
+ "resources": ["indexexchange.com"]
+ },
+ "Infectious Media": {
+ "properties": ["infectiousmedia.com"],
+ "resources": ["impressiondesk.com", "infectiousmedia.com"]
+ },
+ "Infernotions": {
+ "properties": ["infernotions.com"],
+ "resources": ["infernotions.com"]
+ },
+ "Inflection Point Media": {
+ "properties": ["inflectionpointmedia.com"],
+ "resources": ["inflectionpointmedia.com"]
+ },
+ "Infogroup": {
+ "properties": ["infogroup.com"],
+ "resources": ["infogroup.com"]
+ },
+ "Infolinks": {
+ "properties": ["infolinks.com"],
+ "resources": ["infolinks.com"]
+ },
+ "INFOnline": {
+ "properties": ["infonline.de"],
+ "resources": ["infonline.de", "ioam.de", "ivwbox.de"]
+ },
+ "InfoStars": {
+ "properties": ["hotlog.ru", "infostars.ru"],
+ "resources": ["hotlog.ru", "infostars.ru"]
+ },
+ "Infra-Ad": {
+ "properties": ["infra-ad.com"],
+ "resources": ["infra-ad.com"]
+ },
+ "InMobi": {
+ "properties": ["aerserv.com", "inmobi.com", "sproutinc.com"],
+ "resources": ["aerserv.com", "inmobi.com", "sproutinc.com"]
+ },
+ "inneractive": {
+ "properties": ["inner-active.com"],
+ "resources": ["inner-active.com"]
+ },
+ "Innity": {
+ "properties": ["innity.com"],
+ "resources": ["innity.com"]
+ },
+ "InsightExpress": {
+ "properties": ["insightexpress.com"],
+ "resources": ["insightexpress.com", "insightexpressai.com"]
+ },
+ "InSkin Media": {
+ "properties": ["inskinmedia.com"],
+ "resources": ["inskinmedia.com"]
+ },
+ "Inspectlet": {
+ "properties": ["inspectlet.com"],
+ "resources": ["inspectlet.com"]
+ },
+ "Instinctive": {
+ "properties": ["instinctive.io"],
+ "resources": ["instinctive.io", "instinctiveads.com"]
+ },
+ "Integral Ad Science": {
+ "properties": ["integralads.com"],
+ "resources": [
+ "adsafemedia.com",
+ "adsafeprotected.com",
+ "iasds01.com",
+ "integralads.com"
+ ]
+ },
+ "IntelligenceFocus": {
+ "properties": ["intelligencefocus.com", "leadchampion.com"],
+ "resources": ["domodomain.com", "intelligencefocus.com", "leadchampion.com"]
+ },
+ "Intent Media": {
+ "properties": ["intentmedia.com"],
+ "resources": ["intentmedia.com", "intentmedia.net"]
+ },
+ "Intergi": {
+ "properties": ["intergi.com"],
+ "resources": ["intergi.com"]
+ },
+ "Intermarkets": {
+ "properties": ["intermarkets.net"],
+ "resources": ["intermarkets.net"]
+ },
+ "Intermundo Media": {
+ "properties": ["intermundomedia.com"],
+ "resources": ["intermundomedia.com"]
+ },
+ "Internet Brands": {
+ "properties": ["ibpxl.com", "internetbrands.com"],
+ "resources": ["ibpxl.com", "internetbrands.com"]
+ },
+ "Interpolls": {
+ "properties": ["interpolls.com"],
+ "resources": ["interpolls.com"]
+ },
+ "Inuvo": {
+ "properties": ["inuvo.com"],
+ "resources": ["inuvo.com"]
+ },
+ "InvestingChannel": {
+ "properties": ["investingchannel.com"],
+ "resources": ["investingchannel.com"]
+ },
+ "iovation": {
+ "properties": ["iovation.com"],
+ "resources": ["iesnare.com", "iovation.com"]
+ },
+ "iPerceptions": {
+ "properties": ["iperceptions.com"],
+ "resources": ["iperceptions.com"]
+ },
+ "IponWeb": {
+ "properties": ["iponweb.com"],
+ "resources": ["iponweb.com", "iponweb.net"]
+ },
+ "iPROM": {
+ "properties": [
+ "centraliprom.com",
+ "iprom.net",
+ "iprom.si",
+ "mediaiprom.com"
+ ],
+ "resources": ["centraliprom.com", "iprom.net", "iprom.si", "mediaiprom.com"]
+ },
+ "iPromote": {
+ "properties": ["ipromote.com"],
+ "resources": ["ipromote.com"]
+ },
+ "iProspect": {
+ "properties": ["iprospect.com"],
+ "resources": ["clickmanage.com", "iprospect.com"]
+ },
+ "ISI Technologies": {
+ "properties": ["adversalservers.com", "digbro.com"],
+ "resources": ["adversalservers.com", "digbro.com"]
+ },
+ "IslayTech": {
+ "properties": ["islay.tech"],
+ "resources": ["islay.tech"]
+ },
+ "ismatlab.com": {
+ "properties": ["ismatlab.com"],
+ "resources": ["ismatlab.com"]
+ },
+ "Itch": {
+ "properties": ["itch.io"],
+ "resources": ["itch.io"]
+ },
+ "ItIsATracker": {
+ "properties": ["itisatracker.com"],
+ "resources": ["itisatracker.com"]
+ },
+ "I.UA": {
+ "properties": ["i.ua"],
+ "resources": ["i.ua"]
+ },
+ "Jaroop": {
+ "properties": ["jaroop.com"],
+ "resources": ["jaroop.com"]
+ },
+ "JasperLabs": {
+ "properties": ["jasperlabs.com"],
+ "resources": ["jasperlabs.com"]
+ },
+ "Jemm": {
+ "properties": ["jemmgroup.com"],
+ "resources": ["jemmgroup.com"]
+ },
+ "Jink": {
+ "properties": ["jink.de", "jinkads.com"],
+ "resources": ["jink.de", "jinkads.com"]
+ },
+ "Jirbo": {
+ "properties": ["adcolony.com"],
+ "resources": ["adcolony.com", "jirbo.com"]
+ },
+ "Jivox": {
+ "properties": ["jivox.com"],
+ "resources": ["jivox.com"]
+ },
+ "JobThread": {
+ "properties": ["jobthread.com"],
+ "resources": ["jobthread.com"]
+ },
+ "JSE": {
+ "properties": ["jsecoin.com"],
+ "resources": [
+ "freecontent.bid",
+ "freecontent.date",
+ "freecontent.stream",
+ "hashing.win",
+ "hostingcloud.racing",
+ "hostingcloud.science",
+ "jsecoin.com"
+ ]
+ },
+ "JuicyAds": {
+ "properties": ["juicyads.com"],
+ "resources": ["juicyads.com"]
+ },
+ "Jumptap": {
+ "properties": ["jumptap.com"],
+ "resources": ["jumptap.com"]
+ },
+ "justuno": {
+ "properties": ["justuno.com"],
+ "resources": ["justuno.com"]
+ },
+ "Kaltura": {
+ "properties": ["kaltura.com"],
+ "resources": ["kaltura.com"]
+ },
+ "Kargo": {
+ "properties": ["kargo.com"],
+ "resources": ["kargo.com"]
+ },
+ "Kenshoo": {
+ "properties": ["kenshoo.com", "xg4ken.com"],
+ "resources": ["kenshoo.com", "xg4ken.com"]
+ },
+ "Keyade": {
+ "properties": ["keyade.com"],
+ "resources": ["keyade.com"]
+ },
+ "KeyMetric": {
+ "properties": ["keymetric.net"],
+ "resources": ["keymetric.net"]
+ },
+ "Keywee": {
+ "properties": ["keywee.co"],
+ "resources": ["keywee.co"]
+ },
+ "kikin": {
+ "properties": ["kikin.com"],
+ "resources": ["kikin.com"]
+ },
+ "KISSmetrics": {
+ "properties": ["kissmetrics.com"],
+ "resources": ["kissmetrics.com"]
+ },
+ "KissMyAds": {
+ "properties": ["kissmyads.com"],
+ "resources": ["kissmyads.com"]
+ },
+ "Kitara Media": {
+ "properties": ["103092804.com", "kitaramedia.com"],
+ "resources": ["103092804.com", "kitaramedia.com"]
+ },
+ "Kitcode": {
+ "properties": ["kitcode.net"],
+ "resources": ["kitcode.net"]
+ },
+ "KIT digital": {
+ "properties": ["kitd.com"],
+ "resources": ["keewurd.com", "kitd.com", "peerset.com"]
+ },
+ "Kokteyl": {
+ "properties": ["admost.com", "kokteyl.com"],
+ "resources": ["admost.com", "kokteyl.com"]
+ },
+ "Komli": {
+ "properties": ["komli.com"],
+ "resources": ["komli.com"]
+ },
+ "Konduto": {
+ "properties": ["konduto.com"],
+ "resources": ["k-analytix.com", "konduto.com"]
+ },
+ "Kontera": {
+ "properties": ["kontera.com"],
+ "resources": ["kontera.com"]
+ },
+ "Korrelate": {
+ "properties": ["korrelate.com"],
+ "resources": ["adsummos.com", "adsummos.net", "korrelate.com"]
+ },
+ "Krux": {
+ "properties": ["krux.com", "kruxdigital.com"],
+ "resources": ["krux.com", "kruxdigital.com", "krxd.net"]
+ },
+ "Lakana": {
+ "properties": ["lakana.com"],
+ "resources": ["ibsys.com", "lakana.com"]
+ },
+ "Layer-Ad.org": {
+ "properties": ["layer-ad.org"],
+ "resources": ["layer-ad.org"]
+ },
+ "Layer Ads": {
+ "properties": ["layer-ads.net"],
+ "resources": ["layer-ads.net"]
+ },
+ "LeadBolt": {
+ "properties": ["leadbolt.com"],
+ "resources": ["leadbolt.com"]
+ },
+ "LeadForensics": {
+ "properties": ["leadforensics.com"],
+ "resources": ["leadforensics.com"]
+ },
+ "LeadFormix": {
+ "properties": ["calliduscloud.com", "leadforce1.com", "leadformix.com"],
+ "resources": ["calliduscloud.com", "leadforce1.com", "leadformix.com"]
+ },
+ "LeadsHub": {
+ "properties": ["ztsrv.com"],
+ "resources": ["ztsrv.com"]
+ },
+ "LeanPlum": {
+ "properties": ["leanplum.com"],
+ "resources": ["leanplum.com"]
+ },
+ "Legolas Media": {
+ "properties": ["legolas-media.com"],
+ "resources": ["legolas-media.com"]
+ },
+ "Levexis": {
+ "properties": ["levexis.com"],
+ "resources": ["levexis.com"]
+ },
+ "Lexos Media": {
+ "properties": ["adbull.com", "lexosmedia.com"],
+ "resources": ["adbull.com", "lexosmedia.com"]
+ },
+ "LifeStreet": {
+ "properties": ["lfstmedia.com", "lifestreetmedia.com"],
+ "resources": ["lfstmedia.com", "lifestreetmedia.com"]
+ },
+ "Limelight Networks": {
+ "properties": ["limelight.com"],
+ "resources": ["clickability.com", "limelight.com", "llnwd.net"]
+ },
+ "LineZing": {
+ "properties": ["linezing.com"],
+ "resources": ["linezing.com"]
+ },
+ "LinkConnector": {
+ "properties": ["linkconnector.com"],
+ "resources": ["linkconnector.com"]
+ },
+ "LinkedIn": {
+ "properties": ["linkedin.com"],
+ "resources": ["licdn.com", "linkedin.com"]
+ },
+ "LinkShare": {
+ "properties": ["rakutenmarketing.com"],
+ "resources": ["linkshare.com", "linksynergy.com", "rakutenmarketing.com"]
+ },
+ "Linkz": {
+ "properties": ["linkz.net"],
+ "resources": ["linkz.net"]
+ },
+ "Listrak": {
+ "properties": ["listrak.com", "listrakbi.com"],
+ "resources": ["listrak.com", "listrakbi.com"]
+ },
+ "LiveIntent": {
+ "properties": ["liveintent.com"],
+ "resources": ["liadm.com", "liveintent.com"]
+ },
+ "LiveInternet": {
+ "properties": ["liveinternet.ru", "yadro.ru"],
+ "resources": ["liveinternet.ru", "yadro.ru"]
+ },
+ "LivePerson": {
+ "properties": ["liveperson.com"],
+ "resources": ["liveperson.com", "liveperson.net", "nuconomy.com"]
+ },
+ "LiveRail": {
+ "properties": ["liverail.com"],
+ "resources": ["liverail.com"]
+ },
+ "LiveRamp": {
+ "properties": ["liveramp.com"],
+ "resources": ["liveramp.com", "tvpixel.com"]
+ },
+ "LKQD": {
+ "properties": ["lkqd.com", "lkqd.net"],
+ "resources": ["lkqd.com", "lkqd.net"]
+ },
+ "Local Yokel Media": {
+ "properties": ["localyokelmedia.com"],
+ "resources": ["localyokelmedia.com"]
+ },
+ "Localytics": {
+ "properties": ["localytics.com"],
+ "resources": ["localytics.com"]
+ },
+ "LockerDome": {
+ "properties": ["lockerdome.com"],
+ "resources": ["lockerdome.com"]
+ },
+ "Lockerz": {
+ "properties": ["lockerz.com"],
+ "resources": ["lockerz.com"]
+ },
+ "Logdy": {
+ "properties": ["logdy.com"],
+ "resources": ["logdy.com"]
+ },
+ "Longboard Media": {
+ "properties": ["longboardmedia.com"],
+ "resources": ["longboardmedia.com"]
+ },
+ "LongTail Video": {
+ "properties": ["jwplayer.com"],
+ "resources": ["longtailvideo.com", "ltassrv.com"]
+ },
+ "Loomia": {
+ "properties": ["loomia.com"],
+ "resources": ["loomia.com"]
+ },
+ "LoopFuse": {
+ "properties": ["lfov.net", "loopfuse.net"],
+ "resources": ["lfov.net", "loopfuse.net"]
+ },
+ "LoopMe": {
+ "properties": ["loopme.com"],
+ "resources": ["loopme.com"]
+ },
+ "Lotame": {
+ "properties": ["crwdcntrl.net", "lotame.com"],
+ "resources": ["crwdcntrl.net", "lotame.com"]
+ },
+ "LotLinx": {
+ "properties": ["lotlinx.com"],
+ "resources": ["lotlinx.com"]
+ },
+ "Lower My Bills": {
+ "properties": ["lowermybills.com"],
+ "resources": ["lowermybills.com"]
+ },
+ "lptracker": {
+ "properties": ["lptracker.io"],
+ "resources": ["lptracker.io"]
+ },
+ "LucidMedia": {
+ "properties": ["lucidmedia.com"],
+ "resources": ["lucidmedia.com"]
+ },
+ "LuckyOrange": {
+ "properties": ["luckyorange.com"],
+ "resources": ["luckyorange.com", "luckyorange.net"]
+ },
+ "Lynchpin": {
+ "properties": ["lynchpin.com"],
+ "resources": ["lynchpin.com", "lypn.com"]
+ },
+ "Lyris": {
+ "properties": ["aurea.com"],
+ "resources": ["aurea.com", "clicktracks.com", "lyris.com"]
+ },
+ "Lytiks": {
+ "properties": ["lytiks.com"],
+ "resources": ["lytiks.com"]
+ },
+ "m6d": {
+ "properties": ["dstillery.com"],
+ "resources": ["dstillery.com", "m6d.com", "media6degrees.com"]
+ },
+ "Madhouse": {
+ "properties": ["madhouse.cn"],
+ "resources": ["madhouse.cn"]
+ },
+ "Madison Logic": {
+ "properties": ["dinclinx.com", "madisonlogic.com"],
+ "resources": ["dinclinx.com", "madisonlogic.com"]
+ },
+ "madvertise": {
+ "properties": ["madvertise.com"],
+ "resources": ["madvertise.com"]
+ },
+ "Magnetic": {
+ "properties": ["domdex.net", "magnetic.com"],
+ "resources": ["domdex.com", "domdex.net", "magnetic.com", "qjex.net"]
+ },
+ "Magnify360": {
+ "properties": ["dialogmgr.com", "magnify360.com"],
+ "resources": ["dialogmgr.com", "magnify360.com"]
+ },
+ "MailChimp": {
+ "properties": ["campaign-archive1.com", "mailchi.mp", "mailchimp.com"],
+ "resources": [
+ "campaign-archive1.com",
+ "list-manage.com",
+ "mailchi.mp",
+ "mailchimp.com"
+ ]
+ },
+ "Mail.Ru": {
+ "properties": ["list.ru", "mail.ru"],
+ "resources": ["list.ru", "mail.ru"]
+ },
+ "Manifest": {
+ "properties": ["bannerbank.ru", "manifest.ru"],
+ "resources": ["bannerbank.ru", "manifest.ru"]
+ },
+ "Marchex": {
+ "properties": ["industrybrains.com", "marchex.com"],
+ "resources": ["industrybrains.com", "marchex.com"]
+ },
+ "Marimedia": {
+ "properties": ["marimedia.net"],
+ "resources": ["marimedia.net"]
+ },
+ "MarketGid": {
+ "properties": ["dt00.net", "dt07.net", "marketgid.com"],
+ "resources": ["dt00.net", "dt07.net", "marketgid.com"]
+ },
+ "Marketo": {
+ "properties": ["marketo.com"],
+ "resources": ["marketo.com", "marketo.net"]
+ },
+ "Markit": {
+ "properties": ["markit.com", "wsod.com"],
+ "resources": ["markit.com", "wsod.com"]
+ },
+ "MarkMonitor": {
+ "properties": ["9c9media.ca", "markmonitor.com"],
+ "resources": ["9c9media.ca", "markmonitor.com"]
+ },
+ "Marktest": {
+ "properties": ["marktest.com", "marktest.pt"],
+ "resources": ["marktest.com", "marktest.pt"]
+ },
+ "Martini Media": {
+ "properties": ["martiniadnetwork.com"],
+ "resources": ["martiniadnetwork.com", "martinimedianetwork.com"]
+ },
+ "mashero": {
+ "properties": ["mashero.com"],
+ "resources": ["mashero.com"]
+ },
+ "MashLogic": {
+ "properties": ["mashlogic.com"],
+ "resources": ["mashlogic.com"]
+ },
+ "Match.com": {
+ "properties": ["chemistry.com", "match.com"],
+ "resources": ["chemistry.com", "match.com", "meetic-partners.com"]
+ },
+ "Matomy": {
+ "properties": ["matomy.com"],
+ "resources": [
+ "adnetinteractive.com",
+ "adsmarket.com",
+ "matomy.com",
+ "matomymarket.com",
+ "matomymedia.com",
+ "mediawhiz.com",
+ "optimatic.com",
+ "xtendmedia.com"
+ ]
+ },
+ "MaxBounty": {
+ "properties": ["maxbounty.com", "mb01.com"],
+ "resources": ["maxbounty.com", "mb01.com"]
+ },
+ "MaxMind": {
+ "properties": ["maxmind.com"],
+ "resources": ["maxmind.com", "mmapiws.com"]
+ },
+ "MaxPoint": {
+ "properties": ["maxpointinteractive.com", "maxusglobal.com", "mxptint.net"],
+ "resources": ["maxpointinteractive.com", "maxusglobal.com", "mxptint.net"]
+ },
+ "McAfee": {
+ "properties": ["mcafee.com", "mcafeesecure.com"],
+ "resources": ["mcafee.com", "mcafeesecure.com", "scanalert.com"]
+ },
+ "MdotM": {
+ "properties": ["mdotm.com"],
+ "resources": ["mdotm.com"]
+ },
+ "MediaBrix": {
+ "properties": ["mediabrix.com"],
+ "resources": ["mediabrix.com"]
+ },
+ "MediaCom": {
+ "properties": ["mediacom.com"],
+ "resources": ["mediacom.com"]
+ },
+ "mediaFORGE": {
+ "properties": ["mediaforge.com"],
+ "resources": ["mediaforge.com"]
+ },
+ "Medialets": {
+ "properties": ["medialets.com"],
+ "resources": ["medialets.com"]
+ },
+ "MediaMath": {
+ "properties": ["mediamath.com"],
+ "resources": [
+ "adroitinteractive.com",
+ "designbloxlive.com",
+ "mathtag.com",
+ "mediamath.com"
+ ]
+ },
+ "Médiamétrie-eStat": {
+ "properties": ["mediametrie-estat.com"],
+ "resources": ["estat.com", "mediametrie-estat.com"]
+ },
+ "media.net": {
+ "properties": ["media.net"],
+ "resources": ["media.net"]
+ },
+ "Mediaocean": {
+ "properties": ["adbuyer.com", "mediaocean.com"],
+ "resources": ["adbuyer.com", "mediaocean.com"]
+ },
+ "MediaShakers": {
+ "properties": ["media-servers.net", "mediashakers.com"],
+ "resources": ["media-servers.net", "mediashakers.com"]
+ },
+ "MediaTrust": {
+ "properties": ["mediatrust.com"],
+ "resources": ["mediatrust.com"]
+ },
+ "Medicx Media Solutions": {
+ "properties": ["medicxmedia.com"],
+ "resources": ["medicxmedia.com"]
+ },
+ "Meebo": {
+ "properties": ["meebo.com"],
+ "resources": ["meebo.com", "meebocdn.net"]
+ },
+ "MegaIndex": {
+ "properties": ["megaindex.ru"],
+ "resources": ["megaindex.ru"]
+ },
+ "Mercadopago": {
+ "properties": [
+ "mercadolibre.cl",
+ "mercadolibre.co.cr",
+ "mercadolibre.com",
+ "mercadolibre.com.ar",
+ "mercadolibre.com.bo",
+ "mercadolibre.com.co",
+ "mercadolibre.com.do",
+ "mercadolibre.com.ec",
+ "mercadolibre.com.gt",
+ "mercadolibre.com.hn",
+ "mercadolibre.com.mx",
+ "mercadolibre.com.ni",
+ "mercadolibre.com.pa",
+ "mercadolibre.com.pe",
+ "mercadolibre.com.py",
+ "mercadolibre.com.sv",
+ "mercadolibre.com.uy",
+ "mercadolibre.com.ve",
+ "mercadolivre.com.br",
+ "mercadopago.com"
+ ],
+ "resources": ["mercadopago.com"]
+ },
+ "Mercent": {
+ "properties": ["mercent.com"],
+ "resources": ["mercent.com"]
+ },
+ "MerchantAdvantage": {
+ "properties": ["merchantadvantage.com"],
+ "resources": ["merchantadvantage.com"]
+ },
+ "Merchenta": {
+ "properties": ["merchenta.com"],
+ "resources": ["merchenta.com"]
+ },
+ "Merkle": {
+ "properties": ["merkleinc.com", "rkdms.com"],
+ "resources": ["merkleinc.com", "rimmkaufman.com", "rkdms.com"]
+ },
+ "Meta Network": {
+ "properties": ["metanetwork.com"],
+ "resources": ["metanetwork.com"]
+ },
+ "Meteor": {
+ "properties": ["meteorsolutions.com"],
+ "resources": ["meteorsolutions.com"]
+ },
+ "MetrixLab": {
+ "properties": [
+ "crm-metrix.com",
+ "customerconversio.com",
+ "metrixlab.com",
+ "opinionbar.com"
+ ],
+ "resources": [
+ "adoftheyear.com",
+ "crm-metrix.com",
+ "customerconversio.com",
+ "metrixlab.com",
+ "opinionbar.com"
+ ]
+ },
+ "MicroAd": {
+ "properties": ["microad.jp", "www.microad.jp"],
+ "resources": ["microad.jp", "www.microad.jp"]
+ },
+ "Microsoft": {
+ "properties": [
+ "acompli.net",
+ "aka.ms",
+ "azure.com",
+ "azure.net",
+ "azurerms.com",
+ "bing.com",
+ "cloudappsecurity.com",
+ "gamesforwindows.com",
+ "getgamesmart.com",
+ "gfx.ms",
+ "healthvault.com",
+ "hockeyapp.net",
+ "ieaddons.com",
+ "iegallery.com",
+ "live.com",
+ "microsoft.com",
+ "microsoftalumni.com",
+ "microsoftalumni.org",
+ "microsoftazuread-sso.com",
+ "microsoftedgeinsiders.com",
+ "microsoftonline-p.com",
+ "microsoftonline-p.net",
+ "microsoftonline.com",
+ "microsoftstore.com",
+ "microsoftstream.com",
+ "msappproxy.net",
+ "msft.net",
+ "msftidentity.com",
+ "msidentity.com",
+ "msn.com",
+ "o365weve.com",
+ "oaspapps.com",
+ "office.com",
+ "office365.com",
+ "officelive.com",
+ "onedrive.com",
+ "onenote.com",
+ "outlook.com",
+ "outlookmobile.com",
+ "phonefactor.net",
+ "s-msn.com",
+ "sfx.ms",
+ "sharepoint.com",
+ "skype.com",
+ "skypeforbusiness.com",
+ "staffhub.ms",
+ "sway-extensions.com",
+ "sway.com",
+ "trafficmanager.net",
+ "virtualearth.net",
+ "visualstudio.com",
+ "windows.net",
+ "windowsazure.com",
+ "windowsphone.com",
+ "worldwidetelescope.org",
+ "wunderlist.com",
+ "xbox.com",
+ "yammer.com"
+ ],
+ "resources": [
+ "aadrm.com",
+ "adbureau.net",
+ "adecn.com",
+ "aquantive.com",
+ "aspnetcdn.com",
+ "assets-yammer.com",
+ "azure.com",
+ "azureedge.net",
+ "bing.com",
+ "cloudapp.net",
+ "gamesforwindows.com",
+ "getgamesmart.com",
+ "gfx.ms",
+ "healthvault.com",
+ "live.com",
+ "microsoft.com",
+ "microsoftazuread-sso.com",
+ "microsoftonline-p.com",
+ "microsoftonline-p.net",
+ "microsoftonline.com",
+ "microsoftstore.com",
+ "msads.net",
+ "msauthimages.net",
+ "msecnd.net",
+ "msedge.net",
+ "msndirect.com",
+ "msocdn.com",
+ "netconversions.com",
+ "oaspapps.com",
+ "office.com",
+ "office.net",
+ "officelive.com",
+ "onenote.net",
+ "onestore.ms",
+ "onmicrosoft.com",
+ "outlook.com",
+ "roiservice.com",
+ "s-msn.com",
+ "sfbassets.com",
+ "sharepoint.com",
+ "skype.com",
+ "skypeassets.com",
+ "sway-cdn.com",
+ "sway-extensions.com",
+ "windows.net",
+ "windowsazure.com",
+ "yammerusercontent.com"
+ ]
+ },
+ "Millennial Media": {
+ "properties": ["decktrade.com", "millennialmedia.com", "mydas.mobi"],
+ "resources": ["decktrade.com", "millennialmedia.com", "mydas.mobi"]
+ },
+ "Mindset Media": {
+ "properties": ["mindset-media.com"],
+ "resources": ["mindset-media.com", "mmismm.com"]
+ },
+ "MinerAlt": {
+ "properties": ["mineralt.io", "vidzi.nu", "vidzi.tv"],
+ "resources": [
+ "1q2w3.website",
+ "analytics.blue",
+ "aster18cdn.nl",
+ "belicimo.pw",
+ "besstahete.info",
+ "dinorslick.icu",
+ "feesocrald.com",
+ "gramombird.com",
+ "istlandoll.com",
+ "mepirtedic.com",
+ "mineralt.io",
+ "pampopholf.com",
+ "tercabilis.info",
+ "tulip18.com",
+ "vidzi.tv",
+ "yololike.space"
+ ]
+ },
+ "Minescripts": {
+ "properties": ["minescripts.info"],
+ "resources": ["minescripts.info", "sslverify.info"]
+ },
+ "MineXMR": {
+ "properties": ["minexmr.stream"],
+ "resources": ["minexmr.stream"]
+ },
+ "Mirando": {
+ "properties": ["mirando.de"],
+ "resources": ["mirando.de"]
+ },
+ "Mixpanel": {
+ "properties": ["mixpanel.com"],
+ "resources": ["mixpanel.com", "mxpnl.com"]
+ },
+ "Mixpo": {
+ "properties": ["mixpo.com"],
+ "resources": ["mixpo.com"]
+ },
+ "Moat": {
+ "properties": ["moat.com", "moatads.com"],
+ "resources": ["moat.com", "moatads.com"]
+ },
+ "MobFox": {
+ "properties": ["mobfox.com"],
+ "resources": ["mobfox.com"]
+ },
+ "Mobials": {
+ "properties": ["mobials.com"],
+ "resources": ["mobials.com"]
+ },
+ "MobileAdTrading": {
+ "properties": ["mobileadtrading.com"],
+ "resources": ["mobileadtrading.com"]
+ },
+ "Mobile Meteor": {
+ "properties": ["mobilemeteor.com"],
+ "resources": ["mobilemeteor.com", "showmeinn.com"]
+ },
+ "Mobile Storm": {
+ "properties": ["mobilestorm.com"],
+ "resources": ["mobilestorm.com"]
+ },
+ "MobVision": {
+ "properties": ["admoda.com"],
+ "resources": ["admoda.com", "mobvision.com"]
+ },
+ "Mocean Mobile": {
+ "properties": ["moceanmobile.com"],
+ "resources": ["moceanmobile.com"]
+ },
+ "Mochila": {
+ "properties": ["mochila.com"],
+ "resources": ["mochila.com"]
+ },
+ "Mojiva": {
+ "properties": ["mojiva.com"],
+ "resources": ["mojiva.com"]
+ },
+ "Monetate": {
+ "properties": ["monetate.com", "monetate.net"],
+ "resources": ["monetate.com", "monetate.net"]
+ },
+ "MONETIZEdigital": {
+ "properties": ["cpalead.com"],
+ "resources": ["cpalead.com"]
+ },
+ "Monetize More": {
+ "properties": ["monetizemore.com"],
+ "resources": ["monetizemore.com"]
+ },
+ "Mongoose Metrics": {
+ "properties": ["mongoosemetrics.com"],
+ "resources": ["mongoosemetrics.com"]
+ },
+ "Monitus": {
+ "properties": ["monitus.net"],
+ "resources": ["monitus.net"]
+ },
+ "Monoloop": {
+ "properties": ["monoloop.com"],
+ "resources": ["monoloop.com"]
+ },
+ "Monster": {
+ "properties": ["monster.com"],
+ "resources": ["monster.com"]
+ },
+ "Moolah Media": {
+ "properties": ["moolah-media.com", "moolahmedia.com"],
+ "resources": ["moolah-media.com", "moolahmedia.com"]
+ },
+ "MoPub": {
+ "properties": ["mopub.com"],
+ "resources": ["mopub.com"]
+ },
+ "motigo": {
+ "properties": ["motigo.com"],
+ "resources": ["motigo.com", "nedstatbasic.net"]
+ },
+ "Mouseflow": {
+ "properties": ["mouseflow.com"],
+ "resources": ["mouseflow.com"]
+ },
+ "MovieLush.com": {
+ "properties": ["affbuzzads.com", "movielush.com"],
+ "resources": ["affbuzzads.com", "movielush.com"]
+ },
+ "Multiple Stream Media": {
+ "properties": ["adclickmedia.com", "multiplestreammktg.com"],
+ "resources": ["adclickmedia.com", "multiplestreammktg.com"]
+ },
+ "MUNDO Media": {
+ "properties": ["mundomedia.com", "silver-path.com"],
+ "resources": ["mundomedia.com", "silver-path.com"]
+ },
+ "MyCounter": {
+ "properties": ["mycounter.com.ua"],
+ "resources": ["mycounter.com.ua"]
+ },
+ "MyPagerank.Net": {
+ "properties": ["mypagerank.net"],
+ "resources": ["mypagerank.net"]
+ },
+ "MyPressPlus": {
+ "properties": ["mypressplus.com", "ppjol.net"],
+ "resources": ["mypressplus.com", "ppjol.net"]
+ },
+ "Mystighty": {
+ "properties": ["mystighty.info"],
+ "resources": ["mystighty.info", "sweeterge.info"]
+ },
+ "myThings": {
+ "properties": ["mythings.com", "mythingsmedia.com"],
+ "resources": ["mythings.com", "mythingsmedia.com"]
+ },
+ "MyWebGrocer": {
+ "properties": ["mywebgrocer.com"],
+ "resources": ["mywebgrocer.com"]
+ },
+ "Nanigans": {
+ "properties": ["nanigans.com"],
+ "resources": ["nanigans.com"]
+ },
+ "Narrative": {
+ "properties": ["narrative.io"],
+ "resources": ["narrative.io"]
+ },
+ "NativeAds": {
+ "properties": ["nativeads.com"],
+ "resources": ["nativeads.com"]
+ },
+ "Nativo": {
+ "properties": ["nativo.com", "postrelease.com"],
+ "resources": ["nativo.com", "postrelease.com"]
+ },
+ "Navegg": {
+ "properties": ["navdmp.com", "navegg.com"],
+ "resources": ["navdmp.com", "navegg.com"]
+ },
+ "NDN": {
+ "properties": ["newsinc.com"],
+ "resources": ["newsinc.com"]
+ },
+ "Negishim": {
+ "properties": ["negishim.org"],
+ "resources": ["negishim.org"]
+ },
+ "NeroHut": {
+ "properties": ["nerohut.com"],
+ "resources": ["nerohut.com", "nhsrv.cf"]
+ },
+ "NetAffiliation": {
+ "properties": ["netaffiliation.com"],
+ "resources": ["netaffiliation.com"]
+ },
+ "Net Applications": {
+ "properties": ["netapplications.com"],
+ "resources": ["hitsprocessor.com", "netapplications.com"]
+ },
+ "NetBina": {
+ "properties": ["netbina.com"],
+ "resources": ["netbina.com"]
+ },
+ "NetElixir": {
+ "properties": ["adelixir.com", "netelixir.com"],
+ "resources": ["adelixir.com", "netelixir.com"]
+ },
+ "Netmining": {
+ "properties": ["netmining.com", "netmng.com"],
+ "resources": ["netmining.com", "netmng.com"]
+ },
+ "Net-Results": {
+ "properties": ["net-results.com", "nr7.us"],
+ "resources": ["cdnma.com", "net-results.com", "nr7.us"]
+ },
+ "NetSeer": {
+ "properties": ["netseer.com"],
+ "resources": ["netseer.com"]
+ },
+ "NetShelter": {
+ "properties": ["ziffdavistech.com"],
+ "resources": ["netshelter.com", "netshelter.net", "ziffdavistech.com"]
+ },
+ "Neustar": {
+ "properties": ["adadvisor.net", "home.neustar", "neustar.biz"],
+ "resources": ["adadvisor.net", "neustar.biz"]
+ },
+ "New Relic": {
+ "properties": ["newrelic.com"],
+ "resources": ["newrelic.com", "nr-data.net"]
+ },
+ "NewsRight": {
+ "properties": ["apnewsregistry.com", "newsright.com"],
+ "resources": ["apnewsregistry.com", "newsright.com"]
+ },
+ "newtention": {
+ "properties": ["newtention.de", "newtention.net", "newtentionassets.net"],
+ "resources": ["newtention.de", "newtention.net", "newtentionassets.net"]
+ },
+ "Nexage": {
+ "properties": ["nexage.com"],
+ "resources": ["nexage.com"]
+ },
+ "Nextag": {
+ "properties": ["nextag.com"],
+ "resources": ["nextag.com"]
+ },
+ "NextPerformance": {
+ "properties": ["nextperf.com", "nextperformance.com", "nxtck.com"],
+ "resources": ["nextperf.com", "nextperformance.com", "nxtck.com"]
+ },
+ "NextSTAT": {
+ "properties": ["nextstat.com"],
+ "resources": ["nextstat.com"]
+ },
+ "Nielsen": {
+ "properties": [
+ "glanceguide.com",
+ "imrworldwide.com",
+ "imrworldwide.net",
+ "nielsen.com"
+ ],
+ "resources": [
+ "glanceguide.com",
+ "imrworldwide.com",
+ "imrworldwide.net",
+ "nielsen.com"
+ ]
+ },
+ "Ninua": {
+ "properties": ["networkedblogs.com", "ninua.com"],
+ "resources": ["networkedblogs.com", "ninua.com"]
+ },
+ "Nokta": {
+ "properties": ["noktamedya.com", "virgul.com"],
+ "resources": ["noktamedya.com", "virgul.com"]
+ },
+ "NowSpots": {
+ "properties": ["nowspots.com"],
+ "resources": ["nowspots.com"]
+ },
+ "nrelate": {
+ "properties": ["nrelate.com"],
+ "resources": ["nrelate.com"]
+ },
+ "NuDataSecurity": {
+ "properties": ["nudatasecurity.com"],
+ "resources": ["nudatasecurity.com"]
+ },
+ "Nuffnang": {
+ "properties": ["nuffnang.com", "nuffnang.com.my", "www.nuffnang.com.my"],
+ "resources": ["nuffnang.com", "nuffnang.com.my", "www.nuffnang.com.my"]
+ },
+ "nugg.ad": {
+ "properties": ["nugg.ad"],
+ "resources": ["nugg.ad", "nuggad.net"]
+ },
+ "nurago": {
+ "properties": ["sensic.net"],
+ "resources": ["nurago.com", "nurago.de", "sensic.net"]
+ },
+ "Oberon Media": {
+ "properties": ["iwin.com"],
+ "resources": ["blaze.com", "iwin.com", "oberon-media.com"]
+ },
+ "Observer": {
+ "properties": ["observerapp.com"],
+ "resources": ["observerapp.com"]
+ },
+ "Ohana Media": {
+ "properties": ["adohana.com", "ohana-media.com", "ohanaqb.com"],
+ "resources": ["adohana.com", "ohana-media.com", "ohanaqb.com"]
+ },
+ "Omnicom Group": {
+ "properties": ["accuenmedia.com", "omnicomgroup.com"],
+ "resources": ["accuenmedia.com", "omnicomgroup.com", "p-td.com"]
+ },
+ "onAd": {
+ "properties": ["onad.eu"],
+ "resources": ["onad.eu"]
+ },
+ "OnAudience": {
+ "properties": ["behavioralengine.com", "onaudience.com"],
+ "resources": ["behavioralengine.com", "onaudience.com"]
+ },
+ "Onclusive": {
+ "properties": ["onclusive.com"],
+ "resources": ["airpr.com"]
+ },
+ "OneAd": {
+ "properties": ["onead.com.tw"],
+ "resources": ["guoshipartners.com", "onevision.com.tw"]
+ },
+ "One iota": {
+ "properties": ["itsoneiota.com", "oneiota.co.uk"],
+ "resources": ["itsoneiota.com", "oneiota.co.uk"]
+ },
+ "OneStat": {
+ "properties": ["onestat.com"],
+ "resources": ["onestat.com"]
+ },
+ "Oneupweb": {
+ "properties": ["oneupweb.com", "sodoit.com"],
+ "resources": ["oneupweb.com", "sodoit.com"]
+ },
+ "OnlineMetrix": {
+ "properties": ["online-metrix.net"],
+ "resources": ["online-metrix.net"]
+ },
+ "Ooyala": {
+ "properties": ["ooyala.com"],
+ "resources": ["oo4.com", "ooyala.com"]
+ },
+ "Open New Media": {
+ "properties": ["onm.de"],
+ "resources": ["onm.de"]
+ },
+ "Openstat": {
+ "properties": ["openstat.com"],
+ "resources": ["openstat.com", "openstat.ru", "spylog.com"]
+ },
+ "Opentracker": {
+ "properties": ["opentracker.net"],
+ "resources": ["opentracker.net"]
+ },
+ "OpenX": {
+ "properties": ["openx.com", "openx.net"],
+ "resources": [
+ "liftdna.com",
+ "openx.com",
+ "openx.net",
+ "openx.org",
+ "openxenterprise.com",
+ "servedbyopenx.com"
+ ]
+ },
+ "Opera": {
+ "properties": ["opera.com"],
+ "resources": ["mobiletheory.com", "opera.com"]
+ },
+ "Opolen": {
+ "properties": ["opolen.com.br"],
+ "resources": ["opolen.com.br"]
+ },
+ "OPT": {
+ "properties": ["www.opt.ne.jp"],
+ "resources": ["advg.jp", "opt.ne.jp", "p-advg.com", "www.opt.ne.jp"]
+ },
+ "Optify": {
+ "properties": ["optify.net"],
+ "resources": ["optify.net"]
+ },
+ "Optimal": {
+ "properties": ["bn.co"],
+ "resources": [
+ "cpmadvisors.com",
+ "cpmatic.com",
+ "nprove.com",
+ "optim.al",
+ "orbengine.com",
+ "xa.net"
+ ]
+ },
+ "Optimizely": {
+ "properties": ["optimizely.com"],
+ "resources": ["optimizely.com"]
+ },
+ "OptimumResponse": {
+ "properties": ["optimumresponse.com"],
+ "resources": ["optimumresponse.com"]
+ },
+ "OptinMonster": {
+ "properties": ["optinmonster.com", "optnmstr.com"],
+ "resources": ["optinmonster.com", "optnmstr.com"]
+ },
+ "OptMD": {
+ "properties": ["optmd.com"],
+ "resources": ["optmd.com"]
+ },
+ "Oracle": {
+ "properties": ["oracle.com"],
+ "resources": [
+ "atgsvcs.com",
+ "eloqua.com",
+ "estara.com",
+ "instantservice.com",
+ "istrack.com",
+ "maxymiser.com",
+ "oracle.com"
+ ]
+ },
+ "OrangeSoda": {
+ "properties": ["orangesoda.com", "otracking.com"],
+ "resources": ["orangesoda.com", "otracking.com"]
+ },
+ "Outbrain": {
+ "properties": ["outbrain.com", "sphere.com"],
+ "resources": ["outbrain.com", "sphere.com", "visualrevenue.com"]
+ },
+ "Out There Media": {
+ "properties": ["out-there-media.com"],
+ "resources": ["out-there-media.com"]
+ },
+ "Oversee.net": {
+ "properties": ["dsnextgen.com", "oversee.net"],
+ "resources": ["dsnextgen.com", "oversee.net"]
+ },
+ "ÖWA": {
+ "properties": ["oewa.at"],
+ "resources": ["oewa.at", "oewabox.at"]
+ },
+ "OwnerIQ": {
+ "properties": ["owneriq.com", "owneriq.net"],
+ "resources": ["owneriq.com", "owneriq.net"]
+ },
+ "OxaMedia": {
+ "properties": ["oxamedia.com"],
+ "resources": ["adconnexa.com", "adsbwm.com", "oxamedia.com"]
+ },
+ "PageFair": {
+ "properties": ["pagefair.com", "pagefair.net"],
+ "resources": ["pagefair.com", "pagefair.net"]
+ },
+ "Paid-To-Promote.net": {
+ "properties": ["paid-to-promote.net"],
+ "resources": ["paid-to-promote.net"]
+ },
+ "Papaya": {
+ "properties": ["papayamobile.com"],
+ "resources": ["papayamobile.com"]
+ },
+ "Pardot": {
+ "properties": ["pardot.com"],
+ "resources": ["pardot.com"]
+ },
+ "Parse.ly": {
+ "properties": ["parsely.com"],
+ "resources": ["parsely.com"]
+ },
+ "PayHit": {
+ "properties": ["payhit.com"],
+ "resources": ["payhit.com"]
+ },
+ "PaymentsMB": {
+ "properties": ["paymentsmb.com"],
+ "resources": ["paymentsmb.com"]
+ },
+ "Paypal": {
+ "properties": ["paypal.com", "simility.com"],
+ "resources": ["paypal.com", "simility.com"]
+ },
+ "Paypopup.com": {
+ "properties": ["paypopup.com"],
+ "resources": ["lzjl.com", "paypopup.com"]
+ },
+ "PebblePost": {
+ "properties": ["pebblepost.com"],
+ "resources": ["pbbl.co"]
+ },
+ "Peer39": {
+ "properties": ["peer39.com", "peer39.net"],
+ "resources": ["peer39.com", "peer39.net"]
+ },
+ "PeerFly": {
+ "properties": ["peerfly.com"],
+ "resources": ["peerfly.com"]
+ },
+ "Peerius": {
+ "properties": ["peerius.com"],
+ "resources": ["peerius.com"]
+ },
+ "Performancing": {
+ "properties": ["performancing.com"],
+ "resources": ["performancing.com"]
+ },
+ "PerimeterX": {
+ "properties": ["perimeterx.com"],
+ "resources": ["perimeterx.com"]
+ },
+ "PersianStat.com": {
+ "properties": ["persianstat.com"],
+ "resources": ["persianstat.com"]
+ },
+ "Pheedo": {
+ "properties": ["pheedo.com"],
+ "resources": ["pheedo.com"]
+ },
+ "Phonalytics": {
+ "properties": ["phonalytics.com"],
+ "resources": ["phonalytics.com"]
+ },
+ "phpMyVisites": {
+ "properties": ["phpmyvisites.us"],
+ "resources": ["phpmyvisites.us"]
+ },
+ "Pictela": {
+ "properties": ["pictela.com", "pictela.net"],
+ "resources": ["pictela.com", "pictela.net"]
+ },
+ "PinPoll": {
+ "properties": ["pinpoll.com"],
+ "resources": ["pinpoll.com"]
+ },
+ "Pinterest": {
+ "properties": [
+ "pinterest.at",
+ "pinterest.ca",
+ "pinterest.ch",
+ "pinterest.cl",
+ "pinterest.co.kr",
+ "pinterest.co.uk",
+ "pinterest.com",
+ "pinterest.com.au",
+ "pinterest.com.mx",
+ "pinterest.de",
+ "pinterest.dk",
+ "pinterest.es",
+ "pinterest.fr",
+ "pinterest.ie",
+ "pinterest.jp",
+ "pinterest.nz",
+ "pinterest.pt",
+ "pinterest.se"
+ ],
+ "resources": ["pinimg.com", "pinterest.com"]
+ },
+ "Piwik": {
+ "properties": ["piwik.org"],
+ "resources": ["piwik.org"]
+ },
+ "PixAnalytics": {
+ "properties": ["pixanalytics.com"],
+ "resources": ["pixanalytics.com"]
+ },
+ "Pixel.sg": {
+ "properties": ["pixel.sg"],
+ "resources": ["pixel.sg"]
+ },
+ "Piximedia": {
+ "properties": ["piximedia.com"],
+ "resources": ["piximedia.com"]
+ },
+ "Pixlee": {
+ "properties": ["pixlee.com"],
+ "resources": ["pixlee.com"]
+ },
+ "PLATFORM ONE": {
+ "properties": ["platform-one.co.jp", "www.platform-one.co.jp"],
+ "resources": ["platform-one.co.jp", "www.platform-one.co.jp"]
+ },
+ "plista": {
+ "properties": ["plista.com"],
+ "resources": ["plista.com"]
+ },
+ "PocketCents": {
+ "properties": ["pocketcents.com"],
+ "resources": ["pocketcents.com"]
+ },
+ "Polar Mobile": {
+ "properties": ["mediavoice.com"],
+ "resources": ["mediavoice.com", "polarmobile.com"]
+ },
+ "Politads": {
+ "properties": ["politads.com"],
+ "resources": ["politads.com"]
+ },
+ "Polymorph": {
+ "properties": ["getpolymorph.com"],
+ "resources": ["adsnative.com", "getpolymorph.com"]
+ },
+ "Pontiflex": {
+ "properties": ["pontiflex.com"],
+ "resources": ["pontiflex.com"]
+ },
+ "Poool": {
+ "properties": ["poool.fr"],
+ "resources": ["poool.fr"]
+ },
+ "PopAds": {
+ "properties": ["popads.net"],
+ "resources": ["popads.net", "popadscdn.net"]
+ },
+ "PopRule": {
+ "properties": ["gocampaignlive.com", "poprule.com"],
+ "resources": ["gocampaignlive.com", "poprule.com"]
+ },
+ "Popunder.ru": {
+ "properties": ["popunder.ru"],
+ "resources": ["popunder.ru"]
+ },
+ "Po.st": {
+ "properties": ["po.st"],
+ "resources": ["po.st"]
+ },
+ "Powerlinks": {
+ "properties": ["powerlinks.com"],
+ "resources": ["powerlinks.com"]
+ },
+ "PPCProtect": {
+ "properties": ["ppcprotect.com"],
+ "resources": ["ppcprotect.com"]
+ },
+ "PrecisionClick": {
+ "properties": ["precisionclick.com"],
+ "resources": ["precisionclick.com"]
+ },
+ "PredictAd": {
+ "properties": ["predictad.com"],
+ "resources": ["predictad.com"]
+ },
+ "Pressflex": {
+ "properties": ["blogads.com", "pressflex.com"],
+ "resources": ["blogads.com", "pressflex.com"]
+ },
+ "Prime Visibility": {
+ "properties": ["primevisibility.com"],
+ "resources": [
+ "adcde.com",
+ "addlvr.com",
+ "adonnetwork.com",
+ "adonnetwork.net",
+ "adtrgt.com",
+ "bannertgt.com",
+ "cptgt.com",
+ "cpvfeed.com",
+ "cpvtgt.com",
+ "dashboardad.net",
+ "popcde.com",
+ "primevisibility.com",
+ "sdfje.com",
+ "urtbk.com"
+ ]
+ },
+ "Primis": {
+ "properties": ["primis.tech"],
+ "resources": ["sekindo.com"]
+ },
+ "PrismApp": {
+ "properties": ["prismapp.io"],
+ "resources": ["prismapp.io"]
+ },
+ "Proclivity": {
+ "properties": ["proclivitysystems.com", "pswec.com"],
+ "resources": ["proclivitymedia.com", "proclivitysystems.com", "pswec.com"]
+ },
+ "Project Wonderful": {
+ "properties": ["projectwonderful.com"],
+ "resources": ["projectwonderful.com"]
+ },
+ "PrometheusIntelligenceTechnology": {
+ "properties": ["prometheusintelligencetechnology.com"],
+ "resources": ["prometheusintelligencetechnology.com"]
+ },
+ "Pronunciator": {
+ "properties": ["pronunciator.com", "visitorville.com"],
+ "resources": ["pronunciator.com", "visitorville.com"]
+ },
+ "Propeller Ads": {
+ "properties": ["propellerads.com"],
+ "resources": ["propellerads.com"]
+ },
+ "Prosperent": {
+ "properties": ["prosperent.com"],
+ "resources": ["prosperent.com"]
+ },
+ "Protected Media": {
+ "properties": ["ad-score.com", "protected.media"],
+ "resources": ["ad-score.com", "protected.media"]
+ },
+ "Provers": {
+ "properties": ["provers.pro"],
+ "resources": ["provers.pro"]
+ },
+ "Psonstrentie": {
+ "properties": ["psonstrentie.info"],
+ "resources": ["psonstrentie.info"]
+ },
+ "Public-Idées": {
+ "properties": ["publicidees.com"],
+ "resources": ["publicidees.com"]
+ },
+ "Publishers Clearing House": {
+ "properties": ["pch.com"],
+ "resources": ["pch.com"]
+ },
+ "PubMatic": {
+ "properties": ["pubmatic.com"],
+ "resources": ["pubmatic.com", "revinet.com"]
+ },
+ "PulsePoint": {
+ "properties": ["pulsepoint.com"],
+ "resources": ["pulsepoint.com"]
+ },
+ "PunchTab": {
+ "properties": ["punchtab.com"],
+ "resources": ["punchtab.com"]
+ },
+ "quadrantOne": {
+ "properties": ["quadrantone.com"],
+ "resources": ["quadrantone.com"]
+ },
+ "Quake Marketing": {
+ "properties": ["quakemarketing.com"],
+ "resources": ["quakemarketing.com"]
+ },
+ "Qualaroo": {
+ "properties": ["qualaroo.com"],
+ "resources": ["kissinsights.com", "qualaroo.com"]
+ },
+ "Quantcast": {
+ "properties": ["quantcast.com", "quantserve.com"],
+ "resources": ["quantcast.com", "quantserve.com"]
+ },
+ "QuantumAdvertising": {
+ "properties": ["quantum-advertising.com"],
+ "resources": ["quantum-advertising.com"]
+ },
+ "QuinStreet": {
+ "properties": ["quinstreet.com", "thecounter.com"],
+ "resources": ["qnsr.com", "qsstats.com", "quinstreet.com", "thecounter.com"]
+ },
+ "Quintelligence": {
+ "properties": ["quintelligence.com"],
+ "resources": ["quintelligence.com"]
+ },
+ "QUISMA": {
+ "properties": ["quisma.com"],
+ "resources": [
+ "iaded.com",
+ "quisma.com",
+ "quismatch.com",
+ "xaded.com",
+ "xmladed.com"
+ ]
+ },
+ "RadarURL": {
+ "properties": ["radarurl.com"],
+ "resources": ["radarurl.com"]
+ },
+ "Radial": {
+ "properties": ["radial.com"],
+ "resources": ["gsicommerce.com", "gsimedia.net"]
+ },
+ "Radiate Media": {
+ "properties": ["gtnetwork.com.au", "solesolution.com"],
+ "resources": [
+ "gtnetwork.com.au",
+ "matchbin.com",
+ "radiatemedia.com",
+ "solesolution.com"
+ ]
+ },
+ "RadiumOne": {
+ "properties": ["radiumone.com"],
+ "resources": ["gwallet.com", "radiumone.com"]
+ },
+ "Radius Marketing": {
+ "properties": ["radiusmarketing.com"],
+ "resources": ["radiusmarketing.com"]
+ },
+ "Rambler": {
+ "properties": ["rambler.ru"],
+ "resources": ["rambler.ru"]
+ },
+ "Rapleaf": {
+ "properties": ["rapleaf.com", "rlcdn.com"],
+ "resources": ["rapleaf.com", "rlcdn.com"]
+ },
+ "ReachLocal": {
+ "properties": ["reachlocal.com", "rlcdn.net"],
+ "resources": ["reachlocal.com", "rlcdn.net"]
+ },
+ "React2Media": {
+ "properties": ["react2media.com"],
+ "resources": ["react2media.com"]
+ },
+ "reddit": {
+ "properties": ["reddit.com"],
+ "resources": ["reddit.com"]
+ },
+ "Redux Media": {
+ "properties": ["reduxmedia.com"],
+ "resources": ["reduxmedia.com"]
+ },
+ "Rekko": {
+ "properties": ["convertglobal.com", "rekko.com"],
+ "resources": ["convertglobal.com", "rekko.com"]
+ },
+ "Reklamport": {
+ "properties": ["reklamport.com"],
+ "resources": ["reklamport.com"]
+ },
+ "Reklam Store": {
+ "properties": ["reklamstore.com"],
+ "resources": ["reklamstore.com"]
+ },
+ "Reklamz": {
+ "properties": ["reklamz.com"],
+ "resources": ["reklamz.com"]
+ },
+ "Relevad": {
+ "properties": ["relestar.com", "relevad.com"],
+ "resources": ["relestar.com", "relevad.com"]
+ },
+ "Renegade Internet": {
+ "properties": ["advertserve.com", "renegadeinternet.com"],
+ "resources": ["advertserve.com", "renegadeinternet.com"]
+ },
+ "Reporo": {
+ "properties": ["reporo.com"],
+ "resources": ["buzzcity.com"]
+ },
+ "Research Now": {
+ "properties": ["researchnow.com", "valuedopinions.co.uk"],
+ "resources": ["researchnow.com", "valuedopinions.co.uk"]
+ },
+ "ResolutionMedia": {
+ "properties": ["nonstoppartner.net"],
+ "resources": ["nonstoppartner.net"]
+ },
+ "Resolution Media": {
+ "properties": ["resolutionmedia.com"],
+ "resources": ["resolutionmedia.com"]
+ },
+ "Resonate": {
+ "properties": ["resonateinsights.com", "resonatenetworks.com"],
+ "resources": ["reson8.com", "resonateinsights.com", "resonatenetworks.com"]
+ },
+ "Responsys": {
+ "properties": ["responsys.com"],
+ "resources": ["responsys.com"]
+ },
+ "Retail Automata": {
+ "properties": ["retailautomata.com"],
+ "resources": ["retailautomata.com"]
+ },
+ "ReTargeter": {
+ "properties": ["retargeter.com"],
+ "resources": ["retargeter.com"]
+ },
+ "Retirement Living": {
+ "properties": ["blvdstatus.com", "retirement-living.com"],
+ "resources": ["blvdstatus.com", "retirement-living.com"]
+ },
+ "RevContent": {
+ "properties": ["revcontent.com"],
+ "resources": ["revcontent.com"]
+ },
+ "RevenueMax": {
+ "properties": ["revenuemax.de"],
+ "resources": ["revenuemax.de"]
+ },
+ "Revtracks": {
+ "properties": ["revtrax.com"],
+ "resources": ["revtrax.com"]
+ },
+ "Rhythm": {
+ "properties": ["rhythmone.com"],
+ "resources": [
+ "1rx.io",
+ "rhythmnewmedia.com",
+ "rhythmone.com",
+ "rhythmxchange.com",
+ "rnmd.net"
+ ]
+ },
+ "RichAudience": {
+ "properties": ["richaudience.com"],
+ "resources": ["richaudience.com"]
+ },
+ "RichRelevance": {
+ "properties": ["richrelevance.com"],
+ "resources": ["richrelevance.com"]
+ },
+ "RightAction": {
+ "properties": ["rightaction.com"],
+ "resources": ["rightaction.com"]
+ },
+ "RIM": {
+ "properties": ["global.blackberry.com", "laptopverge.com"],
+ "resources": [
+ "global.blackberry.com",
+ "laptopverge.com",
+ "rim.com",
+ "scoreloop.com"
+ ]
+ },
+ "Ringier": {
+ "properties": ["ringier.cz"],
+ "resources": ["ringier.cz"]
+ },
+ "RMBN": {
+ "properties": ["traforet.com"],
+ "resources": ["rmbn.net", "rmbn.ru", "traforet.com"]
+ },
+ "RMM": {
+ "properties": ["rmmonline.com"],
+ "resources": ["rmmonline.com"]
+ },
+ "Rocket Fuel": {
+ "properties": ["rfihub.com", "rfihub.net", "rocketfuel.com"],
+ "resources": [
+ "rfihub.com",
+ "rfihub.net",
+ "rocketfuel.com",
+ "ru4.com",
+ "xplusone.com"
+ ]
+ },
+ "Rollick": {
+ "properties": ["gorollick.com"],
+ "resources": ["rollick.io"]
+ },
+ "Rovion": {
+ "properties": ["rovion.com"],
+ "resources": ["rovion.com"]
+ },
+ "Roxr": {
+ "properties": ["clicky.com", "roxr.net"],
+ "resources": ["clicky.com", "getclicky.com", "roxr.net", "staticstuff.net"]
+ },
+ "rtk": {
+ "properties": ["rtk.io"],
+ "resources": ["rtk.io"]
+ },
+ "RubiconProject": {
+ "properties": ["rubiconproject.com"],
+ "resources": ["adsbyisocket.com", "isocket.com", "rubiconproject.com"]
+ },
+ "RunAds": {
+ "properties": ["runads.com"],
+ "resources": ["runads.com", "rundsp.com"]
+ },
+ "RuTarget": {
+ "properties": ["rutarget.ru"],
+ "resources": ["rutarget.ru"]
+ },
+ "Sabavision": {
+ "properties": ["sabavision.com"],
+ "resources": ["sabavision.com"]
+ },
+ "Sabre": {
+ "properties": ["reztrack.com", "sabre.com", "sabrehospitality.com"],
+ "resources": ["reztrack.com", "sabre.com", "sabrehospitality.com"]
+ },
+ "Safecount": {
+ "properties": ["safecount.net"],
+ "resources": [
+ "dl-rms.com",
+ "dlqm.net",
+ "questionmarket.com",
+ "safecount.net"
+ ]
+ },
+ "SageMetrics": {
+ "properties": ["sagemetrics.com"],
+ "resources": ["sageanalyst.net", "sagemetrics.com"]
+ },
+ "Salesforce.com": {
+ "properties": ["force.com", "salesforce.com", "trailblazer.me"],
+ "resources": [
+ "documentforce.com",
+ "force.com",
+ "forcesslreports.com",
+ "forceusercontent.com",
+ "lightning.com",
+ "salesforce-communities.com",
+ "salesforce-hub.com",
+ "salesforce.com",
+ "salesforceliveagent.com",
+ "trailblazer.me",
+ "visualforce.com"
+ ]
+ },
+ "Salesintelligence": {
+ "properties": ["salesintelligence.pl"],
+ "resources": ["plugin.management"]
+ },
+ "Samurai Factory": {
+ "properties": ["samurai-factory.jp", "shinobi.jp"],
+ "resources": ["samurai-factory.jp", "shinobi.jp"]
+ },
+ "SAP": {
+ "properties": ["sap.com"],
+ "resources": ["sap.com", "seewhy.com"]
+ },
+ "Sapient": {
+ "properties": ["bridgetrack.com", "sapient.com"],
+ "resources": ["bridgetrack.com", "sapient.com"]
+ },
+ "SAS": {
+ "properties": ["aimatch.com", "sas.com"],
+ "resources": ["aimatch.com", "sas.com"]
+ },
+ "SAY": {
+ "properties": ["saymedia.com", "typepad.com", "videoegg.com"],
+ "resources": ["saymedia.com", "typepad.com", "videoegg.com"]
+ },
+ "Scandinavian AdNetworks": {
+ "properties": ["scandinavianadnetworks.com"],
+ "resources": ["scandinavianadnetworks.com"]
+ },
+ "ScribeFire": {
+ "properties": ["scribefire.com"],
+ "resources": ["scribefire.com"]
+ },
+ "Scribol": {
+ "properties": ["scribol.com"],
+ "resources": ["scribol.com"]
+ },
+ "SearchForce": {
+ "properties": ["searchforce.com", "searchforce.net"],
+ "resources": ["searchforce.com", "searchforce.net"]
+ },
+ "Seevast": {
+ "properties": ["kanoodle.com"],
+ "resources": [
+ "kanoodle.com",
+ "pulse360.com",
+ "seevast.com",
+ "syndigonetworks.com"
+ ]
+ },
+ "SeeVolution": {
+ "properties": ["seevolution.com", "svlu.net"],
+ "resources": ["seevolution.com", "svlu.net"]
+ },
+ "Segment.io": {
+ "properties": ["segment.io"],
+ "resources": ["segment.io"]
+ },
+ "Selectable Media": {
+ "properties": ["selectablemedia.com"],
+ "resources": ["nabbr.com", "selectablemedia.com"]
+ },
+ "Semantiqo": {
+ "properties": ["semantiqo.com"],
+ "resources": ["semantiqo.com"]
+ },
+ "Semasio": {
+ "properties": ["semasio.com"],
+ "resources": ["semasio.com", "semasio.net"]
+ },
+ "SendPulse": {
+ "properties": ["sendpulse.com"],
+ "resources": ["sendpulse.com"]
+ },
+ "Service4refresh": {
+ "properties": ["service4refresh.info"],
+ "resources": ["service4refresh.info"]
+ },
+ "SessionCam": {
+ "properties": ["sessioncam.com"],
+ "resources": ["sessioncam.com"]
+ },
+ "SevenAds": {
+ "properties": ["sevenads.net"],
+ "resources": ["sevenads.net"]
+ },
+ "SexInYourCity": {
+ "properties": ["sexinyourcity.com"],
+ "resources": ["sexinyourcity.com"]
+ },
+ "ShaftTraffic": {
+ "properties": ["shafttraffic.com"],
+ "resources": ["libertystmedia.com", "shafttraffic.com"]
+ },
+ "Shareaholic": {
+ "properties": ["shareaholic.com"],
+ "resources": ["shareaholic.com"]
+ },
+ "ShareASale": {
+ "properties": ["shareasale.com"],
+ "resources": ["shareasale.com"]
+ },
+ "ShareThis": {
+ "properties": ["sharethis.com"],
+ "resources": ["sharethis.com"]
+ },
+ "Sharethrough": {
+ "properties": ["sharethrough.com"],
+ "resources": ["sharethrough.com"]
+ },
+ "ShinyStat": {
+ "properties": ["shinystat.com"],
+ "resources": ["shinystat.com"]
+ },
+ "Shopzilla": {
+ "properties": ["shopzilla.com"],
+ "resources": ["shopzilla.com"]
+ },
+ "Shortest": {
+ "properties": ["shorte.st"],
+ "resources": ["shorte.st"]
+ },
+ "SiftScience": {
+ "properties": ["sift.com"],
+ "resources": ["siftscience.com"]
+ },
+ "Signifyd": {
+ "properties": ["signifyd.com"],
+ "resources": ["signifyd.com"]
+ },
+ "Silverpop": {
+ "properties": ["mkt51.net", "silverpop.com"],
+ "resources": ["mkt51.net", "pages05.net", "silverpop.com", "vtrenz.net"]
+ },
+ "Simpli.fi": {
+ "properties": ["simpli.fi"],
+ "resources": ["simpli.fi"]
+ },
+ "SiteScout": {
+ "properties": ["sitescout.com"],
+ "resources": ["sitescout.com"]
+ },
+ "Six Apart": {
+ "properties": ["movabletype.com", "sixapart.com"],
+ "resources": ["movabletype.com", "sixapart.com"]
+ },
+ "Skimlinks": {
+ "properties": ["skimlinks.com", "skimresources.com"],
+ "resources": ["skimlinks.com", "skimresources.com"]
+ },
+ "Skribit": {
+ "properties": ["paulstamatiou.com"],
+ "resources": ["paulstamatiou.com", "skribit.com"]
+ },
+ "Skupe Net": {
+ "properties": ["adcentriconline.com", "skupenet.com"],
+ "resources": ["adcentriconline.com", "skupenet.com"]
+ },
+ "Smaato": {
+ "properties": ["smaato.com"],
+ "resources": ["smaato.com"]
+ },
+ "SmartAdServer": {
+ "properties": ["smartadserver.com"],
+ "resources": ["smartadserver.com"]
+ },
+ "Smartlook": {
+ "properties": ["smartlook.com"],
+ "resources": ["smartlook.com"]
+ },
+ "SmartyAds": {
+ "properties": ["smartyads.com"],
+ "resources": ["smartyads.com"]
+ },
+ "Smi": {
+ "properties": ["24smi.net"],
+ "resources": ["24smi.net"]
+ },
+ "Smiley Media": {
+ "properties": ["smileymedia.com"],
+ "resources": ["smileymedia.com"]
+ },
+ "Smowtion": {
+ "properties": ["smowtion.com"],
+ "resources": ["smowtion.com"]
+ },
+ "Snap": {
+ "properties": ["snap.com"],
+ "resources": ["snap.com"]
+ },
+ "SnapEngage": {
+ "properties": ["snapengage.com"],
+ "resources": ["snapengage.com"]
+ },
+ "Snoobi": {
+ "properties": ["snoobi.fi"],
+ "resources": ["snoobi.com", "snoobi.fi"]
+ },
+ "SocialChorus": {
+ "properties": ["socialchorus.com"],
+ "resources": [
+ "halogenmediagroup.com",
+ "halogennetwork.com",
+ "socialchorus.com"
+ ]
+ },
+ "SocialInterface": {
+ "properties": ["socialinterface.com"],
+ "resources": ["ratevoice.com", "socialinterface.com"]
+ },
+ "SocialTwist": {
+ "properties": ["socialtwist.com"],
+ "resources": ["socialtwist.com"]
+ },
+ "sociomantic labs": {
+ "properties": ["sociomantic.com"],
+ "resources": ["sociomantic.com"]
+ },
+ "Socital": {
+ "properties": ["socital.com"],
+ "resources": ["socital.com"]
+ },
+ "Sojern": {
+ "properties": ["sojern.com"],
+ "resources": ["sojern.com"]
+ },
+ "SomoAudience": {
+ "properties": ["somoaudience.com"],
+ "resources": ["somoaudience.com"]
+ },
+ "Sonobi": {
+ "properties": ["sonobi.com"],
+ "resources": ["sonobi.com"]
+ },
+ "sophus3": {
+ "properties": ["sophus3.com"],
+ "resources": ["sophus3.co.uk", "sophus3.com"]
+ },
+ "Sortable": {
+ "properties": ["sortable.com"],
+ "resources": ["deployads.com"]
+ },
+ "Sourcepoint": {
+ "properties": ["sourcepoint.com"],
+ "resources": ["summerhamster.com"]
+ },
+ "Sovrn": {
+ "properties": ["sovrn.com"],
+ "resources": ["sovrn.com"]
+ },
+ "Space Chimp Media": {
+ "properties": ["spacechimpmedia.com"],
+ "resources": ["spacechimpmedia.com"]
+ },
+ "SpareChange": {
+ "properties": ["sparechange.io"],
+ "resources": ["sparechange.io"]
+ },
+ "Sparklit": {
+ "properties": ["adbutler.com", "sparklit.com"],
+ "resources": ["adbutler.com", "sparklit.com"]
+ },
+ "Spark Studios": {
+ "properties": ["sparkstudios.com"],
+ "resources": ["sparkstudios.com"]
+ },
+ "Specific Media": {
+ "properties": ["sitemeter.com", "specificmedia.com"],
+ "resources": [
+ "adviva.co.uk",
+ "adviva.net",
+ "sitemeter.com",
+ "specificclick.net",
+ "specificmedia.com"
+ ]
+ },
+ "Spectate": {
+ "properties": ["spectate.com"],
+ "resources": ["spectate.com"]
+ },
+ "Sponge": {
+ "properties": ["spongegroup.com"],
+ "resources": ["spongegroup.com"]
+ },
+ "Spongecell": {
+ "properties": ["spongecell.com"],
+ "resources": ["spongecell.com"]
+ },
+ "SponsorAds": {
+ "properties": ["sponsorads.de"],
+ "resources": ["sponsorads.de"]
+ },
+ "Spot200": {
+ "properties": ["spot200.com"],
+ "resources": ["spot200.com"]
+ },
+ "SpotX": {
+ "properties": ["spotx.tv"],
+ "resources": ["spotx.tv"]
+ },
+ "SpotXchange": {
+ "properties": ["spotxchange.com"],
+ "resources": ["spotxcdn.com", "spotxchange.com"]
+ },
+ "Spring Metrics": {
+ "properties": ["springmetrics.com"],
+ "resources": ["springmetrics.com"]
+ },
+ "SpringServe": {
+ "properties": ["springserve.com"],
+ "resources": ["springserve.com"]
+ },
+ "Sputnik.ru": {
+ "properties": ["sputnik.ru"],
+ "resources": ["sputnik.ru"]
+ },
+ "StackAdapt": {
+ "properties": ["stackadapt.com"],
+ "resources": ["stackadapt.com"]
+ },
+ "StackTrack": {
+ "properties": ["stat-track.com"],
+ "resources": ["stat-track.com"]
+ },
+ "StarGames": {
+ "properties": ["stargames.net", "stargamesaffiliate.com"],
+ "resources": ["stargames.net", "stargamesaffiliate.com"]
+ },
+ "stat4u": {
+ "properties": ["4u.pl"],
+ "resources": ["4u.pl"]
+ },
+ "StatCounter": {
+ "properties": ["statcounter.com"],
+ "resources": ["statcounter.com"]
+ },
+ "Statisfy": {
+ "properties": ["statisfy.net"],
+ "resources": ["statisfy.net"]
+ },
+ "STATSIT": {
+ "properties": ["statsit.com"],
+ "resources": ["statsit.com"]
+ },
+ "SteelHouse": {
+ "properties": ["steelhouse.com", "steelhousemedia.com"],
+ "resources": ["steelhouse.com", "steelhousemedia.com"]
+ },
+ "Storeland": {
+ "properties": ["storeland.ru"],
+ "resources": ["storeland.ru"]
+ },
+ "Storygize": {
+ "properties": ["storygize.com"],
+ "resources": ["storygize.com", "storygize.net"]
+ },
+ "Stratigent": {
+ "properties": ["stratigent.com"],
+ "resources": ["stratigent.com"]
+ },
+ "Streamray": {
+ "properties": ["cams.com", "streamray.com"],
+ "resources": ["cams.com", "streamray.com"]
+ },
+ "StrikeAd": {
+ "properties": ["strikead.com"],
+ "resources": ["strikead.com"]
+ },
+ "Stripe": {
+ "properties": ["stripe.com"],
+ "resources": ["stripe.network"]
+ },
+ "StrongMail": {
+ "properties": ["strongmail.com"],
+ "resources": ["popularmedia.com", "strongmail.com"]
+ },
+ "Struq": {
+ "properties": ["struq.com"],
+ "resources": ["struq.com"]
+ },
+ "StumbleUpon": {
+ "properties": ["stumbleupon.com"],
+ "resources": ["stumble-upon.com", "stumbleupon.com"]
+ },
+ "Sublime Skinz": {
+ "properties": ["sublime.xyz"],
+ "resources": ["ayads.co", "sublime.xyz"]
+ },
+ "Suite 66": {
+ "properties": ["suite66.com"],
+ "resources": ["suite66.com"]
+ },
+ "Summit": {
+ "properties": ["summitmedia.co.uk", "www.summit.co.uk"],
+ "resources": ["summitmedia.co.uk", "www.summit.co.uk"]
+ },
+ "Superfish": {
+ "properties": ["superfish.com"],
+ "resources": ["superfish.com"]
+ },
+ "SupersonicAds": {
+ "properties": ["supersonicads.com"],
+ "resources": ["supersonicads.com"]
+ },
+ "Survata": {
+ "properties": ["survata.com"],
+ "resources": ["survata.com"]
+ },
+ "SwiftMining": {
+ "properties": ["swiftmining.win"],
+ "resources": ["swiftmining.win"]
+ },
+ "Switch": {
+ "properties": ["switchadhub.com", "switchconcepts.com"],
+ "resources": [
+ "switchadhub.com",
+ "switchads.com",
+ "switchconcepts.co.uk",
+ "switchconcepts.com"
+ ]
+ },
+ "Swoop": {
+ "properties": ["swoop.com"],
+ "resources": ["swoop.com"]
+ },
+ "SymphonyAM": {
+ "properties": ["factortg.com"],
+ "resources": ["factortg.com"]
+ },
+ "Synacor": {
+ "properties": ["synacor.com"],
+ "resources": ["synacor.com"]
+ },
+ "Syncapse": {
+ "properties": ["clickable.net", "syncapse.com"],
+ "resources": ["clickable.net", "syncapse.com"]
+ },
+ "Syrup Ad": {
+ "properties": ["adotsolution.com"],
+ "resources": ["adotsolution.com"]
+ },
+ "Taboola": {
+ "properties": ["taboola.com"],
+ "resources": ["perfectmarket.com", "taboola.com"]
+ },
+ "Tailsweep": {
+ "properties": ["tailsweep.com"],
+ "resources": ["tailsweep.com"]
+ },
+ "Taleria": {
+ "properties": ["telaria.com"],
+ "resources": ["freeskreen.com"]
+ },
+ "Tapad": {
+ "properties": ["tapad.com"],
+ "resources": ["tapad.com"]
+ },
+ "Tapgage": {
+ "properties": ["bizmey.com", "tapgage.com"],
+ "resources": ["bizmey.com", "tapgage.com"]
+ },
+ "TapIt!": {
+ "properties": ["tapit.com"],
+ "resources": ["tapit.com"]
+ },
+ "Tap.me": {
+ "properties": ["tap.me"],
+ "resources": ["tap.me"]
+ },
+ "Targetix": {
+ "properties": ["targetix.net"],
+ "resources": ["targetix.net"]
+ },
+ "Tatto Media": {
+ "properties": ["tattomedia.com"],
+ "resources": ["quicknoodles.com", "tattomedia.com"]
+ },
+ "Teadma": {
+ "properties": ["teadma.com"],
+ "resources": ["teadma.com"]
+ },
+ "Teads.tv": {
+ "properties": ["teads.tv"],
+ "resources": ["teads.tv"]
+ },
+ "Tealium": {
+ "properties": ["tealium.com"],
+ "resources": ["tealiumiq.com"]
+ },
+ "Technorati": {
+ "properties": ["technorati.com"],
+ "resources": ["technorati.com", "technoratimedia.com"]
+ },
+ "TechSolutions": {
+ "properties": ["techsolutions.com.tw"],
+ "resources": ["techsolutions.com.tw"]
+ },
+ "TellApart": {
+ "properties": ["tellapart.com", "tellapt.com"],
+ "resources": ["tellapart.com", "tellapt.com"]
+ },
+ "Telstra": {
+ "properties": ["sensis.com.au", "sensisdata.com.au", "telstra.com.au"],
+ "resources": [
+ "sensis.com.au",
+ "sensisdata.com.au",
+ "sensisdigitalmedia.com.au",
+ "telstra.com.au"
+ ]
+ },
+ "TENSQUARE": {
+ "properties": ["tensquare.com"],
+ "resources": ["tensquare.com"]
+ },
+ "Terra": {
+ "properties": ["eztargetmedia.com", "terra.com.br", "www.terra.com.br"],
+ "resources": ["eztargetmedia.com", "terra.com.br", "www.terra.com.br"]
+ },
+ "The Heron Partnership": {
+ "properties": ["marinsm.com"],
+ "resources": ["heronpartners.com.au", "marinsm.com", "marinsoftware.com"]
+ },
+ "The Numa Group": {
+ "properties": ["hittail.com", "thenumagroup.com"],
+ "resources": ["hittail.com", "thenumagroup.com"]
+ },
+ "The Search Agency": {
+ "properties": ["thesearchagency.com"],
+ "resources": ["thesearchagency.com", "thesearchagency.net"]
+ },
+ "The Trade Desk": {
+ "properties": ["thetradedesk.com"],
+ "resources": ["adsrvr.org", "thetradedesk.com"]
+ },
+ "ThingLink": {
+ "properties": ["thinglink.com"],
+ "resources": ["thinglink.com"]
+ },
+ "Think Realtime": {
+ "properties": ["echosearch.com", "thinkrealtime.com"],
+ "resources": ["echosearch.com", "esm1.net", "thinkrealtime.com"]
+ },
+ "Thismoment": {
+ "properties": ["thismoment.com"],
+ "resources": ["thismoment.com"]
+ },
+ "Thummit": {
+ "properties": ["thummit.com"],
+ "resources": ["thummit.com"]
+ },
+ "Tinder": {
+ "properties": ["carbonads.com", "tinder.com"],
+ "resources": ["carbonads.com", "tinder.com"]
+ },
+ "TiqIQ": {
+ "properties": ["tiqiq.com"],
+ "resources": ["tiqiq.com"]
+ },
+ "Tisoomi": {
+ "properties": ["adternal.com", "tisoomi.com"],
+ "resources": ["adternal.com", "tisoomi.com"]
+ },
+ "TLVMedia": {
+ "properties": ["tlvmedia.com"],
+ "resources": ["tlvmedia.com"]
+ },
+ "TNS": {
+ "properties": [
+ "statistik-gallup.net",
+ "tns-counter.ru",
+ "tns-cs.net",
+ "tnsglobal.com"
+ ],
+ "resources": [
+ "sesamestats.com",
+ "statistik-gallup.net",
+ "tns-counter.ru",
+ "tns-cs.net",
+ "tnsglobal.com"
+ ]
+ },
+ "Todacell": {
+ "properties": ["todacell.com"],
+ "resources": ["todacell.com"]
+ },
+ "ToneFuse": {
+ "properties": ["tonefuse.com"],
+ "resources": ["tonefuse.com"]
+ },
+ "ToneMedia": {
+ "properties": ["clickfuse.com"],
+ "resources": ["clickfuse.com", "tonemedia.com"]
+ },
+ "tongdun.cn": {
+ "properties": ["tongdun.cn"],
+ "resources": ["fraudmetrix.cn", "tongdun.net"]
+ },
+ "Topsy": {
+ "properties": ["topsy.com"],
+ "resources": ["topsy.com"]
+ },
+ "TouchCommerce": {
+ "properties": ["nuance.com"],
+ "resources": ["inq.com", "nuance.com", "touchcommerce.com"]
+ },
+ "TraceMyIP.org": {
+ "properties": ["tracemyip.org"],
+ "resources": ["tracemyip.org"]
+ },
+ "TrackingSoft": {
+ "properties": ["roia.biz", "trackingsoft.com"],
+ "resources": ["roia.biz", "trackingsoft.com"]
+ },
+ "Trackset": {
+ "properties": ["trackset.com"],
+ "resources": ["trackset.com"]
+ },
+ "Tradedoubler": {
+ "properties": ["tradedoubler.com"],
+ "resources": ["tradedoubler.com"]
+ },
+ "TradeTracker": {
+ "properties": ["tradetracker.com"],
+ "resources": ["tradetracker.com", "tradetracker.net"]
+ },
+ "TrafficHaus": {
+ "properties": ["traffichaus.com", "traffichouse.com"],
+ "resources": ["traffichaus.com", "traffichouse.com"]
+ },
+ "TrafficRevenue": {
+ "properties": ["trafficrevenue.net"],
+ "resources": ["trafficrevenue.net"]
+ },
+ "TrafficScore": {
+ "properties": ["trafficscore.com"],
+ "resources": ["trafficscore.com"]
+ },
+ "Traffiq": {
+ "properties": ["traffiq.com"],
+ "resources": ["traffiq.com"]
+ },
+ "Trafmag": {
+ "properties": ["trafmag.com"],
+ "resources": ["trafmag.com"]
+ },
+ "Traverse": {
+ "properties": ["traversedata.com"],
+ "resources": ["traversedlp.com"]
+ },
+ "Travora Media": {
+ "properties": ["travoramedia.com"],
+ "resources": [
+ "traveladnetwork.com",
+ "traveladvertising.com",
+ "travoramedia.com"
+ ]
+ },
+ "Tremor Video": {
+ "properties": ["tremorvideo.com"],
+ "resources": [
+ "scanscout.com",
+ "tmnetads.com",
+ "tremorhub.com",
+ "tremormedia.com",
+ "tremorvideo.com"
+ ]
+ },
+ "Triggit": {
+ "properties": ["triggit.com"],
+ "resources": ["triggit.com"]
+ },
+ "TripleLift": {
+ "properties": ["triplelift.com"],
+ "resources": ["3lift.com", "triplelift.com"]
+ },
+ "Trovus": {
+ "properties": ["trovus.co.uk", "www.trovus.co.uk"],
+ "resources": ["trovus.co.uk", "www.trovus.co.uk"]
+ },
+ "TruEffect": {
+ "properties": ["adlegend.com", "trueffect.com"],
+ "resources": ["adlegend.com", "trueffect.com"]
+ },
+ "Trumba": {
+ "properties": ["trumba.com"],
+ "resources": ["trumba.com"]
+ },
+ "TRUSTe": {
+ "properties": ["truste.com"],
+ "resources": ["truste.com"]
+ },
+ "TrustX": {
+ "properties": ["trustx.org"],
+ "resources": ["trustx.org"]
+ },
+ "TubeMogul": {
+ "properties": ["tmogul.com", "tubemogul.com"],
+ "resources": ["tmogul.com", "tubemogul.com"]
+ },
+ "TurnTo": {
+ "properties": ["turntonetworks.com"],
+ "resources": ["turnto.com", "turntonetworks.com"]
+ },
+ "Tweetboard": {
+ "properties": ["tweetboard.com"],
+ "resources": ["tweetboard.com"]
+ },
+ "Twelvefold": {
+ "properties": ["buzzlogic.com", "twelvefold.com"],
+ "resources": ["buzzlogic.com", "twelvefold.com"]
+ },
+ "Twitter": {
+ "properties": [
+ "digits.com",
+ "fabric.io",
+ "tweetdeck.com",
+ "twitter.com",
+ "twitter.jp"
+ ],
+ "resources": [
+ "ads-twitter.com",
+ "fabric.io",
+ "tweetdeck.com",
+ "twimg.com",
+ "twitter.com",
+ "twitter.jp"
+ ]
+ },
+ "Twitter Counter": {
+ "properties": ["twittercounter.com"],
+ "resources": ["twittercounter.com"]
+ },
+ "Twyn Group": {
+ "properties": ["twyn-group.com", "twyn.com"],
+ "resources": ["twyn-group.com", "twyn.com"]
+ },
+ "Tyroo": {
+ "properties": ["tyroo.com"],
+ "resources": ["tyroo.com"]
+ },
+ "UberMedia": {
+ "properties": ["tweetup.com", "ubermedia.com"],
+ "resources": ["tweetup.com", "ubermedia.com"]
+ },
+ "UberTags": {
+ "properties": ["ubertags.com"],
+ "resources": ["ubertags.com"]
+ },
+ "ucfunnel": {
+ "properties": ["ucfunnel.com"],
+ "resources": ["aralego.com", "ucfunnel.com"]
+ },
+ "uCoz": {
+ "properties": ["ucoz.ae", "ucoz.com", "ucoz.fr", "ucoz.net", "ucoz.ru"],
+ "resources": [
+ "ucoz.ae",
+ "ucoz.br",
+ "ucoz.com",
+ "ucoz.du",
+ "ucoz.fr",
+ "ucoz.net",
+ "ucoz.ru"
+ ]
+ },
+ "Umbel": {
+ "properties": ["umbel.com"],
+ "resources": ["umbel.com"]
+ },
+ "Unanimis": {
+ "properties": ["unanimis.co.uk", "www.unanimis.co.uk"],
+ "resources": ["unanimis.co.uk", "www.unanimis.co.uk"]
+ },
+ "Unbounce": {
+ "properties": ["unbounce.com"],
+ "resources": ["unbounce.com"]
+ },
+ "Underdog Media": {
+ "properties": ["udmserve.net", "underdogmedia.com"],
+ "resources": ["udmserve.net", "underdogmedia.com"]
+ },
+ "Undertone": {
+ "properties": ["undertone.com", "undertonevideo.com"],
+ "resources": [
+ "undertone.com",
+ "undertonenetworks.com",
+ "undertonevideo.com"
+ ]
+ },
+ "UniQlick": {
+ "properties": ["51network.com", "uniqlick.com", "wanmo.com"],
+ "resources": ["51network.com", "uniqlick.com", "wanmo.com"]
+ },
+ "Unruly": {
+ "properties": ["unruly.co"],
+ "resources": ["unrulymedia.com"]
+ },
+ "Upland": {
+ "properties": ["uplandsoftware.com"],
+ "resources": [
+ "leadlander.com",
+ "sf14g.com",
+ "trackalyzer.com",
+ "uplandsoftware.com"
+ ]
+ },
+ "Uptrends": {
+ "properties": ["uptrends.com"],
+ "resources": ["uptrends.com"]
+ },
+ "up-value": {
+ "properties": ["up-value.de"],
+ "resources": ["up-value.de"]
+ },
+ "Usability Sciences": {
+ "properties": ["usabilitysciences.com"],
+ "resources": ["usabilitysciences.com", "webiqonline.com"]
+ },
+ "User Local": {
+ "properties": ["nakanohito.jp"],
+ "resources": ["nakanohito.jp"]
+ },
+ "UserVoice": {
+ "properties": ["uservoice.com"],
+ "resources": ["uservoice.com"]
+ },
+ "V12 Data": {
+ "properties": ["v12group.com"],
+ "resources": ["v12data.com", "v12group.com"]
+ },
+ "Value Ad": {
+ "properties": ["valuead.com"],
+ "resources": ["valuead.com"]
+ },
+ "Various": {
+ "properties": [
+ "amigos.com",
+ "getiton.com",
+ "medley.com",
+ "nostringsattached.com",
+ "various.com"
+ ],
+ "resources": [
+ "amigos.com",
+ "getiton.com",
+ "medley.com",
+ "nostringsattached.com",
+ "various.com"
+ ]
+ },
+ "Vdopia": {
+ "properties": ["ivdopia.com", "vdopia.com"],
+ "resources": ["ivdopia.com", "vdopia.com"]
+ },
+ "Veeseo": {
+ "properties": ["veeseo.com"],
+ "resources": ["veeseo.com"]
+ },
+ "Velocity Media": {
+ "properties": ["adsvelocity.com"],
+ "resources": ["adsvelocity.com"]
+ },
+ "Velti": {
+ "properties": ["mobclix.com", "velti.com"],
+ "resources": ["mobclix.com", "velti.com"]
+ },
+ "Vemba": {
+ "properties": ["vemba.com"],
+ "resources": ["vemba.com"]
+ },
+ "Venatus Media": {
+ "properties": ["venatusmedia.com"],
+ "resources": ["venatusmedia.com"]
+ },
+ "Vendemore": {
+ "properties": ["vendemore.com"],
+ "resources": ["vendemore.com"]
+ },
+ "Vendio": {
+ "properties": ["singlefeed.com", "vendio.com"],
+ "resources": ["singlefeed.com", "vendio.com"]
+ },
+ "Veoxa": {
+ "properties": ["veoxa.com"],
+ "resources": ["veoxa.com"]
+ },
+ "Veremedia": {
+ "properties": ["veremedia.com"],
+ "resources": ["veremedia.com"]
+ },
+ "Vertical Acuity": {
+ "properties": ["verticalacuity.com"],
+ "resources": ["verticalacuity.com"]
+ },
+ "VerticalHealth": {
+ "properties": ["verticalhealth.com"],
+ "resources": ["verticalhealth.net"]
+ },
+ "VerticalResponse": {
+ "properties": ["verticalresponse.com", "vresp.com"],
+ "resources": ["verticalresponse.com", "vresp.com"]
+ },
+ "Vertster": {
+ "properties": ["vertster.com"],
+ "resources": ["vertster.com"]
+ },
+ "VG WORT": {
+ "properties": ["vgwort.de"],
+ "resources": ["vgwort.de"]
+ },
+ "Vibrant Media": {
+ "properties": ["vibrantmedia.com"],
+ "resources": ["intellitxt.com", "picadmedia.com", "vibrantmedia.com"]
+ },
+ "VideoIntelligence": {
+ "properties": ["vi.ai"],
+ "resources": ["vi.ai"]
+ },
+ "Videology": {
+ "properties": ["tidaltv.com", "videologygroup.com"],
+ "resources": ["tidaltv.com", "videologygroup.com"]
+ },
+ "Viewbix": {
+ "properties": ["qoof.com", "viewbix.com"],
+ "resources": ["qoof.com", "viewbix.com"]
+ },
+ "VigLink": {
+ "properties": ["viglink.com"],
+ "resources": ["viglink.com"]
+ },
+ "Vimeo": {
+ "properties": ["vimeo.com", "vimeocdn.com"],
+ "resources": ["vimeo.com", "vimeocdn.com"]
+ },
+ "VINDICO": {
+ "properties": ["vindicogroup.com", "vindicosuite.com"],
+ "resources": ["vindicogroup.com", "vindicosuite.com"]
+ },
+ "VisibleBrands": {
+ "properties": ["visbrands.com"],
+ "resources": ["visbrands.com"]
+ },
+ "Visible Measures": {
+ "properties": ["visiblemeasures.com"],
+ "resources": ["viewablemedia.net", "visiblemeasures.com"]
+ },
+ "VisiStat": {
+ "properties": ["id.kickfire.com", "sa-as.com"],
+ "resources": ["d.kickfire.com", "sa-as.com", "visistat.com"]
+ },
+ "Visit Streamer": {
+ "properties": ["visitstreamer.com"],
+ "resources": ["visitstreamer.com"]
+ },
+ "vistrac": {
+ "properties": ["vistrac.com"],
+ "resources": ["vistrac.com"]
+ },
+ "VisualDNA": {
+ "properties": ["vdna-assets.com", "visualdna-stats.com", "visualdna.com"],
+ "resources": ["vdna-assets.com", "visualdna-stats.com", "visualdna.com"]
+ },
+ "ViziSense": {
+ "properties": ["vizisense.com", "vizisense.net"],
+ "resources": ["vizisense.com", "vizisense.net"]
+ },
+ "Vizu": {
+ "properties": ["vizu.com"],
+ "resources": ["vizu.com"]
+ },
+ "Vizury": {
+ "properties": ["vizury.com"],
+ "resources": ["vizury.com"]
+ },
+ "VKontakte": {
+ "properties": ["vk.com"],
+ "resources": ["userapi.com", "vk.com", "vkontakte.ru"]
+ },
+ "Voice2Page": {
+ "properties": ["voice2page.com"],
+ "resources": ["voice2page.com"]
+ },
+ "Vserv": {
+ "properties": ["vserv.com", "vserv.mobi"],
+ "resources": ["vserv.com", "vserv.mobi"]
+ },
+ "Vuble": {
+ "properties": ["vuble.tv"],
+ "resources": ["mediabong.com"]
+ },
+ "Wahoha": {
+ "properties": ["contentwidgets.net", "wahoha.com"],
+ "resources": ["contentwidgets.net", "wahoha.com"]
+ },
+ "Wayfair": {
+ "properties": ["wayfair.com"],
+ "resources": ["wayfair.com"]
+ },
+ "WebAds": {
+ "properties": ["webads.co.uk", "www.webads.co.uk"],
+ "resources": ["webads.co.uk", "www.webads.co.uk"]
+ },
+ "Webclicktracker": {
+ "properties": ["webclicktracker.com"],
+ "resources": ["webclicktracker.com"]
+ },
+ "Web.com": {
+ "properties": ["feedperfect.com", "web.com"],
+ "resources": ["feedperfect.com", "web.com"]
+ },
+ "WebGozar.com": {
+ "properties": ["webgozar.com", "webgozar.ir"],
+ "resources": ["webgozar.com", "webgozar.ir"]
+ },
+ "Webmecanik": {
+ "properties": ["webmecanik.com"],
+ "resources": ["webmecanik.com"]
+ },
+ "WebMetro": {
+ "properties": ["dsmmadvantage.com", "revanadigital.com"],
+ "resources": ["dsmmadvantage.com", "revanadigital.com", "webmetro.com"]
+ },
+ "Webmine": {
+ "properties": ["webmine.cz"],
+ "resources": ["authedwebmine.cz", "webmine.cz"]
+ },
+ "WebminePool": {
+ "properties": ["webminepool.com"],
+ "resources": ["webminepool.com"]
+ },
+ "Webmining": {
+ "properties": ["webmining.co"],
+ "resources": ["webmining.co"]
+ },
+ "Weborama": {
+ "properties": ["weborama.com"],
+ "resources": ["weborama.com", "weborama.fr"]
+ },
+ "WebsiteAlive": {
+ "properties": [
+ "websitealive.com",
+ "websitealive0.com",
+ "websitealive1.com",
+ "websitealive2.com",
+ "websitealive3.com",
+ "websitealive4.com",
+ "websitealive5.com",
+ "websitealive6.com",
+ "websitealive7.com",
+ "websitealive8.com",
+ "websitealive9.com"
+ ],
+ "resources": ["websitealive.com"]
+ },
+ "Web Stats": {
+ "properties": ["onlinewebstats.com"],
+ "resources": ["onlinewebstats.com"]
+ },
+ "Web Tracking Services": {
+ "properties": ["web-stat.com", "webtrackingservices.com"],
+ "resources": ["web-stat.com", "webtrackingservices.com"]
+ },
+ "Webtraffic": {
+ "properties": ["webtraffic.no", "webtraffic.se"],
+ "resources": ["webtraffic.no", "webtraffic.se"]
+ },
+ "Web Traxs": {
+ "properties": ["webtraxs.com"],
+ "resources": ["webtraxs.com"]
+ },
+ "Webtrekk": {
+ "properties": ["webtrekk.com", "webtrekk.net"],
+ "resources": ["webtrekk.com", "webtrekk.net"]
+ },
+ "Webtrends": {
+ "properties": ["webtrends.com"],
+ "resources": ["reinvigorate.net", "webtrends.com", "webtrendslive.com"]
+ },
+ "White Ops": {
+ "properties": ["adzmath.com", "whiteops.com"],
+ "resources": ["adzmath.com", "whiteops.com"]
+ },
+ "whos.amung.us": {
+ "properties": ["amung.us"],
+ "resources": ["amung.us"]
+ },
+ "WideOrbit": {
+ "properties": ["wideorbit.com"],
+ "resources": ["dep-x.com"]
+ },
+ "Wingify": {
+ "properties": ["vwo.com", "wingify.com"],
+ "resources": ["visualwebsiteoptimizer.com", "vwo.com", "wingify.com"]
+ },
+ "WiredMinds": {
+ "properties": ["wiredminds.de"],
+ "resources": ["wiredminds.com", "wiredminds.de"]
+ },
+ "Wishabi": {
+ "properties": ["wishabi.com", "wishabi.net"],
+ "resources": ["flipp.com", "wishabi.com", "wishabi.net"]
+ },
+ "Woopra": {
+ "properties": ["woopra-ns.com", "woopra.com"],
+ "resources": ["woopra-ns.com", "woopra.com"]
+ },
+ "WordStream": {
+ "properties": ["wordstream.com"],
+ "resources": ["wordstream.com"]
+ },
+ "WOW Analytics": {
+ "properties": ["wowanalytics.co.uk"],
+ "resources": ["wowanalytics.co.uk"]
+ },
+ "WPP": {
+ "properties": [
+ "compete.com",
+ "decdna.net",
+ "groupm.com",
+ "kantarmedia.com",
+ "mecglobal.com",
+ "mindshareworld.com",
+ "themig.com",
+ "wpp.com",
+ "xaxis.com"
+ ],
+ "resources": [
+ "247realmedia.com",
+ "accelerator-media.com",
+ "acceleratorusa.com",
+ "compete.com",
+ "decdna.net",
+ "decideinteractive.com",
+ "gmads.net",
+ "groupm.com",
+ "kantarmedia.com",
+ "mecglobal.com",
+ "mindshare.nl",
+ "mindshareworld.com",
+ "mookie1.com",
+ "pm14.com",
+ "realmedia.com",
+ "targ.ad",
+ "themig.com",
+ "wpp.com",
+ "xaxis.com"
+ ]
+ },
+ "Wysistat": {
+ "properties": ["wysistat.net"],
+ "resources": ["wysistat.com", "wysistat.net"]
+ },
+ "xAd": {
+ "properties": ["xad.com"],
+ "resources": ["xad.com"]
+ },
+ "Xertive Media": {
+ "properties": ["xertivemedia.com"],
+ "resources": ["admanager-xertive.com", "xertivemedia.com"]
+ },
+ "xplosion interactive": {
+ "properties": ["xplosion.de"],
+ "resources": ["xplosion.de"]
+ },
+ "Xrost DS": {
+ "properties": ["adplan-ds.com"],
+ "resources": ["adplan-ds.com"]
+ },
+ "Yabuka": {
+ "properties": ["yabuka.com"],
+ "resources": ["yabuka.com"]
+ },
+ "Yahoo!": {
+ "properties": [
+ "flickr.com",
+ "flurry.com",
+ "tumblr.com",
+ "yahoo.co.jp",
+ "yahoo.com",
+ "yahoostudios.com",
+ "yuilibrary.com"
+ ],
+ "resources": [
+ "adinterax.com",
+ "adrevolver.com",
+ "bluelithium.com",
+ "dapper.net",
+ "flickr.com",
+ "flurry.com",
+ "interclick.com",
+ "luminate.com",
+ "mybloglog.com",
+ "overture.com",
+ "pixazza.com",
+ "rightmedia.com",
+ "rmxads.com",
+ "rocketmail.com",
+ "secure-adserver.com",
+ "staticflickr.com",
+ "tumblr.com",
+ "yahoo.co.jp",
+ "yahoo.com",
+ "yahooapis.com",
+ "yahooapis.jp",
+ "yahoofs.com",
+ "yieldmanager.com",
+ "yieldmanager.net",
+ "yimg.com",
+ "yimg.jp",
+ "yldmgrimg.net",
+ "ymail.com",
+ "yuilibrary.com",
+ "zenfs.com"
+ ]
+ },
+ "Yandex": {
+ "properties": [
+ "kinopoisk.ru",
+ "moikrug.ru",
+ "yadi.sk",
+ "yandex.by",
+ "yandex.com",
+ "yandex.com.tr",
+ "yandex.ru",
+ "yandex.st",
+ "yandex.ua"
+ ],
+ "resources": [
+ "api-maps.yandex.ru",
+ "moikrug.ru",
+ "web-visor.com",
+ "yandex.by",
+ "yandex.com",
+ "yandex.com.tr",
+ "yandex.ru",
+ "yandex.st",
+ "yandex.ua"
+ ]
+ },
+ "Ybrant Digital": {
+ "properties": ["addynamix.com", "brightcom.com", "luj.sdsjweb.com"],
+ "resources": [
+ "addynamix.com",
+ "adserverplus.com",
+ "brightcom.com",
+ "oridian.com",
+ "ybrantdigital.com"
+ ]
+ },
+ "YD": {
+ "properties": ["ydworld.com", "yieldivision.com"],
+ "resources": ["ydworld.com", "yieldivision.com"]
+ },
+ "YellowHammer": {
+ "properties": ["yhmg.com"],
+ "resources": [
+ "attracto.com",
+ "clickhype.com",
+ "yellowhammermg.com",
+ "yhmg.com"
+ ]
+ },
+ "YellowTracker": {
+ "properties": ["yellowtracker.com"],
+ "resources": ["yellowtracker.com"]
+ },
+ "Yes Ads": {
+ "properties": ["yesads.com"],
+ "resources": ["yesads.com"]
+ },
+ "YieldAds": {
+ "properties": ["yieldads.com"],
+ "resources": ["yieldads.com"]
+ },
+ "YieldBids": {
+ "properties": ["ybx.io"],
+ "resources": ["ybx.io"]
+ },
+ "YieldBot": {
+ "properties": ["yieldbot.com"],
+ "resources": ["yldbt.com"]
+ },
+ "YieldBuild": {
+ "properties": ["yieldbuild.com"],
+ "resources": ["yieldbuild.com"]
+ },
+ "Yieldify": {
+ "properties": ["yieldify.com"],
+ "resources": ["yieldify.com"]
+ },
+ "Yieldlab": {
+ "properties": ["yieldlab.de", "yieldlab.net"],
+ "resources": ["yieldlab.de", "yieldlab.net"]
+ },
+ "Yieldmo": {
+ "properties": ["yieldmo.com"],
+ "resources": ["yieldmo.com"]
+ },
+ "YieldNexus": {
+ "properties": ["ynxs.io"],
+ "resources": ["ynxs.io"]
+ },
+ "YOC": {
+ "properties": ["yoc.com"],
+ "resources": ["yoc.com"]
+ },
+ "Yoggrt": {
+ "properties": ["yoggrt.com"],
+ "resources": ["yoggrt.com"]
+ },
+ "youknowbest": {
+ "properties": ["youknowbest.com"],
+ "resources": ["youknowbest.com"]
+ },
+ "YSance": {
+ "properties": ["ysance.com"],
+ "resources": ["y-track.com"]
+ },
+ "YuMe": {
+ "properties": ["yume.com", "yumenetworks.com"],
+ "resources": ["yume.com", "yumenetworks.com"]
+ },
+ "ZafulAffiliate": {
+ "properties": ["zaful.com"],
+ "resources": ["zaful.com"]
+ },
+ "Zango": {
+ "properties": ["metricsdirect.com", "zango.com"],
+ "resources": ["metricsdirect.com", "zango.com"]
+ },
+ "zanox": {
+ "properties": ["buy.at", "zanox-affiliate.de", "zanox.com"],
+ "resources": ["buy.at", "zanox-affiliate.de", "zanox.com"]
+ },
+ "zapunited": {
+ "properties": ["zaparena.com", "zapunited.com"],
+ "resources": ["zaparena.com", "zapunited.com"]
+ },
+ "ZEDO": {
+ "properties": ["zedo.com", "zincx.com"],
+ "resources": ["zedo.com", "zincx.com"]
+ },
+ "Zefir": {
+ "properties": ["ze-fir.com"],
+ "resources": ["ze-fir.com"]
+ },
+ "Zemanta": {
+ "properties": ["zemanta.com"],
+ "resources": ["zemanta.com"]
+ },
+ "Zendesk": {
+ "properties": ["zendesk.com"],
+ "resources": ["zendesk.com"]
+ },
+ "ZestAd": {
+ "properties": ["zestad.com"],
+ "resources": ["zestad.com"]
+ },
+ "Zeta Email Solutions": {
+ "properties": ["insightgrit.com", "zetaemailsolutions.com"],
+ "resources": ["insightgrit.com", "zetaemailsolutions.com"]
+ },
+ "Zopim": {
+ "properties": ["zopim.com"],
+ "resources": ["zopim.com"]
+ },
+ "Zumobi": {
+ "properties": ["zumobi.com"],
+ "resources": ["zumobi.com"]
+ },
+ "ZypMedia": {
+ "properties": ["zypmedia.com"],
+ "resources": ["extend.tv", "zypmedia.com"]
+ }
}
diff --git a/mobile/android/android-components/components/browser/errorpages/src/main/assets/errorPageScripts.js b/mobile/android/android-components/components/browser/errorpages/src/main/assets/errorPageScripts.js
index 7836e30ac0..09804908f7 100644
--- a/mobile/android/android-components/components/browser/errorpages/src/main/assets/errorPageScripts.js
+++ b/mobile/android/android-components/components/browser/errorpages/src/main/assets/errorPageScripts.js
@@ -6,50 +6,54 @@
* Handles the parsing of the ErrorPages URI and then passes them to injectValues
*/
function parseQuery(queryString) {
- if (queryString[0] === '?') {
- queryString = queryString.substr(1);
- }
- const query = Object.fromEntries(new URLSearchParams(queryString).entries());
- injectValues(query)
- updateShowSSL(query)
- updateShowHSTS(query)
-};
+ if (queryString[0] === "?") {
+ queryString = queryString.substr(1);
+ }
+ const query = Object.fromEntries(new URLSearchParams(queryString).entries());
+ injectValues(query);
+ updateShowSSL(query);
+ updateShowHSTS(query);
+}
/**
* Updates the HTML elements based on the queryMap
*/
function injectValues(queryMap) {
- const tryAgainButton = document.getElementById('errorTryAgain')
- const continueHttpButton = document.getElementById("continueHttp")
-
+ const tryAgainButton = document.getElementById("errorTryAgain");
+ const continueHttpButton = document.getElementById("continueHttp");
- // Go through each element and inject the values
- document.title = queryMap.title
- tryAgainButton.innerHTML = queryMap.button
- continueHttpButton.innerHTML = queryMap.continueHttpButton
- document.getElementById('errorTitleText').innerHTML = queryMap.title
- document.getElementById('errorShortDesc').innerHTML = queryMap.description
- document.getElementById('advancedButton').innerHTML = queryMap.badCertAdvanced
- document.getElementById('badCertTechnicalInfo').innerHTML = queryMap.badCertTechInfo
- document.getElementById('advancedPanelBackButton').innerHTML = queryMap.badCertGoBack
- document.getElementById('advancedPanelAcceptButton').innerHTML = queryMap.badCertAcceptTemporary
- document.getElementById('advancedPanelAcceptButton').s = queryMap.badCertAcceptTemporary
+ // Go through each element and inject the values
+ document.title = queryMap.title;
+ tryAgainButton.innerHTML = queryMap.button;
+ continueHttpButton.innerHTML = queryMap.continueHttpButton;
+ document.getElementById("errorTitleText").innerHTML = queryMap.title;
+ document.getElementById("errorShortDesc").innerHTML = queryMap.description;
+ document.getElementById("advancedButton").innerHTML =
+ queryMap.badCertAdvanced;
+ document.getElementById("badCertTechnicalInfo").innerHTML =
+ queryMap.badCertTechInfo;
+ document.getElementById("advancedPanelBackButton").innerHTML =
+ queryMap.badCertGoBack;
+ document.getElementById("advancedPanelAcceptButton").innerHTML =
+ queryMap.badCertAcceptTemporary;
+ document.getElementById("advancedPanelAcceptButton").s =
+ queryMap.badCertAcceptTemporary;
- // If no image is passed in, remove the element so as not to leave an empty iframe
- const errorImage = document.getElementById('errorImage');
- if (!queryMap.image) {
- errorImage.remove();
- } else {
- errorImage.src = "resource://android/assets/" + queryMap.image;
- }
+ // If no image is passed in, remove the element so as not to leave an empty iframe
+ const errorImage = document.getElementById("errorImage");
+ if (!queryMap.image) {
+ errorImage.remove();
+ } else {
+ errorImage.src = "resource://android/assets/" + queryMap.image;
+ }
- if (queryMap.showContinueHttp === "true") {
- // On the "HTTPS-Only" error page "Try again" doesn't make sense since reloading the page
- // will just show an error page again.
- tryAgainButton.style.display = 'none';
- } else {
- continueHttpButton.style.display = 'none';
- }
+ if (queryMap.showContinueHttp === "true") {
+ // On the "HTTPS-Only" error page "Try again" doesn't make sense since reloading the page
+ // will just show an error page again.
+ tryAgainButton.style.display = "none";
+ } else {
+ continueHttpButton.style.display = "none";
+ }
}
var advancedVisible = false;
@@ -58,65 +62,75 @@ var advancedVisible = false;
* Used to show or hide the "advanced" button based on the validity of the SSL certificate
*/
function updateShowSSL(queryMap) {
- /** @type {'true' | 'false'} */
- const showSSL = queryMap.showSSL;
- if (typeof document.addCertException === "undefined") {
- document.getElementById('advancedButton').style.display='none';
+ /** @type {'true' | 'false'} */
+ const showSSL = queryMap.showSSL;
+ if (typeof document.addCertException === "undefined") {
+ document.getElementById("advancedButton").style.display = "none";
+ } else {
+ if (showSSL === "true") {
+ document.getElementById("advancedButton").style.display = "block";
} else {
- if (showSSL === 'true') {
- document.getElementById('advancedButton').style.display='block';
- } else {
- document.getElementById('advancedButton').style.display='none';
- }
+ document.getElementById("advancedButton").style.display = "none";
}
+ }
}
/**
* Used to show or hide the "accept" button based for the HSTS error page
*/
function updateShowHSTS(queryMap) {
- const showHSTS = queryMap.showHSTS;
- if (showHSTS === 'true') {
- document.getElementById('advancedButton').style.display='block';
- document.getElementById('advancedPanelAcceptButton').style.display='none';
- }
+ const showHSTS = queryMap.showHSTS;
+ if (showHSTS === "true") {
+ document.getElementById("advancedButton").style.display = "block";
+ document.getElementById("advancedPanelAcceptButton").style.display = "none";
+ }
}
/**
* Used to display information about the SSL certificate in `error_pages.html`
*/
function toggleAdvanced() {
- if (advancedVisible) {
- document.getElementById('badCertAdvancedPanel').style.display='none';
- } else {
- document.getElementById('badCertAdvancedPanel').style.display='block';
- }
- advancedVisible = !advancedVisible;
+ if (advancedVisible) {
+ document.getElementById("badCertAdvancedPanel").style.display = "none";
+ } else {
+ document.getElementById("badCertAdvancedPanel").style.display = "block";
+ }
+ advancedVisible = !advancedVisible;
}
/**
* Used to bypass an SSL pages in `error_pages.html`
*/
async function acceptAndContinue(temporary) {
- try {
- await document.addCertException(temporary);
- location.reload();
- } catch (error) {
- console.error("Unexpected error: " + error)
- }
+ try {
+ await document.addCertException(temporary);
+ location.reload();
+ } catch (error) {
+ console.error("Unexpected error: " + error);
+ }
}
-document.addEventListener('DOMContentLoaded', function () {
- if (window.history.length == 1) {
- document.getElementById('advancedPanelBackButton').style.display = 'none';
- } else {
- document.getElementById('advancedPanelBackButton').addEventListener('click', () => window.history.back());
- }
+document.addEventListener("DOMContentLoaded", function () {
+ if (window.history.length == 1) {
+ document.getElementById("advancedPanelBackButton").style.display = "none";
+ } else {
+ document
+ .getElementById("advancedPanelBackButton")
+ .addEventListener("click", () => window.history.back());
+ }
- document.getElementById('errorTryAgain').addEventListener('click', () => window.location.reload());
- document.getElementById('advancedButton').addEventListener('click', toggleAdvanced);
- document.getElementById('advancedPanelAcceptButton').addEventListener('click', () => acceptAndContinue(true));
- document.getElementById('continueHttp').addEventListener('click', () => document.reloadWithHttpsOnlyException());
+ document
+ .getElementById("errorTryAgain")
+ .addEventListener("click", () => window.location.reload());
+ document
+ .getElementById("advancedButton")
+ .addEventListener("click", toggleAdvanced);
+ document
+ .getElementById("advancedPanelAcceptButton")
+ .addEventListener("click", () => acceptAndContinue(true));
+ document
+ .getElementById("continueHttp")
+ .addEventListener("click", () => document.reloadWithHttpsOnlyException());
});
parseQuery(document.documentURI);
diff --git a/mobile/android/android-components/components/browser/errorpages/src/main/assets/error_page_js.html b/mobile/android/android-components/components/browser/errorpages/src/main/assets/error_page_js.html
index 397e237303..a6ae19df7c 100644
--- a/mobile/android/android-components/components/browser/errorpages/src/main/assets/error_page_js.html
+++ b/mobile/android/android-components/components/browser/errorpages/src/main/assets/error_page_js.html
@@ -5,54 +5,64 @@
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
<html xmlns="http://www.w3.org/1999/xhtml">
- <head>
- <meta charset="UTF-8">
- <meta name="viewport" content="width=device-width; user-scalable=false;" />
- <meta http-equiv="Content-Security-Policy" content="default-src resource:; object-src 'none'" />
- <link rel="stylesheet" type="text/css" href="error_style.css">
- </head>
-
- <body id="errorPage" dir="auto">
- <!-- PAGE CONTAINER (for styling purposes only) -->
- <div id="errorPageContainer">
-
- <!-- Error Image -->
- <iframe id="errorImage" src="" frameborder="0"></iframe>
-
- <!-- Error Title -->
- <div id="errorTitle">
- <h1 id="errorTitleText"></h1>
- </div>
-
- <!-- LONG CONTENT (the section most likely to require scrolling) -->
- <div id="errorLongContent">
- <div id="errorShortDesc"></div>
- </div>
-
- <!-- Retry Button -->
- <button id="errorTryAgain"></button>
-
- <!-- Advanced Button -->
- <button id="advancedButton" class="buttonSecondary"></button>
-
- <!-- "Continue to HTTP site" Button (For HTTPS-Only error page only) -->
- <button id="continueHttp" class="buttonSecondary"></button>
-
- <div id="advancedPanelContainer">
- <div id="badCertAdvancedPanel" class="advanced-panel">
- <p id="badCertTechnicalInfo"></p>
- <div id="advancedPanelBackButtonContainer" class="advancedPanelButtonContainer">
- <button id="advancedPanelBackButton"></button>
- </div>
- <div id="advancedPanelAcceptButtonContainer" class="advancedPanelButtonContainer">
- <button id="advancedPanelAcceptButton" class="buttonSecondary"></button>
- </div>
- </div>
- </div>
- </div>
+ <head>
+ <meta charset="UTF-8" />
+ <meta name="viewport" content="width=device-width; user-scalable=false;" />
+ <meta
+ http-equiv="Content-Security-Policy"
+ content="default-src resource:; object-src 'none'"
+ />
+ <link rel="stylesheet" type="text/css" href="error_style.css" />
+ </head>
+
+ <body id="errorPage" dir="auto">
+ <!-- PAGE CONTAINER (for styling purposes only) -->
+ <div id="errorPageContainer">
+ <!-- Error Image -->
+ <iframe id="errorImage" src="" frameborder="0"></iframe>
+
+ <!-- Error Title -->
+ <div id="errorTitle">
+ <h1 id="errorTitleText"></h1>
+ </div>
+
+ <!-- LONG CONTENT (the section most likely to require scrolling) -->
+ <div id="errorLongContent">
+ <div id="errorShortDesc"></div>
+ </div>
- </body>
+ <!-- Retry Button -->
+ <button id="errorTryAgain"></button>
+
+ <!-- Advanced Button -->
+ <button id="advancedButton" class="buttonSecondary"></button>
+
+ <!-- "Continue to HTTP site" Button (For HTTPS-Only error page only) -->
+ <button id="continueHttp" class="buttonSecondary"></button>
+
+ <div id="advancedPanelContainer">
+ <div id="badCertAdvancedPanel" class="advanced-panel">
+ <p id="badCertTechnicalInfo"></p>
+ <div
+ id="advancedPanelBackButtonContainer"
+ class="advancedPanelButtonContainer"
+ >
+ <button id="advancedPanelBackButton"></button>
+ </div>
+ <div
+ id="advancedPanelAcceptButtonContainer"
+ class="advancedPanelButtonContainer"
+ >
+ <button
+ id="advancedPanelAcceptButton"
+ class="buttonSecondary"
+ ></button>
+ </div>
+ </div>
+ </div>
+ </div>
+ </body>
- <!-- Each consumer that uses a unique HTML error page must implement a parsing script-->
- <script src="./errorPageScripts.js"></script>
+ <!-- Each consumer that uses a unique HTML error page must implement a parsing script-->
+ <script src="./errorPageScripts.js"></script>
</html>
diff --git a/mobile/android/android-components/components/browser/errorpages/src/main/res/values-azb/strings.xml b/mobile/android/android-components/components/browser/errorpages/src/main/res/values-azb/strings.xml
index 158dbeb60f..b9ca4c9688 100644
--- a/mobile/android/android-components/components/browser/errorpages/src/main/res/values-azb/strings.xml
+++ b/mobile/android/android-components/components/browser/errorpages/src/main/res/values-azb/strings.xml
@@ -83,6 +83,21 @@
<string name="mozac_browser_errorpages_unknown_protocol_title">تانینمایان پروتکل</string>
<!-- The document title and heading of an error page. -->
+ <string name="mozac_browser_errorpages_file_not_found_title">فایل تاپیلمادی</string>
+
+ <!-- The document title and heading of an error page. -->
+ <string name="mozac_browser_errorpages_file_access_denied_title">فایلؽن ایشلدیلمه‌سینه ایجازه وئریلمه‌دی</string>
+
+ <!-- The document title and heading of an error page. -->
+ <string name="mozac_browser_errorpages_proxy_connection_refused_title">پروکسی سرور باغلانتی‌نی رد ائتدی</string>
+
+ <!-- The document title and heading of an error page. -->
+ <string name="mozac_browser_errorpages_unknown_proxy_host_title">پروکسی سرور تاپیلمادی</string>
+
+ <!-- The document title and heading of an error page. -->
+ <string name="mozac_browser_errorpages_safe_browsing_malware_uri_title">ضرر وئریجی سایت سورونو</string>
+
+ <!-- The document title and heading of an error page. -->
<string name="mozac_browser_errorpages_safe_browsing_unwanted_uri_title">ایستنمیه‌ن سایت سورونو</string>
<!-- The document title and heading of an error page. -->
diff --git a/mobile/android/android-components/components/browser/errorpages/src/main/res/values-su/strings.xml b/mobile/android/android-components/components/browser/errorpages/src/main/res/values-su/strings.xml
index 2620051760..cc7efa64eb 100644
--- a/mobile/android/android-components/components/browser/errorpages/src/main/res/values-su/strings.xml
+++ b/mobile/android/android-components/components/browser/errorpages/src/main/res/values-su/strings.xml
@@ -115,7 +115,7 @@
<string name="mozac_browser_errorpages_offline_title">Mode Oplén</string>
<!-- The error message shown when a website cannot be loaded because the browser is in offline mode. -->
- <string name="mozac_browser_errorpages_offline_message"><![CDATA[<p>Panyungsi keur leumpang dina mode luring na jeung teu tiasa nyambung ka barang anu dipénta.</p>
+ <string name="mozac_browser_errorpages_offline_message"><![CDATA[<p>Panyungsi keur leumpang dina modeu luring na jeung teu tiasa nyambung ka barang anu dipénta.</p>
<ul>
<li>Ieu parangkat nyambung ka jaringan aktip heunteu?</li>
<li>Pencét "Cobi deui" pikeun ngalih ka modeu daring sareng ngamuat deui ieu kaca.</li>
@@ -125,7 +125,7 @@
<string name="mozac_browser_errorpages_port_blocked_title">Port diwates pikeun kaamanan</string>
<!-- The error message shown when the browser prevents loading a website on a restricted port. -->
- <string name="mozac_browser_errorpages_port_blocked_message"><![CDATA[<p>Alamat anu dipénta nyebutkeun port (contona <q>mozilla.org:80</q> pikeun port 80 di mozilla.org) galibna dipaké <em>lain</em> pikeun nyungsi Raramat. Panyungsi geus ngabolaykeun paménta pikeun kaamanan anjeun.</p>]]></string>
+ <string name="mozac_browser_errorpages_port_blocked_message"><![CDATA[<p>Alamat anu dipénta nyebutkeun port (contona <q>mozilla.org:80</q> pikeun port 80 di mozilla.org) umumna dipaké <em>lain</em> pikeun nyungsi Raramat. Panyungsi geus ngabolaykeun paménta pikeun kaamanan anjeun.</p>]]></string>
<!-- The document title and heading of the error page shown when the Internet connection is disrupted while loading a website. -->
<string name="mozac_browser_errorpages_net_reset_title">Sambunganana dirését</string>
@@ -206,7 +206,7 @@
</ul>]]></string>
<!-- The document title and heading of an error page. -->
- <string name="mozac_browser_errorpages_unknown_protocol_title">Protokol Teu Dipikawanoh</string>
+ <string name="mozac_browser_errorpages_unknown_protocol_title">Protokol Teu Dipiwanoh</string>
<string name="mozac_browser_errorpages_unknown_protocol_message"><![CDATA[<p>Alamatna méré protocol (e.g., <q>wxyz://</q>) anu teu dipikawanoh ku pamaluruh, ku kituna pamaluruhna teu bisa nyambung kalawan bener ka lokana.</p>
<ul>
@@ -273,7 +273,7 @@
<!-- The title of the error page for websites that do not support HTTPS when HTTPS-Only is turned on -->
<string name="mozac_browser_errorpages_httpsonly_title">Situs Aman Teu Sayaga</string>
<!-- The text of the error page for websites that do not support HTTPS when HTTPS-Only is turned on. %1$s will be replaced with the URL of the website. -->
- <string name="mozac_browser_errorpages_httpsonly_message"><![CDATA[Anjeun ngahurungkeun Mode Ukur-HTTPS pikeun kaamanan lanjutan, anapon pérsi HTTPS <em>%1$s</em> teu sayaga.]]></string>
+ <string name="mozac_browser_errorpages_httpsonly_message"><![CDATA[Anjeun ngahurungkeun Mode Ukur-HTTPS pikeun kaamanan terusan, anapon pérsi HTTPS <em>%1$s</em> teu sayaga.]]></string>
<!-- Button on error page for websites that do not support HTTPS when HTTPS-Only is turned on. Clicking the button allows the user to nevertheless load the website using HTTP. -->
<string name="mozac_browser_errorpages_httpsonly_button">Teruskeun ka Situs HTTP</string>
</resources>
diff --git a/mobile/android/android-components/components/browser/errorpages/src/main/res/values-sv-rSE/strings.xml b/mobile/android/android-components/components/browser/errorpages/src/main/res/values-sv-rSE/strings.xml
index 9a0bf69388..4f22ac030e 100644
--- a/mobile/android/android-components/components/browser/errorpages/src/main/res/values-sv-rSE/strings.xml
+++ b/mobile/android/android-components/components/browser/errorpages/src/main/res/values-sv-rSE/strings.xml
@@ -241,7 +241,7 @@
<ul>
<li>Kan objektet ha bytt namn, tagits bort eller flyttat?</li>
<li>Finns det stavfel, stor bokstav eller annat typografiskt fel i adressen?</li>
- <li>Har du tillräckliga åtkomstbehörigheter till den begärda objektet?</li>
+ <li>Har du tillräckliga åtkomstbehörigheter till det begärda objektet?</li>
</ul>
]]></string>
diff --git a/mobile/android/android-components/components/browser/icons/src/main/assets/extensions/browser-icons/icons.js b/mobile/android/android-components/components/browser/icons/src/main/assets/extensions/browser-icons/icons.js
index 20eada9a19..bc2c6ee35e 100644
--- a/mobile/android/android-components/components/browser/icons/src/main/assets/extensions/browser-icons/icons.js
+++ b/mobile/android/android-components/components/browser/icons/src/main/assets/extensions/browser-icons/icons.js
@@ -2,80 +2,81 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
- /*
- * This web extension looks for known icon tags, collects URLs and available
- * meta data (e.g. sizes) and passes that to the app code.
- */
+/*
+ * This web extension looks for known icon tags, collects URLs and available
+ * meta data (e.g. sizes) and passes that to the app code.
+ */
/**
* Takes a DOMTokenList and returns a String array.
*/
function sizesToList(sizes) {
- if (sizes == null) {
- return []
- }
+ if (sizes == null) {
+ return [];
+ }
- if (!(sizes instanceof DOMTokenList)) {
- return []
- }
+ if (!(sizes instanceof DOMTokenList)) {
+ return [];
+ }
- return Array.from(sizes)
+ return Array.from(sizes);
}
function collect_link_icons(icons, rel) {
- document.querySelectorAll('link[rel="' + rel + '"]').forEach(
- function(currentValue, currentIndex, listObj) {
- icons.push({
- 'type': rel,
- 'href': currentValue.href,
- 'sizes': sizesToList(currentValue.sizes),
- 'mimeType': currentValue.type
- });
- })
+ document
+ .querySelectorAll('link[rel="' + rel + '"]')
+ .forEach(function (currentValue, currentIndex, listObj) {
+ icons.push({
+ type: rel,
+ href: currentValue.href,
+ sizes: sizesToList(currentValue.sizes),
+ mimeType: currentValue.type,
+ });
+ });
}
function collect_meta_property_icons(icons, property) {
- document.querySelectorAll('meta[property="' + property + '"]').forEach(
- function(currentValue, currentIndex, listObj) {
- icons.push({
- 'type': property,
- 'href': currentValue.content
- })
- }
- )
+ document
+ .querySelectorAll('meta[property="' + property + '"]')
+ .forEach(function (currentValue, currentIndex, listObj) {
+ icons.push({
+ type: property,
+ href: currentValue.content,
+ });
+ });
}
function collect_meta_name_icons(icons, name) {
- document.querySelectorAll('meta[name="' + name + '"]').forEach(
- function(currentValue, currentIndex, listObj) {
- icons.push({
- 'type': name,
- 'href': currentValue.content
- })
- }
- )
+ document
+ .querySelectorAll('meta[name="' + name + '"]')
+ .forEach(function (currentValue, currentIndex, listObj) {
+ icons.push({
+ type: name,
+ href: currentValue.content,
+ });
+ });
}
let icons = [];
-collect_link_icons(icons, 'icon');
-collect_link_icons(icons, 'shortcut icon');
-collect_link_icons(icons, 'fluid-icon')
-collect_link_icons(icons, 'apple-touch-icon')
-collect_link_icons(icons, 'image_src')
-collect_link_icons(icons, 'apple-touch-icon image_src')
-collect_link_icons(icons, 'apple-touch-icon-precomposed')
+collect_link_icons(icons, "icon");
+collect_link_icons(icons, "shortcut icon");
+collect_link_icons(icons, "fluid-icon");
+collect_link_icons(icons, "apple-touch-icon");
+collect_link_icons(icons, "image_src");
+collect_link_icons(icons, "apple-touch-icon image_src");
+collect_link_icons(icons, "apple-touch-icon-precomposed");
-collect_meta_property_icons(icons, 'og:image')
-collect_meta_property_icons(icons, 'og:image:url')
-collect_meta_property_icons(icons, 'og:image:secure_url')
+collect_meta_property_icons(icons, "og:image");
+collect_meta_property_icons(icons, "og:image:url");
+collect_meta_property_icons(icons, "og:image:secure_url");
-collect_meta_name_icons(icons, 'twitter:image')
-collect_meta_name_icons(icons, 'msapplication-TileImage')
+collect_meta_name_icons(icons, "twitter:image");
+collect_meta_name_icons(icons, "msapplication-TileImage");
let message = {
- 'url': document.location.href,
- 'icons': icons
-}
+ url: document.location.href,
+ icons: icons,
+};
browser.runtime.sendNativeMessage("MozacBrowserIcons", message);
diff --git a/mobile/android/android-components/components/browser/icons/src/main/java/mozilla/components/browser/icons/BrowserIcons.kt b/mobile/android/android-components/components/browser/icons/src/main/java/mozilla/components/browser/icons/BrowserIcons.kt
index 3bf5c2b2ff..fe44cfc6be 100644
--- a/mobile/android/android-components/components/browser/icons/src/main/java/mozilla/components/browser/icons/BrowserIcons.kt
+++ b/mobile/android/android-components/components/browser/icons/src/main/java/mozilla/components/browser/icons/BrowserIcons.kt
@@ -38,10 +38,12 @@ import mozilla.components.browser.icons.extension.IconMessageHandler
import mozilla.components.browser.icons.generator.DefaultIconGenerator
import mozilla.components.browser.icons.generator.IconGenerator
import mozilla.components.browser.icons.loader.DataUriIconLoader
+import mozilla.components.browser.icons.loader.DefaultMemoryInfoProvider
import mozilla.components.browser.icons.loader.DiskIconLoader
import mozilla.components.browser.icons.loader.HttpIconLoader
import mozilla.components.browser.icons.loader.IconLoader
import mozilla.components.browser.icons.loader.MemoryIconLoader
+import mozilla.components.browser.icons.loader.MemoryInfoProvider
import mozilla.components.browser.icons.loader.NonBlockingHttpIconLoader
import mozilla.components.browser.icons.pipeline.IconResourceComparator
import mozilla.components.browser.icons.preparer.DiskIconPreparer
@@ -91,6 +93,7 @@ class BrowserIcons constructor(
private val context: Context,
httpClient: Client,
private val generator: IconGenerator = DefaultIconGenerator(),
+ private val memoryInfoProvider: MemoryInfoProvider = DefaultMemoryInfoProvider(context),
private val preparers: List<IconPreprarer> = listOf(
TippyTopIconPreparer(context.assets),
MemoryIconPreparer(sharedMemoryCache),
@@ -99,7 +102,10 @@ class BrowserIcons constructor(
internal var loaders: List<IconLoader> = listOf(
MemoryIconLoader(sharedMemoryCache),
DiskIconLoader(sharedDiskCache),
- HttpIconLoader(httpClient),
+ HttpIconLoader(
+ httpClient = httpClient,
+ memoryInfoProvider = memoryInfoProvider,
+ ),
DataUriIconLoader(),
),
private val decoders: List<ImageDecoder> = listOf(
@@ -120,7 +126,10 @@ class BrowserIcons constructor(
private val maximumSize = context.resources.getDimensionPixelSize(R.dimen.mozac_browser_icons_maximum_size)
private val minimumSize = context.resources.getDimensionPixelSize(R.dimen.mozac_browser_icons_minimum_size)
private val scope = CoroutineScope(jobDispatcher)
- private val backgroundHttpIconLoader = NonBlockingHttpIconLoader(httpClient) { request, resource, result ->
+ private val backgroundHttpIconLoader = NonBlockingHttpIconLoader(
+ httpClient = httpClient,
+ memoryInfoProvider = DefaultMemoryInfoProvider(context),
+ ) { request, resource, result ->
val desiredSize = request.getDesiredSize(context, minimumSize, maximumSize)
val icon = decodeIconLoaderResult(result, decoders, desiredSize)
diff --git a/mobile/android/android-components/components/browser/icons/src/main/java/mozilla/components/browser/icons/loader/HttpIconLoader.kt b/mobile/android/android-components/components/browser/icons/src/main/java/mozilla/components/browser/icons/loader/HttpIconLoader.kt
index 430f46f3ec..d3217bc4b2 100644
--- a/mobile/android/android-components/components/browser/icons/src/main/java/mozilla/components/browser/icons/loader/HttpIconLoader.kt
+++ b/mobile/android/android-components/components/browser/icons/src/main/java/mozilla/components/browser/icons/loader/HttpIconLoader.kt
@@ -12,26 +12,30 @@ import androidx.core.net.toUri
import mozilla.components.browser.icons.Icon
import mozilla.components.browser.icons.IconRequest
import mozilla.components.concept.fetch.Client
+import mozilla.components.concept.fetch.Headers
import mozilla.components.concept.fetch.Request
import mozilla.components.concept.fetch.Response
import mozilla.components.concept.fetch.isSuccess
import mozilla.components.support.base.log.logger.Logger
import mozilla.components.support.ktx.android.net.isHttpOrHttps
import mozilla.components.support.ktx.kotlin.sanitizeURL
+import java.io.ByteArrayOutputStream
import java.io.IOException
import java.util.concurrent.TimeUnit
private const val CONNECT_TIMEOUT = 2L // Seconds
private const val READ_TIMEOUT = 10L // Seconds
+private const val MAX_DOWNLOAD_BYTES = 1048576 // 1MB
/**
* [IconLoader] implementation that will try to download the icon for resources that point to an http(s) URL.
*/
open class HttpIconLoader(
private val httpClient: Client,
+ private val memoryInfoProvider: MemoryInfoProvider,
) : IconLoader {
- private val logger = Logger("HttpIconLoader")
private val failureCache = FailureCache()
+ private val logger = Logger("HttpIconLoader")
override fun load(context: Context, request: IconRequest, resource: IconRequest.Resource): IconLoader.Result {
if (!shouldDownload(resource)) {
@@ -78,10 +82,45 @@ open class HttpIconLoader(
protected fun shouldDownload(resource: IconRequest.Resource): Boolean {
return resource.url.sanitizeURL().toUri().isHttpOrHttps && !failureCache.hasFailedRecently(resource.url)
}
-}
-private fun Response.toIconLoaderResult() = body.useStream {
- IconLoader.Result.BytesResult(it.readBytes(), Icon.Source.DOWNLOAD)
+ private fun Response.toIconLoaderResult(): IconLoader.Result {
+ // Compare the Response Content-Length header with the available memory on device
+ val contentLengthHeader = headers[Headers.Names.CONTENT_LENGTH]
+ if (!contentLengthHeader.isNullOrEmpty()) {
+ val contentLength = contentLengthHeader.toLong()
+ return if (contentLength > MAX_DOWNLOAD_BYTES || contentLength > memoryInfoProvider.getAvailMem()) {
+ IconLoader.Result.NoResult
+ } else {
+ // Load the icon without reading to buffers since the checks above passed
+ body.useStream {
+ IconLoader.Result.BytesResult(it.readBytes(), Icon.Source.DOWNLOAD)
+ }
+ }
+ } else {
+ // Read the response body in chunks and check with available memory to prevent exceeding it
+ val buffer = ByteArray(DEFAULT_BUFFER_SIZE)
+ return ByteArrayOutputStream().use { outStream ->
+ body.useStream { inputStream ->
+ var bytesRead = 0
+ var bytesInChunk: Int
+
+ while (inputStream.read(buffer).also { bytesInChunk = it } != -1) {
+ outStream.write(buffer, 0, bytesInChunk)
+ bytesRead += bytesInChunk
+
+ if (bytesRead > MAX_DOWNLOAD_BYTES || bytesRead > memoryInfoProvider.getAvailMem()) {
+ return@useStream IconLoader.Result.NoResult
+ }
+
+ if (bytesInChunk < DEFAULT_BUFFER_SIZE) {
+ break
+ }
+ }
+ IconLoader.Result.BytesResult(outStream.toByteArray(), Icon.Source.DOWNLOAD)
+ }
+ }
+ }
+ }
}
private const val MAX_FAILURE_URLS = 25
diff --git a/mobile/android/android-components/components/browser/icons/src/main/java/mozilla/components/browser/icons/loader/MemoryInfoProvider.kt b/mobile/android/android-components/components/browser/icons/src/main/java/mozilla/components/browser/icons/loader/MemoryInfoProvider.kt
new file mode 100644
index 0000000000..52f8bcbb28
--- /dev/null
+++ b/mobile/android/android-components/components/browser/icons/src/main/java/mozilla/components/browser/icons/loader/MemoryInfoProvider.kt
@@ -0,0 +1,32 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+package mozilla.components.browser.icons.loader
+
+import android.app.ActivityManager
+import android.content.Context
+import androidx.core.content.ContextCompat
+
+/**
+ * This class provides information about the device memory info without exposing the android
+ * framework APIs directly, making it easier to test the code that depends on it.
+ */
+interface MemoryInfoProvider {
+ /**
+ * Returns the device's available memory
+ */
+ fun getAvailMem(): Long
+}
+
+/**
+ * This class retrieves the available memory on device using activity manager.
+ */
+class DefaultMemoryInfoProvider(private val context: Context) : MemoryInfoProvider {
+ override fun getAvailMem(): Long {
+ val activityManager = ContextCompat.getSystemService(context, ActivityManager::class.java)
+ val memoryInfo = ActivityManager.MemoryInfo()
+ activityManager?.getMemoryInfo(memoryInfo)
+ return memoryInfo.availMem
+ }
+}
diff --git a/mobile/android/android-components/components/browser/icons/src/main/java/mozilla/components/browser/icons/loader/NonBlockingHttpIconLoader.kt b/mobile/android/android-components/components/browser/icons/src/main/java/mozilla/components/browser/icons/loader/NonBlockingHttpIconLoader.kt
index c3203dc13f..fcd64662d6 100644
--- a/mobile/android/android-components/components/browser/icons/src/main/java/mozilla/components/browser/icons/loader/NonBlockingHttpIconLoader.kt
+++ b/mobile/android/android-components/components/browser/icons/src/main/java/mozilla/components/browser/icons/loader/NonBlockingHttpIconLoader.kt
@@ -24,9 +24,10 @@ import mozilla.components.concept.fetch.Client
*/
class NonBlockingHttpIconLoader(
httpClient: Client,
+ memoryInfoProvider: MemoryInfoProvider,
private val scope: CoroutineScope = CoroutineScope(Dispatchers.IO),
private val loadCallback: (IconRequest, IconRequest.Resource, IconLoader.Result) -> Unit,
-) : HttpIconLoader(httpClient) {
+) : HttpIconLoader(httpClient, memoryInfoProvider) {
override fun load(context: Context, request: IconRequest, resource: IconRequest.Resource): IconLoader.Result {
if (!shouldDownload(resource)) {
return IconLoader.Result.NoResult
diff --git a/mobile/android/android-components/components/browser/icons/src/test/java/mozilla/components/browser/icons/BrowserIconsTest.kt b/mobile/android/android-components/components/browser/icons/src/test/java/mozilla/components/browser/icons/BrowserIconsTest.kt
index 67a392d0a2..b14b5a30b3 100644
--- a/mobile/android/android-components/components/browser/icons/src/test/java/mozilla/components/browser/icons/BrowserIconsTest.kt
+++ b/mobile/android/android-components/components/browser/icons/src/test/java/mozilla/components/browser/icons/BrowserIconsTest.kt
@@ -13,6 +13,7 @@ import kotlinx.coroutines.CompletableDeferred
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.Job
import mozilla.components.browser.icons.generator.IconGenerator
+import mozilla.components.browser.icons.loader.MemoryInfoProvider
import mozilla.components.concept.engine.manifest.Size
import mozilla.components.lib.fetch.httpurlconnection.HttpURLConnectionClient
import mozilla.components.support.test.any
@@ -46,6 +47,11 @@ import java.io.OutputStream
@ExperimentalCoroutinesApi // for runTestOnMain
@RunWith(AndroidJUnit4::class)
class BrowserIconsTest {
+ private val defaultAvailMem: Long = 100000
+
+ class FakeMemoryInfoProvider(private val availMem: Long) : MemoryInfoProvider {
+ override fun getAvailMem(): Long = availMem
+ }
@get:Rule
val coroutinesTestRule = MainCoroutineRule()
@@ -65,7 +71,12 @@ class BrowserIconsTest {
`when`(generator.generate(any(), any())).thenReturn(mockedIcon)
val request = IconRequest(url = "https://www.mozilla_test.org")
- val icon = BrowserIcons(testContext, httpClient = mock(), generator = generator)
+ val icon = BrowserIcons(
+ context = testContext,
+ httpClient = mock(),
+ generator = generator,
+ memoryInfoProvider = FakeMemoryInfoProvider(defaultAvailMem),
+ )
.loadIcon(request)
assertEquals(mockedIcon, icon.await())
@@ -114,6 +125,7 @@ class BrowserIconsTest {
val icon = BrowserIcons(
testContext,
httpClient = HttpURLConnectionClient(),
+ memoryInfoProvider = FakeMemoryInfoProvider(defaultAvailMem),
).loadIcon(request).await()
assertNotNull(icon)
@@ -139,7 +151,11 @@ class BrowserIconsTest {
server.start()
try {
- val icons = BrowserIcons(testContext, httpClient = HttpURLConnectionClient())
+ val icons = BrowserIcons(
+ context = testContext,
+ httpClient = HttpURLConnectionClient(),
+ memoryInfoProvider = FakeMemoryInfoProvider(defaultAvailMem),
+ )
val request = IconRequest(
url = "https://www.mozilla.org",
@@ -182,7 +198,11 @@ class BrowserIconsTest {
server.start()
try {
- val icons = BrowserIcons(testContext, httpClient = HttpURLConnectionClient())
+ val icons = BrowserIcons(
+ context = testContext,
+ httpClient = HttpURLConnectionClient(),
+ memoryInfoProvider = FakeMemoryInfoProvider(defaultAvailMem),
+ )
val request = IconRequest(
url = "https://www.mozilla.org",
diff --git a/mobile/android/android-components/components/browser/icons/src/test/java/mozilla/components/browser/icons/loader/HttpIconLoaderTest.kt b/mobile/android/android-components/components/browser/icons/src/test/java/mozilla/components/browser/icons/loader/HttpIconLoaderTest.kt
index 3670066921..872440900a 100644
--- a/mobile/android/android-components/components/browser/icons/src/test/java/mozilla/components/browser/icons/loader/HttpIconLoaderTest.kt
+++ b/mobile/android/android-components/components/browser/icons/src/test/java/mozilla/components/browser/icons/loader/HttpIconLoaderTest.kt
@@ -34,6 +34,11 @@ import java.io.InputStream
@RunWith(AndroidJUnit4::class)
class HttpIconLoaderTest {
+ private val defaultAvailMem: Long = 100000
+
+ class FakeMemoryInfoProvider(private val availMem: Long) : MemoryInfoProvider {
+ override fun getAvailMem(): Long = availMem
+ }
@Test
fun `Loader downloads data and uses appropriate headers`() {
@@ -56,7 +61,7 @@ class HttpIconLoaderTest {
server.start()
try {
- val loader = HttpIconLoader(client)
+ val loader = HttpIconLoader(client, FakeMemoryInfoProvider(defaultAvailMem))
val result = loader.load(
mock(),
mock(),
@@ -94,7 +99,7 @@ class HttpIconLoaderTest {
fun `Loader will not perform any requests for data uris`() {
val client: Client = mock()
- val result = HttpIconLoader(client).load(
+ val result = HttpIconLoader(client, FakeMemoryInfoProvider(defaultAvailMem)).load(
mock(),
mock(),
IconRequest.Resource(
@@ -112,7 +117,7 @@ class HttpIconLoaderTest {
fun `Request has timeouts applied`() {
val client: Client = mock()
- val loader = HttpIconLoader(client)
+ val loader = HttpIconLoader(client, FakeMemoryInfoProvider(defaultAvailMem))
doReturn(
Response(
url = "https://www.example.org",
@@ -144,7 +149,7 @@ class HttpIconLoaderTest {
fun `NoResult is returned for non-successful requests`() {
val client: Client = mock()
- val loader = HttpIconLoader(client)
+ val loader = HttpIconLoader(client, FakeMemoryInfoProvider(defaultAvailMem))
doReturn(
Response(
url = "https://www.example.org",
@@ -170,7 +175,7 @@ class HttpIconLoaderTest {
fun `Loader will not try to load URL again that just recently failed`() {
val client: Client = mock()
- val loader = HttpIconLoader(client)
+ val loader = HttpIconLoader(client, FakeMemoryInfoProvider(defaultAvailMem))
doReturn(
Response(
url = "https://www.example.org",
@@ -203,7 +208,7 @@ class HttpIconLoaderTest {
val client: Client = mock()
doThrow(IOException("Mock")).`when`(client).fetch(any())
- val loader = HttpIconLoader(client)
+ val loader = HttpIconLoader(client, FakeMemoryInfoProvider(defaultAvailMem))
val resource = IconRequest.Resource(
url = "https://www.example.org",
@@ -223,7 +228,7 @@ class HttpIconLoaderTest {
}
}
- val loader = HttpIconLoader(client)
+ val loader = HttpIconLoader(client, FakeMemoryInfoProvider(defaultAvailMem))
doReturn(
Response(
url = "https://www.example.org",
@@ -242,10 +247,164 @@ class HttpIconLoaderTest {
}
@Test
+ fun `Loader will return NoResult for response with large Content-Length size`() {
+ val clients = listOf(
+ HttpURLConnectionClient(),
+ OkHttpClient(),
+ )
+
+ clients.forEach { client ->
+ val server = MockWebServer()
+
+ // Create a mock Response object with the Content-Length header set to a large size
+ server.enqueue(
+ MockResponse().setBody(
+ javaClass.getResourceAsStream("/misc/test.txt")!!
+ .bufferedReader()
+ .use { it.readText() },
+ ).addHeader("Content-Length", "2048576"),
+ )
+
+ server.start()
+
+ try {
+ val loader = HttpIconLoader(client, FakeMemoryInfoProvider(defaultAvailMem))
+ val result = loader.load(
+ mock(),
+ mock(),
+ IconRequest.Resource(
+ url = server.url("/some/path").toString(),
+ type = IconRequest.Resource.Type.APPLE_TOUCH_ICON,
+ ),
+ )
+
+ assertTrue(result is IconLoader.Result.NoResult)
+ } finally {
+ server.shutdown()
+ }
+ }
+ }
+
+ @Test
+ fun `Loader will return NoResult for valid Content-Length size and low available memory`() {
+ val clients = listOf(
+ HttpURLConnectionClient(),
+ OkHttpClient(),
+ )
+
+ clients.forEach { client ->
+ val server = MockWebServer()
+
+ server.enqueue(
+ MockResponse().setBody(
+ javaClass.getResourceAsStream("/misc/test.txt")!!
+ .bufferedReader()
+ .use { it.readText() },
+ ).addHeader("Content-Length", "10000"),
+ )
+
+ server.start()
+
+ try {
+ val loader = HttpIconLoader(client, FakeMemoryInfoProvider(availMem = 0))
+ val result = loader.load(
+ mock(),
+ mock(),
+ IconRequest.Resource(
+ url = server.url("/some/path").toString(),
+ type = IconRequest.Resource.Type.APPLE_TOUCH_ICON,
+ ),
+ )
+
+ assertTrue(result is IconLoader.Result.NoResult)
+ } finally {
+ server.shutdown()
+ }
+ }
+ }
+
+ @Test
+ fun `Loader will return NoResult for null Content-Length header and low available memory`() {
+ val clients = listOf(
+ HttpURLConnectionClient(),
+ OkHttpClient(),
+ )
+
+ clients.forEach { client ->
+ val server = MockWebServer()
+
+ server.enqueue(
+ MockResponse().setBody(
+ javaClass.getResourceAsStream("/misc/test.txt")!!
+ .bufferedReader()
+ .use { it.readText() },
+ ).removeHeader("Content-Length"),
+ )
+
+ server.start()
+
+ try {
+ val loader = HttpIconLoader(client, FakeMemoryInfoProvider(availMem = 0))
+ val result = loader.load(
+ mock(),
+ mock(),
+ IconRequest.Resource(
+ url = server.url("/some/path").toString(),
+ type = IconRequest.Resource.Type.APPLE_TOUCH_ICON,
+ ),
+ )
+
+ assertTrue(result is IconLoader.Result.NoResult)
+ } finally {
+ server.shutdown()
+ }
+ }
+ }
+
+ @Test
+ fun `Loader downloads data for null Content-Length header and response size within limits`() {
+ val clients = listOf(
+ HttpURLConnectionClient(),
+ OkHttpClient(),
+ )
+
+ clients.forEach { client ->
+ val server = MockWebServer()
+
+ server.enqueue(
+ MockResponse().setBody(
+ javaClass.getResourceAsStream("/misc/test.txt")!!
+ .bufferedReader()
+ .use { it.readText() },
+ ).removeHeader("Content-Length"),
+ )
+
+ server.start()
+
+ try {
+ val loader = HttpIconLoader(client, FakeMemoryInfoProvider(defaultAvailMem))
+ val result = loader.load(
+ mock(),
+ mock(),
+ IconRequest.Resource(
+ url = server.url("/some/path").toString(),
+ type = IconRequest.Resource.Type.APPLE_TOUCH_ICON,
+ ),
+ )
+ assertTrue("Result should match BytesResult", result is IconLoader.Result.BytesResult)
+ val data = (result as IconLoader.Result.BytesResult).bytes
+ assertTrue("Data should not be empty", data.isNotEmpty())
+ } finally {
+ server.shutdown()
+ }
+ }
+ }
+
+ @Test
fun `Loader will sanitize URL`() {
val client: Client = mock()
- val loader = HttpIconLoader(client)
+ val loader = HttpIconLoader(client, FakeMemoryInfoProvider(defaultAvailMem))
doReturn(
Response(
url = "https://www.example.org",
diff --git a/mobile/android/android-components/components/browser/icons/src/test/java/mozilla/components/browser/icons/loader/NonBlockingHttpIconLoaderTest.kt b/mobile/android/android-components/components/browser/icons/src/test/java/mozilla/components/browser/icons/loader/NonBlockingHttpIconLoaderTest.kt
index 6b2fe8d8ad..2a2da044bf 100644
--- a/mobile/android/android-components/components/browser/icons/src/test/java/mozilla/components/browser/icons/loader/NonBlockingHttpIconLoaderTest.kt
+++ b/mobile/android/android-components/components/browser/icons/src/test/java/mozilla/components/browser/icons/loader/NonBlockingHttpIconLoaderTest.kt
@@ -45,6 +45,11 @@ class NonBlockingHttpIconLoaderTest {
@get:Rule
val coroutinesTestRule = MainCoroutineRule()
private val scope = coroutinesTestRule.scope
+ private val defaultAvailMem: Long = 100000
+
+ class FakeMemoryInfoProvider(private val availMem: Long) : MemoryInfoProvider {
+ override fun getAvailMem(): Long = availMem
+ }
@Test
fun `Loader will return IconLoader#Result#NoResult for a load request and respond with the result through a callback`() = runTestOnMain {
@@ -71,7 +76,7 @@ class NonBlockingHttpIconLoaderTest {
var callbackIconRequest: IconRequest? = null
var callbackResource: IconRequest.Resource? = null
var callbackIcon: IconLoader.Result? = null
- val loader = NonBlockingHttpIconLoader(client, scope) { request, resource, icon ->
+ val loader = NonBlockingHttpIconLoader(client, FakeMemoryInfoProvider(defaultAvailMem), scope) { request, resource, icon ->
callbackIconRequest = request
callbackResource = resource
callbackIcon = icon
@@ -106,7 +111,7 @@ class NonBlockingHttpIconLoaderTest {
var callbackIconRequest: IconRequest? = null
var callbackResource: IconRequest.Resource? = null
var callbackIcon: IconLoader.Result? = null
- val loader = NonBlockingHttpIconLoader(client, scope) { request, resource, icon ->
+ val loader = NonBlockingHttpIconLoader(client, FakeMemoryInfoProvider(defaultAvailMem), scope) { request, resource, icon ->
callbackIconRequest = request
callbackResource = resource
callbackIcon = icon
@@ -132,7 +137,7 @@ class NonBlockingHttpIconLoaderTest {
@Test
fun `Request has timeouts applied`() = runTestOnMain {
val client: Client = mock()
- val loader = NonBlockingHttpIconLoader(client, scope) { _, _, _ -> }
+ val loader = NonBlockingHttpIconLoader(client, FakeMemoryInfoProvider(defaultAvailMem), scope) { _, _, _ -> }
doReturn(
Response(
url = "https://www.example.org",
@@ -165,7 +170,7 @@ class NonBlockingHttpIconLoaderTest {
var callbackIconRequest: IconRequest? = null
var callbackResource: IconRequest.Resource? = null
var callbackIcon: IconLoader.Result? = null
- val loader = NonBlockingHttpIconLoader(client, scope) { request, resource, icon ->
+ val loader = NonBlockingHttpIconLoader(client, FakeMemoryInfoProvider(defaultAvailMem), scope) { request, resource, icon ->
callbackIconRequest = request
callbackResource = resource
callbackIcon = icon
@@ -198,7 +203,7 @@ class NonBlockingHttpIconLoaderTest {
@Test
fun `Loader will not try to load URL again that just recently failed`() = runTestOnMain {
val client: Client = mock()
- val loader = NonBlockingHttpIconLoader(client, scope) { _, _, _ -> }
+ val loader = NonBlockingHttpIconLoader(client, FakeMemoryInfoProvider(defaultAvailMem), scope) { _, _, _ -> }
doReturn(
Response(
url = "https://www.example.org",
@@ -231,7 +236,7 @@ class NonBlockingHttpIconLoaderTest {
var callbackIconRequest: IconRequest? = null
var callbackResource: IconRequest.Resource? = null
var callbackIcon: IconLoader.Result? = null
- val loader = NonBlockingHttpIconLoader(client, scope) { request, resource, icon ->
+ val loader = NonBlockingHttpIconLoader(client, FakeMemoryInfoProvider(defaultAvailMem), scope) { request, resource, icon ->
callbackIconRequest = request
callbackResource = resource
callbackIcon = icon
@@ -256,7 +261,7 @@ class NonBlockingHttpIconLoaderTest {
var callbackIconRequest: IconRequest? = null
var callbackResource: IconRequest.Resource? = null
var callbackIcon: IconLoader.Result? = null
- val loader = NonBlockingHttpIconLoader(client, scope) { request, resource, icon ->
+ val loader = NonBlockingHttpIconLoader(client, FakeMemoryInfoProvider(defaultAvailMem), scope) { request, resource, icon ->
callbackIconRequest = request
callbackResource = resource
callbackIcon = icon
@@ -292,7 +297,7 @@ class NonBlockingHttpIconLoaderTest {
fun `Loader will sanitize URL`() = runTestOnMain {
val client: Client = mock()
val captor = argumentCaptor<Request>()
- val loader = NonBlockingHttpIconLoader(client, scope) { _, _, _ -> }
+ val loader = NonBlockingHttpIconLoader(client, FakeMemoryInfoProvider(defaultAvailMem), scope) { _, _, _ -> }
doReturn(
Response(
url = "https://www.example.org",
diff --git a/mobile/android/android-components/components/browser/menu/src/main/java/mozilla/components/browser/menu/item/CustomTooltip.kt b/mobile/android/android-components/components/browser/menu/src/main/java/mozilla/components/browser/menu/item/CustomTooltip.kt
index 9e7ce8b674..6f83c1ffd9 100644
--- a/mobile/android/android-components/components/browser/menu/src/main/java/mozilla/components/browser/menu/item/CustomTooltip.kt
+++ b/mobile/android/android-components/components/browser/menu/src/main/java/mozilla/components/browser/menu/item/CustomTooltip.kt
@@ -14,7 +14,6 @@ import android.view.WindowManager
import android.widget.LinearLayout
import android.widget.PopupWindow
import android.widget.TextView
-import androidx.core.view.ViewCompat
import androidx.core.widget.PopupWindowCompat
import mozilla.components.browser.menu.R
@@ -34,7 +33,7 @@ internal class CustomTooltip private constructor(
}
override fun onLongClick(view: View): Boolean {
- if (ViewCompat.isAttachedToWindow(anchor)) {
+ if (anchor.isAttachedToWindow()) {
show()
anchor.addOnAttachStateChangeListener(this)
}
diff --git a/mobile/android/android-components/components/browser/menu/src/main/res/values-be/strings.xml b/mobile/android/android-components/components/browser/menu/src/main/res/values-be/strings.xml
index f3b3bb1755..9edc4724a9 100644
--- a/mobile/android/android-components/components/browser/menu/src/main/res/values-be/strings.xml
+++ b/mobile/android/android-components/components/browser/menu/src/main/res/values-be/strings.xml
@@ -10,6 +10,12 @@
<string name="mozac_browser_menu_extensions">Пашырэнні</string>
<!-- Label for add-ons sub menu item for add-ons manager -->
<string name="mozac_browser_menu_addons_manager" moz:removedIn="126" tools:ignore="UnusedResources">Менеджар дадаткаў</string>
+ <!-- Label for extensions sub menu item for extensions manager -->
+ <string name="mozac_browser_menu_extensions_manager">Менеджар пашырэнняў</string>
<!-- Content description for the action bar "up" button -->
<string name="action_bar_up_description">Перайсці ўверх</string>
- </resources>
+ <!-- Content description for the action bar "up" button of the add-ons sub menu item -->
+ <string name="mozac_browser_menu_addons_description" moz:removedIn="126" tools:ignore="UnusedResources">Дадаткі, перайсці ўніз</string>
+ <!-- Content description for the action bar "up" button of the extensions sub menu item -->
+ <string name="mozac_browser_menu_extensions_content_description">Пашырэнні, перайсці ўверх</string>
+</resources>
diff --git a/mobile/android/android-components/components/browser/menu/src/main/res/values-br/strings.xml b/mobile/android/android-components/components/browser/menu/src/main/res/values-br/strings.xml
index 548cbd7785..f8e14c773d 100644
--- a/mobile/android/android-components/components/browser/menu/src/main/res/values-br/strings.xml
+++ b/mobile/android/android-components/components/browser/menu/src/main/res/values-br/strings.xml
@@ -14,4 +14,8 @@
<string name="mozac_browser_menu_extensions_manager">Merañ an askouezhioù</string>
<!-- Content description for the action bar "up" button -->
<string name="action_bar_up_description">Adpignat</string>
- </resources>
+ <!-- Content description for the action bar "up" button of the add-ons sub menu item -->
+ <string name="mozac_browser_menu_addons_description" moz:removedIn="126" tools:ignore="UnusedResources">Enlugelladoù, pignat</string>
+ <!-- Content description for the action bar "up" button of the extensions sub menu item -->
+ <string name="mozac_browser_menu_extensions_content_description">Askouezhioù, pignat</string>
+</resources>
diff --git a/mobile/android/android-components/components/browser/menu/src/main/res/values-cak/strings.xml b/mobile/android/android-components/components/browser/menu/src/main/res/values-cak/strings.xml
index 7ccb1be616..7623a1f39f 100644
--- a/mobile/android/android-components/components/browser/menu/src/main/res/values-cak/strings.xml
+++ b/mobile/android/android-components/components/browser/menu/src/main/res/values-cak/strings.xml
@@ -5,11 +5,17 @@
<!-- Content description (not visible, for screen readers etc.): Indicates the overflow menu has a highlight -->
<string name="mozac_browser_menu_highlighted">Ya\'on ruq\'ij</string>
<!-- Label for add-ons submenu section -->
- <string name="mozac_browser_menu_addons">Taq tz\'aqat</string>
+ <string name="mozac_browser_menu_addons" moz:removedIn="126" tools:ignore="UnusedResources">Taq tz\'aqat</string>
+ <!-- Label for extensions submenu section -->
+ <string name="mozac_browser_menu_extensions">Taq k\'amal</string>
<!-- Label for add-ons sub menu item for add-ons manager -->
- <string name="mozac_browser_menu_addons_manager">Kinuk\'samajel taq Tz\'aqat</string>
+ <string name="mozac_browser_menu_addons_manager" moz:removedIn="126" tools:ignore="UnusedResources">Kinuk\'samajel taq Tz\'aqat</string>
+ <!-- Label for extensions sub menu item for extensions manager -->
+ <string name="mozac_browser_menu_extensions_manager">Runuk\'samajel taq K\'amal</string>
<!-- Content description for the action bar "up" button -->
<string name="action_bar_up_description">Tib\'an okem ajsik</string>
<!-- Content description for the action bar "up" button of the add-ons sub menu item -->
- <string name="mozac_browser_menu_addons_description">Taq tz\'aqat, tijote\' chi rokem</string>
- </resources>
+ <string name="mozac_browser_menu_addons_description" moz:removedIn="126" tools:ignore="UnusedResources">Taq tz\'aqat, tijote\' chi rokem</string>
+ <!-- Content description for the action bar "up" button of the extensions sub menu item -->
+ <string name="mozac_browser_menu_extensions_content_description">Taq k\'amal, tok q\'anij</string>
+</resources>
diff --git a/mobile/android/android-components/components/browser/menu/src/main/res/values-eo/strings.xml b/mobile/android/android-components/components/browser/menu/src/main/res/values-eo/strings.xml
index 63b30a2150..1ca46d5302 100644
--- a/mobile/android/android-components/components/browser/menu/src/main/res/values-eo/strings.xml
+++ b/mobile/android/android-components/components/browser/menu/src/main/res/values-eo/strings.xml
@@ -5,11 +5,17 @@
<!-- Content description (not visible, for screen readers etc.): Indicates the overflow menu has a highlight -->
<string name="mozac_browser_menu_highlighted">Elstarigitaj</string>
<!-- Label for add-ons submenu section -->
- <string name="mozac_browser_menu_addons">Aldonaĵoj</string>
+ <string name="mozac_browser_menu_addons" moz:removedIn="126" tools:ignore="UnusedResources">Aldonaĵoj</string>
+ <!-- Label for extensions submenu section -->
+ <string name="mozac_browser_menu_extensions">Etendaĵoj</string>
<!-- Label for add-ons sub menu item for add-ons manager -->
- <string name="mozac_browser_menu_addons_manager">Administrilo de aldonaĵoj</string>
+ <string name="mozac_browser_menu_addons_manager" moz:removedIn="126" tools:ignore="UnusedResources">Administrilo de aldonaĵoj</string>
+ <!-- Label for extensions sub menu item for extensions manager -->
+ <string name="mozac_browser_menu_extensions_manager">Administranto de etendaĵoj</string>
<!-- Content description for the action bar "up" button -->
<string name="action_bar_up_description">Iri supren</string>
<!-- Content description for the action bar "up" button of the add-ons sub menu item -->
- <string name="mozac_browser_menu_addons_description">Aldonaĵoj, supren</string>
- </resources>
+ <string name="mozac_browser_menu_addons_description" moz:removedIn="126" tools:ignore="UnusedResources">Aldonaĵoj, supren</string>
+ <!-- Content description for the action bar "up" button of the extensions sub menu item -->
+ <string name="mozac_browser_menu_extensions_content_description">Etendaĵoj, supren</string>
+</resources>
diff --git a/mobile/android/android-components/components/browser/menu/src/main/res/values-eu/strings.xml b/mobile/android/android-components/components/browser/menu/src/main/res/values-eu/strings.xml
index 53f1a556a3..b69e874c01 100644
--- a/mobile/android/android-components/components/browser/menu/src/main/res/values-eu/strings.xml
+++ b/mobile/android/android-components/components/browser/menu/src/main/res/values-eu/strings.xml
@@ -5,11 +5,17 @@
<!-- Content description (not visible, for screen readers etc.): Indicates the overflow menu has a highlight -->
<string name="mozac_browser_menu_highlighted">Nabarmendua</string>
<!-- Label for add-ons submenu section -->
- <string name="mozac_browser_menu_addons">Gehigarriak</string>
+ <string name="mozac_browser_menu_addons" moz:removedIn="126" tools:ignore="UnusedResources">Gehigarriak</string>
+ <!-- Label for extensions submenu section -->
+ <string name="mozac_browser_menu_extensions">Hedapenak</string>
<!-- Label for add-ons sub menu item for add-ons manager -->
- <string name="mozac_browser_menu_addons_manager">Gehigarrien kudeatzailea</string>
+ <string name="mozac_browser_menu_addons_manager" moz:removedIn="126" tools:ignore="UnusedResources">Gehigarrien kudeatzailea</string>
+ <!-- Label for extensions sub menu item for extensions manager -->
+ <string name="mozac_browser_menu_extensions_manager">Hedapenen kudeatzailea</string>
<!-- Content description for the action bar "up" button -->
<string name="action_bar_up_description">Nabigatu gora</string>
<!-- Content description for the action bar "up" button of the add-ons sub menu item -->
- <string name="mozac_browser_menu_addons_description">Gehigarriak, nabigatu gora</string>
- </resources>
+ <string name="mozac_browser_menu_addons_description" moz:removedIn="126" tools:ignore="UnusedResources">Gehigarriak, nabigatu gora</string>
+ <!-- Content description for the action bar "up" button of the extensions sub menu item -->
+ <string name="mozac_browser_menu_extensions_content_description">Hedapenak, nabigatu gora</string>
+</resources>
diff --git a/mobile/android/android-components/components/browser/menu/src/main/res/values-kab/strings.xml b/mobile/android/android-components/components/browser/menu/src/main/res/values-kab/strings.xml
index f36a1014b1..58d8809a2c 100644
--- a/mobile/android/android-components/components/browser/menu/src/main/res/values-kab/strings.xml
+++ b/mobile/android/android-components/components/browser/menu/src/main/res/values-kab/strings.xml
@@ -10,6 +10,12 @@
<string name="mozac_browser_menu_extensions">Isiɣzaf</string>
<!-- Label for add-ons sub menu item for add-ons manager -->
<string name="mozac_browser_menu_addons_manager" moz:removedIn="126" tools:ignore="UnusedResources">Amsefrak n izegrar</string>
+ <!-- Label for extensions sub menu item for extensions manager -->
+ <string name="mozac_browser_menu_extensions_manager">Amsefrak n yisiɣzaf</string>
<!-- Content description for the action bar "up" button -->
<string name="action_bar_up_description">Inig d asawen</string>
- </resources>
+ <!-- Content description for the action bar "up" button of the add-ons sub menu item -->
+ <string name="mozac_browser_menu_addons_description" moz:removedIn="126" tools:ignore="UnusedResources">Izegrar niḍen, ulin-d</string>
+ <!-- Content description for the action bar "up" button of the extensions sub menu item -->
+ <string name="mozac_browser_menu_extensions_content_description">Isiɣzaf niḍen, ulin-d</string>
+</resources>
diff --git a/mobile/android/android-components/components/browser/menu/src/main/res/values-sc/strings.xml b/mobile/android/android-components/components/browser/menu/src/main/res/values-sc/strings.xml
index 4fd82314b3..0a94a4fc21 100644
--- a/mobile/android/android-components/components/browser/menu/src/main/res/values-sc/strings.xml
+++ b/mobile/android/android-components/components/browser/menu/src/main/res/values-sc/strings.xml
@@ -5,9 +5,15 @@
<!-- Content description (not visible, for screen readers etc.): Indicates the overflow menu has a highlight -->
<string name="mozac_browser_menu_highlighted">In evidèntzia</string>
<!-- Label for add-ons submenu section -->
- <string name="mozac_browser_menu_addons">Cumplementos</string>
+ <string name="mozac_browser_menu_addons" moz:removedIn="126" tools:ignore="UnusedResources">Cumplementos</string>
+ <!-- Label for extensions submenu section -->
+ <string name="mozac_browser_menu_extensions">Estensiones</string>
<!-- Label for add-ons sub menu item for add-ons manager -->
- <string name="mozac_browser_menu_addons_manager">Gestore de cumplementos</string>
+ <string name="mozac_browser_menu_addons_manager" moz:removedIn="126" tools:ignore="UnusedResources">Gestore de cumplementos</string>
+ <!-- Label for extensions sub menu item for extensions manager -->
+ <string name="mozac_browser_menu_extensions_manager">Gestore de estensiones</string>
<!-- Content description for the action bar "up" button -->
<string name="action_bar_up_description">Nàviga in artu</string>
- </resources>
+ <!-- Content description for the action bar "up" button of the extensions sub menu item -->
+ <string name="mozac_browser_menu_extensions_content_description">Estensiones, torra a coa</string>
+</resources>
diff --git a/mobile/android/android-components/components/browser/menu2/src/test/java/mozilla/components/browser/menu2/ext/BrowserMenuPositioningTest.kt b/mobile/android/android-components/components/browser/menu2/src/test/java/mozilla/components/browser/menu2/ext/BrowserMenuPositioningTest.kt
index d9be746793..23c421bd7c 100644
--- a/mobile/android/android-components/components/browser/menu2/src/test/java/mozilla/components/browser/menu2/ext/BrowserMenuPositioningTest.kt
+++ b/mobile/android/android-components/components/browser/menu2/src/test/java/mozilla/components/browser/menu2/ext/BrowserMenuPositioningTest.kt
@@ -7,7 +7,6 @@ package mozilla.components.browser.menu2.ext
import android.graphics.Rect
import android.view.View
import android.widget.PopupWindow
-import androidx.core.view.ViewCompat
import androidx.recyclerview.widget.RecyclerView
import androidx.test.ext.junit.runners.AndroidJUnit4
import mozilla.components.browser.menu2.R
@@ -755,9 +754,9 @@ internal fun createAnchor(x: Int, y: Int, isRTL: Boolean = false): View {
}.`when`(view).getLocationInWindow(any())
if (isRTL) {
- doReturn(ViewCompat.LAYOUT_DIRECTION_RTL).`when`(view).layoutDirection
+ doReturn(View.LAYOUT_DIRECTION_RTL).`when`(view).layoutDirection
} else {
- doReturn(ViewCompat.LAYOUT_DIRECTION_LTR).`when`(view).layoutDirection
+ doReturn(View.LAYOUT_DIRECTION_LTR).`when`(view).layoutDirection
}
doReturn(10).`when`(view).height
doReturn(15).`when`(view).width
diff --git a/mobile/android/android-components/components/browser/session-storage/src/androidTest/assets/index.html b/mobile/android/android-components/components/browser/session-storage/src/androidTest/assets/index.html
index b511ab2f19..199b5f61d4 100644
--- a/mobile/android/android-components/components/browser/session-storage/src/androidTest/assets/index.html
+++ b/mobile/android/android-components/components/browser/session-storage/src/androidTest/assets/index.html
@@ -1,8 +1,8 @@
<html>
-<head>
+ <head>
<title>Restore Test</title>
-</head>
-<body>
+ </head>
+ <body>
<h1>Hello World</h1>
-</body>
+ </body>
</html>
diff --git a/mobile/android/android-components/components/browser/state/src/main/java/mozilla/components/browser/state/action/BrowserAction.kt b/mobile/android/android-components/components/browser/state/src/main/java/mozilla/components/browser/state/action/BrowserAction.kt
index cd492b18e5..42ad594c8f 100644
--- a/mobile/android/android-components/components/browser/state/src/main/java/mozilla/components/browser/state/action/BrowserAction.kt
+++ b/mobile/android/android-components/components/browser/state/src/main/java/mozilla/components/browser/state/action/BrowserAction.kt
@@ -1048,6 +1048,30 @@ sealed class TranslationsAction : BrowserAction() {
) : TranslationsAction(), ActionWithTab
/**
+ * Sets the translations offer setting on the global store.
+ * The translations offer setting controls when to offer a translation on a page.
+ *
+ * See [SetPageSettingsAction] for setting the offer setting on the session store.
+ *
+ * @property offerTranslation The offer setting to set.
+ */
+ data class SetGlobalOfferTranslateSettingAction(
+ val offerTranslation: Boolean,
+ ) : TranslationsAction()
+
+ /**
+ * Updates the specified translation offer setting on the translation engine and ensures the final
+ * state on the global store remains in-sync.
+ *
+ * See [UpdatePageSettingAction] for updating the offer setting on the session store.
+ *
+ * @property offerTranslation The offer setting to set.
+ */
+ data class UpdateGlobalOfferTranslateSettingAction(
+ val offerTranslation: Boolean,
+ ) : TranslationsAction()
+
+ /**
* Sets the map of BCP 47 language codes (key) and the [LanguageSetting] option (value).
*
* @property languageSettings A map containing a key of BCP 47 language code and its
@@ -1058,26 +1082,36 @@ sealed class TranslationsAction : BrowserAction() {
) : TranslationsAction()
/**
+ * Updates the specified translation language setting on the translation engine and ensures the
+ * final state on the global store remains in-sync.
+ *
+ * See [UpdatePageSettingAction] for updating the language setting on the session store.
+ *
+ * @property languageCode The BCP-47 language code to update.
+ * @property setting The [LanguageSetting] for the language.
+ */
+ data class UpdateLanguageSettingsAction(
+ val languageCode: String,
+ val setting: LanguageSetting,
+ ) : TranslationsAction()
+
+ /**
* Sets the list of sites that the user has opted to never translate.
*
- * @property tabId The ID of the tab the [EngineSession] that requested the list.
* @property neverTranslateSites The never translate sites.
*/
data class SetNeverTranslateSitesAction(
- override val tabId: String,
val neverTranslateSites: List<String>,
- ) : TranslationsAction(), ActionWithTab
+ ) : TranslationsAction()
/**
* Remove from the list of sites the user has opted to never translate.
*
- * @property tabId The ID of the tab the [EngineSession] that requested the removal.
* @property origin A site origin URI that will have the specified never translate permission set.
*/
data class RemoveNeverTranslateSiteAction(
- override val tabId: String,
val origin: String,
- ) : TranslationsAction(), ActionWithTab
+ ) : TranslationsAction()
/**
* Sets the list of language machine learning translation models the translation engine has available.
@@ -1255,6 +1289,7 @@ sealed class EngineAction : BrowserAction() {
override val tabId: String,
val skipLoading: Boolean = false,
val followupAction: BrowserAction? = null,
+ val includeParent: Boolean = false,
) : EngineAction(), ActionWithTab
/**
@@ -1265,6 +1300,7 @@ sealed class EngineAction : BrowserAction() {
val url: String,
val flags: EngineSession.LoadUrlFlags = EngineSession.LoadUrlFlags.none(),
val additionalHeaders: Map<String, String>? = null,
+ val includeParent: Boolean = false,
) : EngineAction(), ActionWithTab
/**
@@ -1402,6 +1438,7 @@ sealed class EngineAction : BrowserAction() {
val engineSession: EngineSession,
val timestamp: Long = Clock.elapsedRealtime(),
val skipLoading: Boolean = false,
+ val includeParent: Boolean = false,
) : EngineAction(), ActionWithTab
/**
diff --git a/mobile/android/android-components/components/browser/state/src/main/java/mozilla/components/browser/state/engine/middleware/CreateEngineSessionMiddleware.kt b/mobile/android/android-components/components/browser/state/src/main/java/mozilla/components/browser/state/engine/middleware/CreateEngineSessionMiddleware.kt
index 6f807eff16..e83fefb9e1 100644
--- a/mobile/android/android-components/components/browser/state/src/main/java/mozilla/components/browser/state/engine/middleware/CreateEngineSessionMiddleware.kt
+++ b/mobile/android/android-components/components/browser/state/src/main/java/mozilla/components/browser/state/engine/middleware/CreateEngineSessionMiddleware.kt
@@ -69,6 +69,7 @@ internal class CreateEngineSessionMiddleware(
logger,
store,
action.tabId,
+ action.includeParent,
)
action.followupAction?.let {
@@ -85,6 +86,7 @@ private fun getOrCreateEngineSession(
logger: Logger,
store: Store<BrowserState, BrowserAction>,
tabId: String,
+ includeParent: Boolean,
): EngineSession? {
val tab = store.state.findTabOrCustomTab(tabId)
if (tab == null) {
@@ -102,7 +104,7 @@ private fun getOrCreateEngineSession(
return it
}
- return createEngineSession(engine, logger, store, tab)
+ return createEngineSession(engine, logger, store, tab, includeParent)
}
@MainThread
@@ -111,6 +113,7 @@ private fun createEngineSession(
logger: Logger,
store: Store<BrowserState, BrowserAction>,
tab: SessionState,
+ includeParent: Boolean,
): EngineSession {
val engineSession = engine.createSession(tab.content.private, tab.contextId)
logger.debug("Created engine session for tab ${tab.id}")
@@ -127,6 +130,7 @@ private fun createEngineSession(
tab.id,
engineSession,
skipLoading = skipLoading,
+ includeParent = includeParent,
),
)
diff --git a/mobile/android/android-components/components/browser/state/src/main/java/mozilla/components/browser/state/engine/middleware/EngineDelegateMiddleware.kt b/mobile/android/android-components/components/browser/state/src/main/java/mozilla/components/browser/state/engine/middleware/EngineDelegateMiddleware.kt
index 1b7744ff41..82298ef2ce 100644
--- a/mobile/android/android-components/components/browser/state/src/main/java/mozilla/components/browser/state/engine/middleware/EngineDelegateMiddleware.kt
+++ b/mobile/android/android-components/components/browser/state/src/main/java/mozilla/components/browser/state/engine/middleware/EngineDelegateMiddleware.kt
@@ -70,11 +70,11 @@ internal class EngineDelegateMiddleware(
// session is already pointing to. Creating an EngineSession will do exactly
// that in the linking step. So let's do that. Otherwise we would load the URL
// twice.
- store.dispatch(EngineAction.CreateEngineSessionAction(action.tabId))
+ store.dispatch(EngineAction.CreateEngineSessionAction(action.tabId, includeParent = action.includeParent))
return@launch
}
- val parentEngineSession = if (tab is TabSessionState) {
+ val parentEngineSession = if (action.includeParent && tab is TabSessionState) {
tab.parentId?.let { store.state.findTabOrCustomTab(it)?.engineState?.engineSession }
} else {
null
diff --git a/mobile/android/android-components/components/browser/state/src/main/java/mozilla/components/browser/state/engine/middleware/LinkingMiddleware.kt b/mobile/android/android-components/components/browser/state/src/main/java/mozilla/components/browser/state/engine/middleware/LinkingMiddleware.kt
index c6f1d01d39..ba714b5e90 100644
--- a/mobile/android/android-components/components/browser/state/src/main/java/mozilla/components/browser/state/engine/middleware/LinkingMiddleware.kt
+++ b/mobile/android/android-components/components/browser/state/src/main/java/mozilla/components/browser/state/engine/middleware/LinkingMiddleware.kt
@@ -37,7 +37,13 @@ internal class LinkingMiddleware(
when (action) {
is TabListAction.AddTabAction -> {
if (action.tab.engineState.engineSession != null && action.tab.engineState.engineObserver == null) {
- engineObserver = link(context, action.tab.engineState.engineSession, action.tab)
+ engineObserver = link(
+ context,
+ action.tab.engineState.engineSession,
+ action.tab,
+ skipLoading = true,
+ includeParent = false,
+ )
}
}
is TabListAction.AddMultipleTabsAction -> {
@@ -58,7 +64,7 @@ internal class LinkingMiddleware(
when (action) {
is EngineAction.LinkEngineSessionAction -> {
context.state.findTabOrCustomTab(action.tabId)?.let { tab ->
- engineObserver = link(context, action.engineSession, tab, action.skipLoading)
+ engineObserver = link(context, action.engineSession, tab, action.skipLoading, action.includeParent)
}
}
else -> {
@@ -77,6 +83,7 @@ internal class LinkingMiddleware(
engineSession: EngineSession,
tab: SessionState,
skipLoading: Boolean = true,
+ includeParent: Boolean,
): Pair<String, EngineObserver> {
val observer = EngineObserver(tab.id, context.store)
engineSession.register(observer)
@@ -91,7 +98,7 @@ internal class LinkingMiddleware(
// tab, but opened by an extension e.g. via browser.tabs.update.
performLoadOnMainThread(engineSession, tab.content.url, loadFlags = tab.engineState.initialLoadFlags)
} else {
- val parentEngineSession = if (tab is TabSessionState) {
+ val parentEngineSession = if (includeParent && tab is TabSessionState) {
tab.parentId?.let { context.state.findTabOrCustomTab(it)?.engineState?.engineSession }
} else {
null
diff --git a/mobile/android/android-components/components/browser/state/src/main/java/mozilla/components/browser/state/engine/middleware/TranslationsMiddleware.kt b/mobile/android/android-components/components/browser/state/src/main/java/mozilla/components/browser/state/engine/middleware/TranslationsMiddleware.kt
index 81e3b8b48b..3c8e645a97 100644
--- a/mobile/android/android-components/components/browser/state/src/main/java/mozilla/components/browser/state/engine/middleware/TranslationsMiddleware.kt
+++ b/mobile/android/android-components/components/browser/state/src/main/java/mozilla/components/browser/state/engine/middleware/TranslationsMiddleware.kt
@@ -79,6 +79,12 @@ class TranslationsMiddleware(
requestPageSettings(context, action.tabId)
}
}
+ TranslationOperation.FETCH_OFFER_SETTING -> {
+ scope.launch {
+ requestOfferSetting(context, action.tabId)
+ }
+ }
+
TranslationOperation.FETCH_AUTOMATIC_LANGUAGE_SETTINGS -> {
scope.launch {
requestLanguageSettings(context, action.tabId)
@@ -86,7 +92,7 @@ class TranslationsMiddleware(
}
TranslationOperation.FETCH_NEVER_TRANSLATE_SITES -> {
scope.launch {
- getNeverTranslateSites(context, action.tabId)
+ requestNeverTranslateSites(context, action.tabId)
}
}
TranslationOperation.TRANSLATE,
@@ -108,7 +114,7 @@ class TranslationsMiddleware(
is TranslationsAction.RemoveNeverTranslateSiteAction -> {
scope.launch {
- removeNeverTranslateSite(context, action.tabId, action.origin)
+ removeNeverTranslateSite(context, action.origin)
}
}
@@ -151,6 +157,25 @@ class TranslationsMiddleware(
}
}
}
+
+ is TranslationsAction.UpdateGlobalOfferTranslateSettingAction -> {
+ scope.launch {
+ updateAlwaysOfferPopupPageSetting(
+ setting = action.offerTranslation,
+ )
+ }
+ }
+
+ is TranslationsAction.UpdateLanguageSettingsAction -> {
+ scope.launch {
+ updateLanguageSetting(
+ context = context,
+ languageCode = action.languageCode,
+ setting = action.setting,
+ )
+ }
+ }
+
else -> {
// no-op
}
@@ -168,6 +193,8 @@ class TranslationsMiddleware(
* Language Support - [requestSupportedLanguages]
* Language Models - [requestLanguageModels]
* Language Settings - [requestLanguageSettings]
+ * Never Translate Sites List - [requestNeverTranslateSites]
+ * Offer Setting - [requestOfferSetting]
*
* @param context Context to use to dispatch to the store.
*/
@@ -177,6 +204,8 @@ class TranslationsMiddleware(
requestSupportedLanguages(context)
requestLanguageModels(context)
requestLanguageSettings(context)
+ requestNeverTranslateSites(context)
+ requestOfferSetting(context)
}
/**
@@ -336,22 +365,22 @@ class TranslationsMiddleware(
}
/**
- * Retrieves the list of never translate sites using [scope] and dispatches the result to the
- * store via [TranslationsAction.SetNeverTranslateSitesAction] or else dispatches the failure
- * [TranslationsAction.TranslateExceptionAction].
+ * Retrieves the list of never translate sites and dispatches the result to the
+ * store via [TranslationsAction.SetNeverTranslateSitesAction] or else
+ * dispatches the failure via [TranslationsAction.EngineExceptionAction] and
+ * when a [tabId] is provided, [TranslationsAction.TranslateExceptionAction].
*
* @param context Context to use to dispatch to the store.
* @param tabId Tab ID associated with the request.
*/
- private fun getNeverTranslateSites(
+ private fun requestNeverTranslateSites(
context: MiddlewareContext<BrowserState, BrowserAction>,
- tabId: String,
+ tabId: String? = null,
) {
engine.getNeverTranslateSiteList(
onSuccess = {
context.store.dispatch(
TranslationsAction.SetNeverTranslateSitesAction(
- tabId = tabId,
neverTranslateSites = it,
),
)
@@ -360,12 +389,19 @@ class TranslationsMiddleware(
onError = {
context.store.dispatch(
- TranslationsAction.TranslateExceptionAction(
- tabId = tabId,
- operation = TranslationOperation.FETCH_NEVER_TRANSLATE_SITES,
- translationError = TranslationError.CouldNotLoadNeverTranslateSites(it),
+ TranslationsAction.EngineExceptionAction(
+ error = TranslationError.CouldNotLoadNeverTranslateSites(it),
),
)
+ if (tabId != null) {
+ context.store.dispatch(
+ TranslationsAction.TranslateExceptionAction(
+ tabId = tabId,
+ operation = TranslationOperation.FETCH_NEVER_TRANSLATE_SITES,
+ translationError = TranslationError.CouldNotLoadNeverTranslateSites(it),
+ ),
+ )
+ }
logger.error("Error requesting never translate sites: ", it)
},
)
@@ -377,38 +413,23 @@ class TranslationsMiddleware(
* [TranslationsAction.TranslateExceptionAction].
*
* @param context Context to use to dispatch to the store.
- * @param tabId Tab ID associated with the request.
* @param origin A site origin URI that will have the specified never translate permission set.
*/
private fun removeNeverTranslateSite(
context: MiddlewareContext<BrowserState, BrowserAction>,
- tabId: String,
origin: String,
) {
engine.setNeverTranslateSpecifiedSite(
origin = origin,
setting = false,
onSuccess = {
- logger.info("Success requesting never translate sites.")
-
- // Fetch page settings to ensure the state matches the engine.
- context.store.dispatch(
- TranslationsAction.OperationRequestedAction(
- tabId = tabId,
- operation = TranslationOperation.FETCH_PAGE_SETTINGS,
- ),
- )
+ logger.info("Success changing never translate sites.")
},
onError = {
logger.error("Error removing site from never translate list: ", it)
-
- // Fetch never translate sites to ensure the state matches the engine.
- context.store.dispatch(
- TranslationsAction.OperationRequestedAction(
- tabId = tabId,
- operation = TranslationOperation.FETCH_NEVER_TRANSLATE_SITES,
- ),
- )
+ // Fetch never translate sites to ensure the state matches the engine, because it
+ // was proactively removed in the reducer.
+ requestNeverTranslateSites(context)
},
)
}
@@ -472,6 +493,38 @@ class TranslationsMiddleware(
}
/**
+ * Retrieves the setting to always offer to translate and dispatches the result to the
+ * store via [TranslationsAction.SetGlobalOfferTranslateSettingAction]. Will additionally
+ * dispatch a request to update page settings, when a [tabId] is provided.
+ *
+ * @param context Context to use to dispatch to the store.
+ * @param tabId Tab ID associated with the request.
+ */
+ private fun requestOfferSetting(
+ context: MiddlewareContext<BrowserState, BrowserAction>,
+ tabId: String? = null,
+ ) {
+ logger.info("Requesting offer setting.")
+ val alwaysOfferPopup: Boolean = engine.getTranslationsOfferPopup()
+
+ context.store.dispatch(
+ TranslationsAction.SetGlobalOfferTranslateSettingAction(
+ offerTranslation = alwaysOfferPopup,
+ ),
+ )
+
+ if (tabId != null) {
+ // Fetch page settings to ensure the state matches the engine.
+ context.store.dispatch(
+ TranslationsAction.OperationRequestedAction(
+ tabId = tabId,
+ operation = TranslationOperation.FETCH_PAGE_SETTINGS,
+ ),
+ )
+ }
+ }
+
+ /**
* Fetches the always or never language setting synchronously from the engine. Will
* return null if an error occurs.
*
@@ -708,8 +761,8 @@ class TranslationsMiddleware(
/**
* Updates the language settings with the [Engine].
*
- * If an error occurs, then the method will request the page settings be re-fetched and set on
- * the browser store.
+ * If an error occurs, and a [tabId] is known then the method will request the page settings be
+ * re-fetched and set on the browser store.
*
* @param context The context used to request the page settings.
* @param tabId Tab ID associated with the request.
@@ -718,7 +771,7 @@ class TranslationsMiddleware(
*/
private fun updateLanguageSetting(
context: MiddlewareContext<BrowserState, BrowserAction>,
- tabId: String,
+ tabId: String? = null,
languageCode: String,
setting: LanguageSetting,
) {
@@ -729,26 +782,37 @@ class TranslationsMiddleware(
languageSetting = setting,
onSuccess = {
- // Ensure the session's page settings remain in sync with this update.
- context.store.dispatch(
- TranslationsAction.OperationRequestedAction(
- tabId = tabId,
- operation = TranslationOperation.FETCH_AUTOMATIC_LANGUAGE_SETTINGS,
- ),
- )
+ // Value was proactively updated in [TranslationsStateReducer] for
+ // [TranslationsBrowserState.languageSettings]
+
+ if (tabId != null) {
+ // Ensure the session's page settings remain in sync with this update.
+ context.store.dispatch(
+ TranslationsAction.OperationRequestedAction(
+ tabId = tabId,
+ operation = TranslationOperation.FETCH_AUTOMATIC_LANGUAGE_SETTINGS,
+ ),
+ )
+ }
+
logger.info("Successfully updated the language preference.")
},
onError = {
logger.error("Could not update the language preference.", it)
+ // The browser store [TranslationsBrowserState.languageSettings] is out of sync,
+ // re-request to sync the state.
+ requestLanguageSettings(context, tabId)
- // Fetch page settings to ensure the state matches the engine.
- context.store.dispatch(
- TranslationsAction.OperationRequestedAction(
- tabId = tabId,
- operation = TranslationOperation.FETCH_PAGE_SETTINGS,
- ),
- )
+ if (tabId != null) {
+ // Fetch page settings to ensure the state matches the engine.
+ context.store.dispatch(
+ TranslationsAction.OperationRequestedAction(
+ tabId = tabId,
+ operation = TranslationOperation.FETCH_PAGE_SETTINGS,
+ ),
+ )
+ }
},
)
}
diff --git a/mobile/android/android-components/components/browser/state/src/main/java/mozilla/components/browser/state/ext/TabSessionState.kt b/mobile/android/android-components/components/browser/state/src/main/java/mozilla/components/browser/state/ext/TabSessionState.kt
new file mode 100644
index 0000000000..b0f1c2e9e9
--- /dev/null
+++ b/mobile/android/android-components/components/browser/state/src/main/java/mozilla/components/browser/state/ext/TabSessionState.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.browser.state.ext
+
+import mozilla.components.browser.state.state.TabSessionState
+
+/**
+ * Returns the URL of the [TabSessionState].
+ */
+fun TabSessionState.getUrl(): String? {
+ return if (this.readerState.active) {
+ this.readerState.activeUrl
+ } else {
+ this.content.url
+ }
+}
diff --git a/mobile/android/android-components/components/browser/state/src/main/java/mozilla/components/browser/state/reducer/TranslationsStateReducer.kt b/mobile/android/android-components/components/browser/state/src/main/java/mozilla/components/browser/state/reducer/TranslationsStateReducer.kt
index 266964455e..89c7ee3ed4 100644
--- a/mobile/android/android-components/components/browser/state/src/main/java/mozilla/components/browser/state/reducer/TranslationsStateReducer.kt
+++ b/mobile/android/android-components/components/browser/state/src/main/java/mozilla/components/browser/state/reducer/TranslationsStateReducer.kt
@@ -62,11 +62,8 @@ internal object TranslationsStateReducer {
}
// Checking for if the translations engine is in the fully translated state or not based
- // on the values of the translation pair.
- if (action.translationEngineState.requestedTranslationPair == null ||
- action.translationEngineState.requestedTranslationPair?.fromLanguage == null ||
- action.translationEngineState.requestedTranslationPair?.toLanguage == null
- ) {
+ // on if a visual change has occurred on the browser.
+ if (action.translationEngineState.hasVisibleChange != true) {
// In an untranslated state
var translationsError: TranslationError? = null
if (action.translationEngineState.detectedLanguages?.supportedDocumentLang == false) {
@@ -111,9 +108,9 @@ internal object TranslationsStateReducer {
is TranslationsAction.TranslateSuccessAction -> {
when (action.operation) {
TranslationOperation.TRANSLATE -> {
+ // The isTranslated state will be identified on a translation state change.
state.copyWithTranslationsState(action.tabId) {
it.copy(
- isTranslated = true,
isTranslateProcessing = false,
translationError = null,
)
@@ -163,6 +160,17 @@ internal object TranslationsStateReducer {
}
}
+ TranslationOperation.FETCH_OFFER_SETTING -> {
+ // Reset the error state, and then generally expect
+ // [TranslationsAction.SetGlobalOfferTranslateSettingAction] to update state in the
+ // success case.
+ state.copyWithTranslationsState(action.tabId) {
+ it.copy(
+ settingsError = null,
+ )
+ }
+ }
+
TranslationOperation.FETCH_AUTOMATIC_LANGUAGE_SETTINGS -> {
state.copy(
translationEngine = state.translationEngine.copy(
@@ -175,11 +183,11 @@ internal object TranslationsStateReducer {
// Reset the error state, and then generally expect
// [TranslationsAction.SetNeverTranslateSitesAction] to update
// state in the success case.
- state.copyWithTranslationsState(action.tabId) {
- it.copy(
+ state.copy(
+ translationEngine = state.translationEngine.copy(
neverTranslateSites = null,
- )
- }
+ ),
+ )
}
}
}
@@ -229,6 +237,14 @@ internal object TranslationsStateReducer {
}
}
+ TranslationOperation.FETCH_OFFER_SETTING -> {
+ state.copyWithTranslationsState(action.tabId) {
+ it.copy(
+ translationError = action.translationError,
+ )
+ }
+ }
+
TranslationOperation.FETCH_AUTOMATIC_LANGUAGE_SETTINGS -> {
state.copyWithTranslationsState(action.tabId) {
it.copy(
@@ -240,7 +256,6 @@ internal object TranslationsStateReducer {
TranslationOperation.FETCH_NEVER_TRANSLATE_SITES -> {
state.copyWithTranslationsState(action.tabId) {
it.copy(
- neverTranslateSites = null,
settingsError = action.translationError,
)
}
@@ -277,20 +292,20 @@ internal object TranslationsStateReducer {
}
is TranslationsAction.SetNeverTranslateSitesAction ->
- state.copyWithTranslationsState(action.tabId) {
- it.copy(
+ state.copy(
+ translationEngine = state.translationEngine.copy(
neverTranslateSites = action.neverTranslateSites,
- )
- }
+ ),
+ )
is TranslationsAction.RemoveNeverTranslateSiteAction -> {
- val neverTranslateSites = state.findTab(action.tabId)?.translationsState?.neverTranslateSites
+ val neverTranslateSites = state.translationEngine.neverTranslateSites
val updatedNeverTranslateSites = neverTranslateSites?.filter { it != action.origin }?.toList()
- state.copyWithTranslationsState(action.tabId) {
- it.copy(
+ state.copy(
+ translationEngine = state.translationEngine.copy(
neverTranslateSites = updatedNeverTranslateSites,
- )
- }
+ ),
+ )
}
is TranslationsAction.OperationRequestedAction ->
@@ -326,12 +341,20 @@ internal object TranslationsStateReducer {
}
}
+ TranslationOperation.FETCH_OFFER_SETTING -> {
+ state.copy(
+ translationEngine = state.translationEngine.copy(
+ offerTranslation = null,
+ ),
+ )
+ }
+
TranslationOperation.FETCH_NEVER_TRANSLATE_SITES -> {
- state.copyWithTranslationsState(action.tabId) {
- it.copy(
+ state.copy(
+ translationEngine = state.translationEngine.copy(
neverTranslateSites = null,
- )
- }
+ ),
+ )
}
TranslationOperation.TRANSLATE, TranslationOperation.RESTORE -> {
// No state change for these operations
@@ -400,6 +423,35 @@ internal object TranslationsStateReducer {
}
}
+ is TranslationsAction.UpdateLanguageSettingsAction -> {
+ val languageSettings = state.translationEngine.languageSettings?.toMutableMap()
+ // Only set when keys are present.
+ if (languageSettings?.get(action.languageCode) != null) {
+ languageSettings[action.languageCode] = action.setting
+ }
+ state.copy(
+ translationEngine = state.translationEngine.copy(
+ languageSettings = languageSettings,
+ ),
+ )
+ }
+
+ is TranslationsAction.SetGlobalOfferTranslateSettingAction -> {
+ state.copy(
+ translationEngine = state.translationEngine.copy(
+ offerTranslation = action.offerTranslation,
+ ),
+ )
+ }
+
+ is TranslationsAction.UpdateGlobalOfferTranslateSettingAction -> {
+ state.copy(
+ translationEngine = state.translationEngine.copy(
+ offerTranslation = action.offerTranslation,
+ ),
+ )
+ }
+
is TranslationsAction.SetEngineSupportedAction -> {
state.copy(
translationEngine = state.translationEngine.copy(
diff --git a/mobile/android/android-components/components/browser/state/src/main/java/mozilla/components/browser/state/state/TranslationsBrowserState.kt b/mobile/android/android-components/components/browser/state/src/main/java/mozilla/components/browser/state/state/TranslationsBrowserState.kt
index 2fb937f9f3..c34e1bc062 100644
--- a/mobile/android/android-components/components/browser/state/src/main/java/mozilla/components/browser/state/state/TranslationsBrowserState.kt
+++ b/mobile/android/android-components/components/browser/state/src/main/java/mozilla/components/browser/state/state/TranslationsBrowserState.kt
@@ -13,17 +13,21 @@ import mozilla.components.concept.engine.translate.TranslationSupport
* Value type that represents the state of the translations engine within a [BrowserState].
*
* @property isEngineSupported Whether the translations engine supports the device architecture.
+ * @property offerTranslation Whether to offer translations or not to the user.
* @property supportedLanguages Set of languages the translation engine supports.
* @property languageModels Set of language machine learning translation models the translation engine has available.
* @property languageSettings A map containing a key of BCP 47 language code and its
* [LanguageSetting] to represent the automatic language settings.
+ * @property neverTranslateSites List of sites the user has opted to never translate.
* @property engineError Holds the error state of the translations engine.
* See [TranslationsState.translationError] for session level errors.
*/
data class TranslationsBrowserState(
val isEngineSupported: Boolean? = null,
+ val offerTranslation: Boolean? = null,
val supportedLanguages: TranslationSupport? = null,
val languageModels: List<LanguageModel>? = null,
val languageSettings: Map<String, LanguageSetting>? = null,
+ val neverTranslateSites: List<String>? = null,
val engineError: TranslationError? = null,
)
diff --git a/mobile/android/android-components/components/browser/state/src/main/java/mozilla/components/browser/state/state/TranslationsState.kt b/mobile/android/android-components/components/browser/state/src/main/java/mozilla/components/browser/state/state/TranslationsState.kt
index 8c05340928..d70d6e1492 100644
--- a/mobile/android/android-components/components/browser/state/src/main/java/mozilla/components/browser/state/state/TranslationsState.kt
+++ b/mobile/android/android-components/components/browser/state/src/main/java/mozilla/components/browser/state/state/TranslationsState.kt
@@ -23,7 +23,6 @@ import mozilla.components.concept.engine.translate.TranslationPageSettings
* translation engine requires the pair's ML models to be present on the device to complete a
* translation.
* @property pageSettings The translation engine settings that relate to the current page.
- * @property neverTranslateSites List of sites the user has opted to never translate.
* @property translationError Type of error that occurred when acquiring resources, translating, or
* restoring a translation.
* @property settingsError Type of error that occurred when acquiring resources or setting preferences.
@@ -37,7 +36,6 @@ data class TranslationsState(
val isRestoreProcessing: Boolean = false,
val translationDownloadSize: TranslationDownloadSize? = null,
val pageSettings: TranslationPageSettings? = null,
- val neverTranslateSites: List<String>? = null,
val translationError: TranslationError? = null,
val settingsError: TranslationError? = null,
)
diff --git a/mobile/android/android-components/components/browser/state/src/test/java/mozilla/components/browser/state/action/TranslationsActionTest.kt b/mobile/android/android-components/components/browser/state/src/test/java/mozilla/components/browser/state/action/TranslationsActionTest.kt
index 2a12cda264..ecbbae9c61 100644
--- a/mobile/android/android-components/components/browser/state/src/test/java/mozilla/components/browser/state/action/TranslationsActionTest.kt
+++ b/mobile/android/android-components/components/browser/state/src/test/java/mozilla/components/browser/state/action/TranslationsActionTest.kt
@@ -95,6 +95,7 @@ class TranslationsActionTest {
error = null,
isEngineReady = true,
requestedTranslationPair = TranslationPair(fromLanguage = "es", toLanguage = "en"),
+ hasVisibleChange = true,
)
store.dispatch(TranslationsAction.TranslateStateChangeAction(tabId = tab.id, translationEngineState = translatedEngineState))
@@ -110,6 +111,7 @@ class TranslationsActionTest {
error = null,
isEngineReady = true,
requestedTranslationPair = TranslationPair(fromLanguage = null, toLanguage = null),
+ hasVisibleChange = false,
)
store.dispatch(TranslationsAction.TranslateStateChangeAction(tabId = tab.id, nonTranslatedEngineState))
@@ -264,7 +266,6 @@ class TranslationsActionTest {
store.dispatch(TranslationsAction.TranslateSuccessAction(tabId = tab.id, operation = TranslationOperation.TRANSLATE))
.joinBlocking()
assertEquals(false, tabState().translationsState.isTranslateProcessing)
- assertEquals(true, tabState().translationsState.isTranslated)
assertEquals(null, tabState().translationsState.translationError)
}
@@ -347,44 +348,41 @@ class TranslationsActionTest {
@Test
fun `WHEN a SetNeverTranslateSitesAction is dispatched AND successful THEN update neverTranslateSites`() {
// Initial
- assertEquals(null, tabState().translationsState.neverTranslateSites)
+ assertNull(store.state.translationEngine.neverTranslateSites)
// Action started
val neverTranslateSites = listOf("google.com")
store.dispatch(
TranslationsAction.SetNeverTranslateSitesAction(
- tabId = tab.id,
neverTranslateSites = neverTranslateSites,
),
).joinBlocking()
// Action success
- assertEquals(neverTranslateSites, tabState().translationsState.neverTranslateSites)
+ assertEquals(neverTranslateSites, store.state.translationEngine.neverTranslateSites)
}
@Test
fun `WHEN a RemoveNeverTranslateSiteAction is dispatched AND successful THEN update neverTranslateSites`() {
// Initial add to neverTranslateSites
- assertEquals(null, tabState().translationsState.neverTranslateSites)
+ assertNull(store.state.translationEngine.neverTranslateSites)
val neverTranslateSites = listOf("google.com")
store.dispatch(
TranslationsAction.SetNeverTranslateSitesAction(
- tabId = tab.id,
neverTranslateSites = neverTranslateSites,
),
).joinBlocking()
- assertEquals(neverTranslateSites, tabState().translationsState.neverTranslateSites)
+ assertEquals(neverTranslateSites, store.state.translationEngine.neverTranslateSites)
// Action started
store.dispatch(
TranslationsAction.RemoveNeverTranslateSiteAction(
- tabId = tab.id,
origin = "google.com",
),
).joinBlocking()
// Action success
- assertEquals(listOf<String>(), tabState().translationsState.neverTranslateSites)
+ assertEquals(listOf<String>(), store.state.translationEngine.neverTranslateSites)
}
@Test
@@ -451,7 +449,6 @@ class TranslationsActionTest {
),
).joinBlocking()
assertEquals(null, tabState().translationsState.translationError)
- assertEquals(true, tabState().translationsState.isTranslated)
assertEquals(false, tabState().translationsState.isTranslateProcessing)
// RESTORE usage
@@ -900,4 +897,88 @@ class TranslationsActionTest {
// Final state
assertEquals(languageModels, store.state.translationEngine.languageModels)
}
+
+ @Test
+ fun `WHEN SetOfferTranslateSettingAction is called then set offerToTranslate`() {
+ // Initial State
+ assertNull(store.state.translationEngine.offerTranslation)
+
+ // Action started
+ store.dispatch(
+ TranslationsAction.SetGlobalOfferTranslateSettingAction(
+ offerTranslation = false,
+ ),
+ ).joinBlocking()
+
+ // Action success
+ assertFalse(store.state.translationEngine.offerTranslation!!)
+ }
+
+ @Test
+ fun `WHEN UpdateOfferTranslateSettingAction is called then set offerToTranslate`() {
+ // Initial State
+ assertNull(store.state.translationEngine.offerTranslation)
+
+ // Action started
+ store.dispatch(
+ TranslationsAction.UpdateGlobalOfferTranslateSettingAction(
+ offerTranslation = false,
+ ),
+ ).joinBlocking()
+
+ // Action success
+ assertFalse(store.state.translationEngine.offerTranslation!!)
+ }
+
+ @Test
+ fun `WHEN UpdateGlobalLanguageSettingAction is called then update languageSettings`() {
+ // Initial State
+ assertNull(store.state.translationEngine.languageSettings)
+
+ // No-op null test
+ store.dispatch(
+ TranslationsAction.UpdateLanguageSettingsAction(
+ languageCode = "fr",
+ setting = LanguageSetting.ALWAYS,
+ ),
+ ).joinBlocking()
+
+ assertNull(store.state.translationEngine.languageSettings)
+
+ // Setting Initial State
+ val languageSettings = mapOf<String, LanguageSetting>(
+ "en" to LanguageSetting.OFFER,
+ "es" to LanguageSetting.NEVER,
+ "de" to LanguageSetting.ALWAYS,
+ )
+
+ store.dispatch(
+ TranslationsAction.SetLanguageSettingsAction(
+ languageSettings = languageSettings,
+ ),
+ ).joinBlocking()
+
+ assertEquals(languageSettings, store.state.translationEngine.languageSettings)
+
+ // No-op update test
+ store.dispatch(
+ TranslationsAction.UpdateLanguageSettingsAction(
+ languageCode = "fr",
+ setting = LanguageSetting.ALWAYS,
+ ),
+ ).joinBlocking()
+
+ assertEquals(languageSettings, store.state.translationEngine.languageSettings)
+
+ // Main action started
+ store.dispatch(
+ TranslationsAction.UpdateLanguageSettingsAction(
+ languageCode = "es",
+ setting = LanguageSetting.ALWAYS,
+ ),
+ ).joinBlocking()
+
+ // Action success
+ assertEquals(LanguageSetting.ALWAYS, store.state.translationEngine.languageSettings!!["es"])
+ }
}
diff --git a/mobile/android/android-components/components/browser/state/src/test/java/mozilla/components/browser/state/engine/middleware/EngineDelegateMiddlewareTest.kt b/mobile/android/android-components/components/browser/state/src/test/java/mozilla/components/browser/state/engine/middleware/EngineDelegateMiddlewareTest.kt
index 5eaeb328ee..13365b57a7 100644
--- a/mobile/android/android-components/components/browser/state/src/test/java/mozilla/components/browser/state/engine/middleware/EngineDelegateMiddlewareTest.kt
+++ b/mobile/android/android-components/components/browser/state/src/test/java/mozilla/components/browser/state/engine/middleware/EngineDelegateMiddlewareTest.kt
@@ -263,6 +263,7 @@ class EngineDelegateMiddlewareTest {
EngineAction.LoadUrlAction(
"test-tab",
"https://www.firefox.com",
+ includeParent = true,
),
).joinBlocking()
diff --git a/mobile/android/android-components/components/browser/state/src/test/java/mozilla/components/browser/state/engine/middleware/LinkingMiddlewareTest.kt b/mobile/android/android-components/components/browser/state/src/test/java/mozilla/components/browser/state/engine/middleware/LinkingMiddlewareTest.kt
index 89939b71a2..c24f838c02 100644
--- a/mobile/android/android-components/components/browser/state/src/test/java/mozilla/components/browser/state/engine/middleware/LinkingMiddlewareTest.kt
+++ b/mobile/android/android-components/components/browser/state/src/test/java/mozilla/components/browser/state/engine/middleware/LinkingMiddlewareTest.kt
@@ -96,7 +96,9 @@ class LinkingMiddlewareTest {
store.dispatch(EngineAction.LinkEngineSessionAction(parent.id, parentEngineSession)).joinBlocking()
val childEngineSession: EngineSession = mock()
- store.dispatch(EngineAction.LinkEngineSessionAction(child.id, childEngineSession)).joinBlocking()
+ store.dispatch(
+ EngineAction.LinkEngineSessionAction(child.id, childEngineSession, includeParent = true),
+ ).joinBlocking()
dispatcher.scheduler.advanceUntilIdle()
diff --git a/mobile/android/android-components/components/browser/state/src/test/java/mozilla/components/browser/state/engine/middleware/TranslationsMiddlewareTest.kt b/mobile/android/android-components/components/browser/state/src/test/java/mozilla/components/browser/state/engine/middleware/TranslationsMiddlewareTest.kt
index cf30f7060e..dadc88de52 100644
--- a/mobile/android/android-components/components/browser/state/src/test/java/mozilla/components/browser/state/engine/middleware/TranslationsMiddlewareTest.kt
+++ b/mobile/android/android-components/components/browser/state/src/test/java/mozilla/components/browser/state/engine/middleware/TranslationsMiddlewareTest.kt
@@ -327,6 +327,35 @@ class TranslationsMiddlewareTest {
}
@Test
+ fun `WHEN InitTranslationsBrowserState is dispatched AND the engine is supported THEN SetNeverTranslateSitesAction is also dispatched`() = runTest {
+ // Send Action
+ translationsMiddleware.invoke(context = context, next = {}, action = TranslationsAction.InitTranslationsBrowserState)
+
+ // Set the engine to support
+ val engineSupportedCallback = argumentCaptor<((Boolean) -> Unit)>()
+ // At least once, since InitAction also will trigger this
+ verify(engine, atLeastOnce()).isTranslationsEngineSupported(
+ onSuccess = engineSupportedCallback.capture(),
+ onError = any(),
+ )
+ engineSupportedCallback.value.invoke(true)
+
+ val neverTranslateSitesCallBack = argumentCaptor<((List<String>) -> Unit)>()
+ verify(engine, atLeastOnce()).getNeverTranslateSiteList(onSuccess = neverTranslateSitesCallBack.capture(), onError = any())
+ val mockNeverTranslate = listOf("www.mozilla.org")
+ neverTranslateSitesCallBack.value.invoke(mockNeverTranslate)
+
+ waitForIdle()
+
+ // Verifying at least once
+ verify(store, atLeastOnce()).dispatch(
+ TranslationsAction.SetNeverTranslateSitesAction(
+ neverTranslateSites = mockNeverTranslate,
+ ),
+ )
+ }
+
+ @Test
fun `WHEN InitTranslationsBrowserState is dispatched AND has an issue with the engine THEN EngineExceptionAction is dispatched`() = runTest() {
// Send Action
// Note: Implicitly called once due to connection with InitAction
@@ -726,7 +755,6 @@ class TranslationsMiddlewareTest {
verify(context.store).dispatch(
TranslationsAction.SetNeverTranslateSitesAction(
- tabId = tab.id,
neverTranslateSites = neverTranslateSites,
),
)
@@ -825,7 +853,7 @@ class TranslationsMiddlewareTest {
}
@Test
- fun `WHEN RemoveNeverTranslateSiteAction is dispatched AND removing is unsuccessful THEN FETCH_NEVER_TRANSLATE_SITES is dispatched`() = runTest {
+ fun `WHEN RemoveNeverTranslateSiteAction is dispatched AND removing is unsuccessful THEN SetNeverTranslateSitesAction is dispatched`() = runTest {
val errorCallback = argumentCaptor<((Throwable) -> Unit)>()
whenever(
engine.setNeverTranslateSpecifiedSite(
@@ -838,45 +866,20 @@ class TranslationsMiddlewareTest {
val action =
TranslationsAction.RemoveNeverTranslateSiteAction(
- tabId = tab.id,
origin = "google.com",
)
translationsMiddleware.invoke(context, {}, action)
waitForIdle()
- // Verify Dispatch
- verify(store).dispatch(
- TranslationsAction.OperationRequestedAction(
- tabId = tab.id,
- operation = TranslationOperation.FETCH_NEVER_TRANSLATE_SITES,
- ),
- )
- waitForIdle()
- }
-
- @Test
- fun `WHEN RemoveNeverTranslateSiteAction is dispatched AND removing is successful THEN FETCH_PAGE_SETTINGS is dispatched`() = runTest {
- val sitesCallback = argumentCaptor<(() -> Unit)>()
- val action =
- TranslationsAction.RemoveNeverTranslateSiteAction(
- tabId = tab.id,
- origin = "google.com",
- )
- translationsMiddleware.invoke(context, {}, action)
- verify(engine).setNeverTranslateSpecifiedSite(
- origin = any(),
- setting = anyBoolean(),
- onSuccess = sitesCallback.capture(),
- onError = any(),
- )
- sitesCallback.value.invoke()
- waitForIdle()
+ val neverTranslateSitesCallBack = argumentCaptor<((List<String>) -> Unit)>()
+ verify(engine, atLeastOnce()).getNeverTranslateSiteList(onSuccess = neverTranslateSitesCallBack.capture(), onError = any())
+ val mockNeverTranslate = listOf("www.mozilla.org")
+ neverTranslateSitesCallBack.value.invoke(mockNeverTranslate)
// Verify Dispatch
verify(store).dispatch(
- TranslationsAction.OperationRequestedAction(
- tabId = tab.id,
- operation = TranslationOperation.FETCH_PAGE_SETTINGS,
+ TranslationsAction.SetNeverTranslateSitesAction(
+ neverTranslateSites = mockNeverTranslate,
),
)
waitForIdle()
@@ -942,4 +945,116 @@ class TranslationsMiddlewareTest {
waitForIdle()
}
+
+ @Test
+ fun `WHEN InitTranslationsBrowserState is dispatched AND the engine is supported THEN SetOfferTranslateSettingAction is also dispatched`() = runTest {
+ // Send Action
+ translationsMiddleware.invoke(context = context, next = {}, action = TranslationsAction.InitTranslationsBrowserState)
+
+ // Set the engine to support
+ val engineSupportedCallback = argumentCaptor<((Boolean) -> Unit)>()
+ // At least once, since InitAction also will trigger this
+ verify(engine, atLeastOnce()).isTranslationsEngineSupported(
+ onSuccess = engineSupportedCallback.capture(),
+ onError = any(),
+ )
+ engineSupportedCallback.value.invoke(true)
+
+ // Verify results for offer
+ verify(engine, atLeastOnce()).getTranslationsOfferPopup()
+ waitForIdle()
+
+ // Verifying at least once
+ verify(store, atLeastOnce()).dispatch(
+ TranslationsAction.SetGlobalOfferTranslateSettingAction(
+ offerTranslation = false,
+ ),
+ )
+
+ waitForIdle()
+ }
+
+ @Test
+ fun `WHEN FETCH_OFFER_SETTING is dispatched with a tab id THEN SetOfferTranslateSettingAction and SetPageSettingsAction are also dispatched`() = runTest {
+ // Set the mock offer value
+ whenever(
+ engine.getTranslationsOfferPopup(),
+ ).thenAnswer { true }
+
+ // Send Action
+ val action =
+ TranslationsAction.OperationRequestedAction(
+ tabId = tab.id,
+ operation = TranslationOperation.FETCH_OFFER_SETTING,
+ )
+ translationsMiddleware.invoke(context, {}, action)
+ waitForIdle()
+
+ // Verify Dispatch
+ verify(store, atLeastOnce()).dispatch(
+ TranslationsAction.SetGlobalOfferTranslateSettingAction(
+ offerTranslation = true,
+ ),
+ )
+
+ // Since we had a tabId, this call will also happen
+ verify(store, atLeastOnce()).dispatch(
+ TranslationsAction.SetPageSettingsAction(
+ tabId = tab.id,
+ pageSettings = any(),
+ ),
+ )
+
+ waitForIdle()
+ }
+
+ @Test
+ fun `WHEN UpdateOfferTranslateSettingAction is called then setTranslationsOfferPopup is called on the engine`() = runTest {
+ // Send Action
+ val action =
+ TranslationsAction.UpdateGlobalOfferTranslateSettingAction(
+ offerTranslation = true,
+ )
+ translationsMiddleware.invoke(context, {}, action)
+ waitForIdle()
+
+ // Verify offer was set
+ verify(engine, atLeastOnce()).setTranslationsOfferPopup(offer = true)
+ waitForIdle()
+ }
+
+ @Test
+ fun `WHEN UpdateLanguageSettingsAction is dispatched and fails THEN SetLanguageSettingsAction is dispatched`() = runTest {
+ // Send Action
+ val action =
+ TranslationsAction.UpdateLanguageSettingsAction(
+ languageCode = "es",
+ setting = LanguageSetting.ALWAYS,
+ )
+ translationsMiddleware.invoke(context, {}, action)
+
+ waitForIdle()
+
+ // Mock engine error
+ val updateLanguagesErrorCallback = argumentCaptor<((Throwable) -> Unit)>()
+ verify(engine).setLanguageSetting(
+ languageCode = any(),
+ languageSetting = any(),
+ onSuccess = any(),
+ onError = updateLanguagesErrorCallback.capture(),
+ )
+ updateLanguagesErrorCallback.value.invoke(Throwable())
+
+ waitForIdle()
+
+ // Verify Dispatch
+ val languageSettingsCallback = argumentCaptor<((Map<String, LanguageSetting>) -> Unit)>()
+ verify(engine, atLeastOnce()).getLanguageSettings(
+ onSuccess = languageSettingsCallback.capture(),
+ onError = any(),
+ )
+ val mockLanguageSetting = mapOf("en" to LanguageSetting.OFFER)
+ languageSettingsCallback.value.invoke(mockLanguageSetting)
+ waitForIdle()
+ }
}
diff --git a/mobile/android/android-components/components/browser/state/src/test/java/mozilla/components/browser/state/ext/TabSessionStateTest.kt b/mobile/android/android-components/components/browser/state/src/test/java/mozilla/components/browser/state/ext/TabSessionStateTest.kt
new file mode 100644
index 0000000000..1202afb1c6
--- /dev/null
+++ b/mobile/android/android-components/components/browser/state/src/test/java/mozilla/components/browser/state/ext/TabSessionStateTest.kt
@@ -0,0 +1,34 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+package mozilla.components.browser.state.ext
+
+import mozilla.components.browser.state.state.ReaderState
+import mozilla.components.browser.state.state.createTab
+import org.junit.Assert.assertEquals
+import org.junit.Test
+
+class TabSessionStateTest {
+
+ @Test
+ fun `GIVEN reader mode is active WHEN get url extension property is fetched THEN return the active url`() {
+ val readerUrl = "moz-extension://1234"
+ val activeUrl = "https://mozilla.org"
+ val readerTab = createTab(
+ url = readerUrl,
+ readerState = ReaderState(active = true, activeUrl = activeUrl),
+ title = "Mozilla",
+ )
+
+ assertEquals(activeUrl, readerTab.getUrl())
+ }
+
+ @Test
+ fun `WHEN get url extension property is fetched THEN return the content url`() {
+ val url = "https://mozilla.org"
+ val tab = createTab(url = url)
+
+ assertEquals(url, tab.getUrl())
+ }
+}
diff --git a/mobile/android/android-components/components/browser/toolbar/src/main/res/values-nb-rNO/strings.xml b/mobile/android/android-components/components/browser/toolbar/src/main/res/values-nb-rNO/strings.xml
index f9cb99c55d..9d9bcbfc13 100644
--- a/mobile/android/android-components/components/browser/toolbar/src/main/res/values-nb-rNO/strings.xml
+++ b/mobile/android/android-components/components/browser/toolbar/src/main/res/values-nb-rNO/strings.xml
@@ -2,6 +2,7 @@
<resources>
<!-- Content description (not visible, for screen readers etc.): Description for the overflow menu button in the browser toolbar. -->
<string name="mozac_browser_toolbar_menu_button">Meny</string>
+ <!-- Content description: For the clear URL text button. -->
<string name="mozac_clear_button_description">Tøm</string>
<!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection enabled, but none trackers have been blocked or detected. -->
<string name="mozac_browser_toolbar_content_description_tracking_protection_on_no_trackers_blocked">Sporingsbeskyttelse er på</string>
@@ -14,5 +15,5 @@
<!-- Announcement made by the screen reader when the progress bar is shown and a page is loading -->
<string name="mozac_browser_toolbar_progress_loading">Laster</string>
<!-- Content description: For the autoplay toolbar icon, it is set when the auto play permission is blocking content playing.-->
- <string name="mozac_browser_toolbar_content_description_autoplay_blocked">Noe av innholdet er blokkert av autoavspillings-innstillingene </string>
+ <string name="mozac_browser_toolbar_content_description_autoplay_blocked">Noe av innholdet er blokkert av autoavspillings-innstillingene</string>
</resources>
diff --git a/mobile/android/android-components/components/browser/toolbar/src/main/res/values-sc/strings.xml b/mobile/android/android-components/components/browser/toolbar/src/main/res/values-sc/strings.xml
index 5194a4765e..f0b375f172 100644
--- a/mobile/android/android-components/components/browser/toolbar/src/main/res/values-sc/strings.xml
+++ b/mobile/android/android-components/components/browser/toolbar/src/main/res/values-sc/strings.xml
@@ -2,6 +2,7 @@
<resources>
<!-- Content description (not visible, for screen readers etc.): Description for the overflow menu button in the browser toolbar. -->
<string name="mozac_browser_toolbar_menu_button">Menù</string>
+ <!-- Content description: For the clear URL text button. -->
<string name="mozac_clear_button_description">Isbòida</string>
<!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection enabled, but none trackers have been blocked or detected. -->
<string name="mozac_browser_toolbar_content_description_tracking_protection_on_no_trackers_blocked">S’amparu contra sa sighidura est ativu</string>
@@ -13,4 +14,6 @@
<string name="mozac_browser_toolbar_content_description_site_info">Informatziones de su situ</string>
<!-- Announcement made by the screen reader when the progress bar is shown and a page is loading -->
<string name="mozac_browser_toolbar_progress_loading">Carrighende</string>
- </resources>
+ <!-- Content description: For the autoplay toolbar icon, it is set when the auto play permission is blocking content playing.-->
+ <string name="mozac_browser_toolbar_content_description_autoplay_blocked">Sa funtzionalidade de riprodutzione automàtica at blocadu cuntenutos</string>
+</resources>
diff --git a/mobile/android/android-components/components/browser/toolbar/src/main/res/values/strings.xml b/mobile/android/android-components/components/browser/toolbar/src/main/res/values/strings.xml
index 3c2d7dcf1b..c845e189e7 100644
--- a/mobile/android/android-components/components/browser/toolbar/src/main/res/values/strings.xml
+++ b/mobile/android/android-components/components/browser/toolbar/src/main/res/values/strings.xml
@@ -5,6 +5,7 @@
<resources>
<!-- Content description (not visible, for screen readers etc.): Description for the overflow menu button in the browser toolbar. -->
<string name="mozac_browser_toolbar_menu_button">Menu</string>
+ <!-- Content description: For the clear URL text button. -->
<string name="mozac_clear_button_description">Clear</string>
<!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection enabled, but none trackers have been blocked or detected. -->
<string name="mozac_browser_toolbar_content_description_tracking_protection_on_no_trackers_blocked">Tracking Protection is on</string>
diff --git a/mobile/android/android-components/components/browser/toolbar2/README.md b/mobile/android/android-components/components/browser/toolbar2/README.md
new file mode 100644
index 0000000000..a0cfe1d6ce
--- /dev/null
+++ b/mobile/android/android-components/components/browser/toolbar2/README.md
@@ -0,0 +1,37 @@
+# [Android Components](../../../README.md) > Browser > Toolbar2
+
+A customizable toolbar for browsers.
+
+## Usage
+
+### Setting up the dependency
+
+Use Gradle to download the library from [maven.mozilla.org](https://maven.mozilla.org/) ([Setup repository](../../../README.md#maven-repository)):
+
+```Groovy
+implementation "org.mozilla.components:browser-toolbar2:{latest-version}"
+```
+
+## Facts
+
+This component emits the following [Facts](../../support/base/README.md#Facts):
+
+| Action | Item | Extras | Description |
+|--------|---------|----------------|------------------------------------|
+| CLICK | menu | `menuExtras` | The user opened the overflow menu. |
+| COMMIT | toolbar | `commitExtras` | The user has edited the URL. |
+
+`menuExtras` are additional extras set on the `BrowserMenuBuilder` passed to the `BrowserToolbar` (see [browser-menu](../menu/README.md)).
+
+#### `commitExtras`
+
+| Key | Type | Value |
+|--------------|---------|-----------------------------------|
+| autocomplete | Boolean | Whether the URL was autocompleted |
+| source | String? | Which autocomplete list was used |
+
+## License
+
+ This Source Code Form is subject to the terms of the Mozilla Public
+ License, v. 2.0. If a copy of the MPL was not distributed with this
+ file, You can obtain one at http://mozilla.org/MPL/2.0/
diff --git a/mobile/android/android-components/components/browser/toolbar2/build.gradle b/mobile/android/android-components/components/browser/toolbar2/build.gradle
new file mode 100644
index 0000000000..60d3930430
--- /dev/null
+++ b/mobile/android/android-components/components/browser/toolbar2/build.gradle
@@ -0,0 +1,56 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+apply plugin: 'com.android.library'
+apply plugin: 'kotlin-android'
+
+android {
+ defaultConfig {
+ minSdkVersion config.minSdkVersion
+ compileSdk config.compileSdkVersion
+ targetSdkVersion config.targetSdkVersion
+ }
+
+ buildTypes {
+ release {
+ minifyEnabled false
+ proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
+ }
+ }
+
+ namespace 'mozilla.components.browser.toolbar2'
+}
+
+dependencies {
+ api project(':concept-toolbar')
+ api project(':ui-autocomplete')
+ api project(':support-base')
+
+ implementation project(':concept-engine')
+ implementation project(':concept-menu')
+ implementation project(':browser-menu')
+ implementation project(':browser-menu2')
+ implementation project(':ui-icons')
+ implementation project(':ui-colors')
+ implementation project(':ui-widgets')
+ implementation project(':support-ktx')
+
+ implementation ComponentsDependencies.androidx_appcompat
+ implementation ComponentsDependencies.androidx_constraintlayout
+ implementation ComponentsDependencies.androidx_core_ktx
+ implementation ComponentsDependencies.google_material
+
+ implementation ComponentsDependencies.kotlin_coroutines
+
+ testImplementation project(':support-test')
+
+ testImplementation ComponentsDependencies.androidx_test_core
+ testImplementation ComponentsDependencies.androidx_test_junit
+ testImplementation ComponentsDependencies.testing_robolectric
+ testImplementation ComponentsDependencies.testing_coroutines
+}
+
+apply from: '../../../android-lint.gradle'
+apply from: '../../../publish.gradle'
+ext.configurePublish(config.componentsGroupId, archivesBaseName, project.ext.description)
diff --git a/mobile/android/android-components/components/browser/toolbar2/proguard-rules.pro b/mobile/android/android-components/components/browser/toolbar2/proguard-rules.pro
new file mode 100644
index 0000000000..f1b424510d
--- /dev/null
+++ b/mobile/android/android-components/components/browser/toolbar2/proguard-rules.pro
@@ -0,0 +1,21 @@
+# Add project specific ProGuard rules here.
+# You can control the set of applied configuration files using the
+# proguardFiles setting in build.gradle.
+#
+# For more details, see
+# http://developer.android.com/guide/developing/tools/proguard.html
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+# public *;
+#}
+
+# Uncomment this to preserve the line number information for
+# debugging stack traces.
+#-keepattributes SourceFile,LineNumberTable
+
+# If you keep the line number information, uncomment this to
+# hide the original source file name.
+#-renamesourcefileattribute SourceFile
diff --git a/mobile/android/android-components/components/browser/toolbar2/src/main/AndroidManifest.xml b/mobile/android/android-components/components/browser/toolbar2/src/main/AndroidManifest.xml
new file mode 100644
index 0000000000..e16cda1d34
--- /dev/null
+++ b/mobile/android/android-components/components/browser/toolbar2/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/browser/toolbar2/src/main/java/mozilla/components/browser/toolbar2/BrowserToolbar.kt b/mobile/android/android-components/components/browser/toolbar2/src/main/java/mozilla/components/browser/toolbar2/BrowserToolbar.kt
new file mode 100644
index 0000000000..e740455385
--- /dev/null
+++ b/mobile/android/android-components/components/browser/toolbar2/src/main/java/mozilla/components/browser/toolbar2/BrowserToolbar.kt
@@ -0,0 +1,691 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.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.browser.toolbar2
+
+import android.content.Context
+import android.graphics.drawable.Drawable
+import android.util.AttributeSet
+import android.view.LayoutInflater
+import android.view.View
+import android.view.View.NO_ID
+import android.view.ViewGroup
+import android.widget.ImageButton
+import android.widget.ImageView
+import androidx.annotation.ColorRes
+import androidx.annotation.DrawableRes
+import androidx.annotation.VisibleForTesting
+import androidx.annotation.VisibleForTesting.Companion.PRIVATE
+import androidx.coordinatorlayout.widget.CoordinatorLayout
+import androidx.core.content.ContextCompat
+import androidx.core.view.forEach
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.cancelChildren
+import kotlinx.coroutines.isActive
+import kotlinx.coroutines.launch
+import mozilla.components.browser.toolbar2.display.DisplayToolbar
+import mozilla.components.browser.toolbar2.edit.EditToolbar
+import mozilla.components.concept.toolbar.AutocompleteDelegate
+import mozilla.components.concept.toolbar.AutocompleteResult
+import mozilla.components.concept.toolbar.Toolbar
+import mozilla.components.concept.toolbar.Toolbar.Highlight
+import mozilla.components.support.base.android.Padding
+import mozilla.components.support.base.log.logger.Logger
+import mozilla.components.support.ktx.kotlin.trimmed
+import mozilla.components.ui.autocomplete.AutocompleteView
+import mozilla.components.ui.autocomplete.InlineAutocompleteEditText
+import mozilla.components.ui.autocomplete.OnFilterListener
+import mozilla.components.ui.widgets.behavior.EngineViewScrollingBehavior
+import kotlin.coroutines.CoroutineContext
+
+internal fun ImageView.setTintResource(@ColorRes tintColorResource: Int) {
+ if (tintColorResource != NO_ID) {
+ imageTintList = ContextCompat.getColorStateList(context, tintColorResource)
+ }
+}
+
+/**
+ * A customizable toolbar for browsers.
+ *
+ * The toolbar can switch between two modes: display and edit. The display mode displays the current
+ * URL and controls for navigation. In edit mode the current URL can be edited. Those two modes are
+ * implemented by the DisplayToolbar and EditToolbar classes.
+ *
+ * ```
+ * +----------------+
+ * | BrowserToolbar |
+ * +--------+-------+
+ * +
+ * +-------+-------+
+ * | |
+ * +---------v------+ +-------v--------+
+ * | DisplayToolbar | | EditToolbar |
+ * +----------------+ +----------------+
+ * ```
+ */
+@Suppress("TooManyFunctions")
+class BrowserToolbar @JvmOverloads constructor(
+ context: Context,
+ attrs: AttributeSet? = null,
+ defStyleAttr: Int = 0,
+) : ViewGroup(context, attrs, defStyleAttr), Toolbar {
+ private var state: State = State.DISPLAY
+
+ @VisibleForTesting
+ internal var searchTerms: String = ""
+ private var urlCommitListener: ((String) -> Boolean)? = null
+ var isNavBarEnabled: Boolean = false
+
+ /**
+ * Toolbar in "display mode".
+ */
+ var display = DisplayToolbar(
+ context,
+ this,
+ LayoutInflater.from(context).inflate(
+ R.layout.mozac_browser_toolbar_displaytoolbar,
+ this,
+ false,
+ ),
+ )
+ @VisibleForTesting(otherwise = PRIVATE)
+ internal set
+
+ /**
+ * Toolbar in "edit mode".
+ */
+ var edit = EditToolbar(
+ context,
+ this,
+ LayoutInflater.from(context).inflate(
+ R.layout.mozac_browser_toolbar_edittoolbar,
+ this,
+ false,
+ ),
+ )
+ @VisibleForTesting(otherwise = PRIVATE)
+ internal set
+
+ override var title: String
+ get() = display.title
+ set(value) { display.title = value }
+
+ override var url: CharSequence
+ get() = display.url.toString()
+ set(value) {
+ // We update the display toolbar immediately. We do not do that for the edit toolbar to not
+ // mess with what the user is entering. Instead we will remember the value and update the
+ // edit toolbar whenever we switch to it.
+ display.url = (value as String).trimmed()
+ }
+
+ override var siteSecure: Toolbar.SiteSecurity
+ get() = display.siteSecurity
+ set(value) { display.siteSecurity = value }
+
+ override var highlight: Highlight = Highlight.NONE
+ set(value) {
+ if (field != value) {
+ display.setHighlight(value)
+ field = value
+ }
+ }
+
+ override var siteTrackingProtection: Toolbar.SiteTrackingProtection =
+ Toolbar.SiteTrackingProtection.OFF_GLOBALLY
+ set(value) {
+ if (field != value) {
+ display.setTrackingProtectionState(value)
+ field = value
+ }
+ }
+
+ override var private: Boolean
+ get() = edit.private
+ set(value) { edit.private = value }
+
+ /**
+ * Registers the given listener to be invoked when the user edits the URL.
+ */
+ override fun setOnEditListener(listener: Toolbar.OnEditListener) {
+ edit.editListener = listener
+ }
+
+ /**
+ * Registers the given function to be invoked when users changes text in the toolbar.
+ *
+ * @param filter A function which will perform autocompletion and send results to [AutocompleteDelegate].
+ */
+ override fun setAutocompleteListener(filter: suspend (String, AutocompleteDelegate) -> Unit) {
+ // Our 'filter' knows how to autocomplete, and the 'urlView' knows how to apply results of
+ // autocompletion. Which gives us a lovely delegate chain!
+ // urlView decides when it's appropriate to ask for autocompletion, and in turn we invoke
+ // our 'filter' and send results back to 'urlView'.
+ edit.setAutocompleteListener(filter)
+ }
+
+ override fun refreshAutocomplete() {
+ edit.refreshAutocompleteSuggestion()
+ }
+
+ init {
+ addView(display.rootView)
+ addView(edit.rootView)
+
+ updateState(State.DISPLAY)
+ }
+
+ // We layout the toolbar ourselves to avoid the overhead from using complex ViewGroup implementations
+ override fun onLayout(changed: Boolean, left: Int, top: Int, right: Int, bottom: Int) {
+ forEach { child ->
+ child.layout(
+ 0 + paddingLeft,
+ 0 + paddingTop,
+ paddingLeft + child.measuredWidth,
+ paddingTop + child.measuredHeight,
+ )
+ }
+ }
+
+ // We measure the views manually to avoid overhead by using complex ViewGroup implementations
+ override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
+ // Our toolbar will always use the full width and a fixed height (default) or the provided
+ // height if it's an exact value.
+ val width = MeasureSpec.getSize(widthMeasureSpec)
+ val height = if (MeasureSpec.getMode(heightMeasureSpec) == MeasureSpec.EXACTLY) {
+ MeasureSpec.getSize(heightMeasureSpec)
+ } else {
+ resources.getDimensionPixelSize(R.dimen.mozac_browser_toolbar_default_toolbar_height)
+ }
+
+ setMeasuredDimension(width, height)
+
+ // Let the children measure themselves using our fixed size (with padding subtracted)
+ val childWidth = width - paddingLeft - paddingRight
+ val childHeight = height - paddingTop - paddingBottom
+
+ val childWidthSpec = MeasureSpec.makeMeasureSpec(childWidth, MeasureSpec.EXACTLY)
+ val childHeightSpec = MeasureSpec.makeMeasureSpec(childHeight, MeasureSpec.EXACTLY)
+
+ forEach { child -> child.measure(childWidthSpec, childHeightSpec) }
+ }
+
+ override fun onBackPressed(): Boolean {
+ if (state == State.EDIT) {
+ displayMode()
+ return true
+ }
+ return false
+ }
+
+ override fun onStop() {
+ display.onStop()
+ }
+
+ override fun setSearchTerms(searchTerms: String) {
+ this.searchTerms = searchTerms.trimmed()
+
+ if (state == State.EDIT) {
+ edit.editSuggestion(this.searchTerms)
+ }
+ }
+
+ override fun displayProgress(progress: Int) {
+ display.updateProgress(progress)
+ }
+
+ override fun setOnUrlCommitListener(listener: (String) -> Boolean) {
+ this.urlCommitListener = listener
+ }
+
+ /**
+ * Declare that the actions (navigation actions, browser actions, page actions) have changed and
+ * should be updated if needed.
+ *
+ * The toolbar will call the <code>visible</code> lambda of every action to determine whether a
+ * view for this action should be added or removed. Additionally <code>bind</code> will be
+ * called on every visible action to update its view.
+ */
+ override fun invalidateActions() {
+ display.invalidateActions()
+ edit.invalidateActions()
+ }
+
+ /**
+ * Adds an action to be displayed on the right side of the toolbar (outside of the URL bounding
+ * box) in display mode.
+ *
+ * If there is not enough room to show all icons then some icons may be moved to an overflow
+ * menu.
+ *
+ * Related:
+ * https://developer.mozilla.org/en-US/Add-ons/WebExtensions/user_interface/Browser_action
+ */
+ override fun addBrowserAction(action: Toolbar.Action) {
+ display.addBrowserAction(action)
+ }
+
+ /**
+ * Removes a previously added browser action (see [addBrowserAction]). If the provided
+ * action was never added, this method has no effect.
+ *
+ * @param action the action to remove.
+ */
+ override fun removeBrowserAction(action: Toolbar.Action) {
+ display.removeBrowserAction(action)
+ }
+
+ /**
+ * Removes a previously added page action (see [addPageAction]). If the provided
+ * action was never added, this method has no effect.
+ *
+ * @param action the action to remove.
+ */
+ override fun removePageAction(action: Toolbar.Action) {
+ display.removePageAction(action)
+ }
+
+ /**
+ * Adds an action to be displayed on the right side of the URL in display mode.
+ *
+ * Related:
+ * https://developer.mozilla.org/en-US/Add-ons/WebExtensions/user_interface/Page_actions
+ */
+ override fun addPageAction(action: Toolbar.Action) {
+ display.addPageAction(action)
+ }
+
+ /**
+ * Adds an action to be display on the far left side of the toolbar. This area is usually used
+ * on larger devices for navigation actions like "back" and "forward".
+ */
+ override fun addNavigationAction(action: Toolbar.Action) {
+ display.addNavigationAction(action)
+ }
+
+ /**
+ * Removes a previously added navigation action (see [addNavigationAction]). If the provided
+ * action was never added, this method has no effect.
+ *
+ * @param action the action to remove.
+ */
+ override fun removeNavigationAction(action: Toolbar.Action) {
+ display.removeNavigationAction(action)
+ }
+
+ /**
+ * Adds an action to be displayed at the start of the URL in edit mode.
+ */
+ override fun addEditActionStart(action: Toolbar.Action) {
+ edit.addEditActionStart(action)
+ }
+
+ /**
+ * Adds an action to be displayed at the end of the URL in edit mode.
+ */
+ override fun addEditActionEnd(action: Toolbar.Action) {
+ edit.addEditActionEnd(action)
+ }
+
+ /**
+ * Removes an action end of the URL in edit mode.
+ */
+ override fun removeEditActionEnd(action: Toolbar.Action) {
+ edit.removeEditActionEnd(action)
+ }
+
+ /**
+ * Hides the menu button in display mode.
+ */
+ override fun hideMenuButton() {
+ display.hideMenuButton()
+ }
+
+ /**
+ * Shows the menu button in display mode.
+ */
+ override fun showMenuButton() {
+ display.showMenuButton()
+ }
+
+ /**
+ * Sets the horizontal padding in display mode.
+ */
+ override fun setDisplayHorizontalPadding(horizontalPadding: Int) {
+ display.setHorizontalPadding(horizontalPadding)
+ }
+
+ /**
+ * Hides the page action separator in display/edit mode.
+ */
+ override fun hidePageActionSeparator() {
+ display.hidePageActionSeparator()
+ edit.hidePageActionSeparator()
+ }
+
+ /**
+ * Shows the page action separator in display/edit mode.
+ */
+ override fun showPageActionSeparator() {
+ display.showPageActionSeparator()
+ edit.showPageActionSeparator()
+ }
+
+ /**
+ * Switches to URL editing mode.
+ *
+ * @param cursorPlacement Where the cursor should be placed after focusing on the URL input field.
+ */
+ override fun editMode(cursorPlacement: Toolbar.CursorPlacement) {
+ val urlValue = if (searchTerms.isEmpty()) url else searchTerms
+ edit.updateUrl(urlValue.toString(), false)
+ updateState(State.EDIT)
+ edit.focus()
+
+ when (cursorPlacement) {
+ Toolbar.CursorPlacement.ALL -> {
+ edit.selectAll()
+ }
+ Toolbar.CursorPlacement.END -> {
+ edit.selectEnd()
+ }
+ }
+ }
+
+ /**
+ * Switches to URL displaying mode.
+ */
+ override fun displayMode() {
+ updateState(State.DISPLAY)
+ }
+
+ /**
+ * Dismisses the display toolbar popup menu.
+ */
+ override fun dismissMenu() {
+ display.views.menu.dismissMenu()
+ }
+
+ override fun enableScrolling() {
+ // Behavior can be changed without us knowing. Not safe to use a memoized value.
+ (layoutParams as? CoordinatorLayout.LayoutParams)?.apply {
+ (behavior as? EngineViewScrollingBehavior)?.enableScrolling()
+ }
+ }
+
+ override fun disableScrolling() {
+ // Behavior can be changed without us knowing. Not safe to use a memoized value.
+ (layoutParams as? CoordinatorLayout.LayoutParams)?.apply {
+ (behavior as? EngineViewScrollingBehavior)?.disableScrolling()
+ }
+ }
+
+ override fun expand() {
+ (layoutParams as? CoordinatorLayout.LayoutParams)?.apply {
+ (behavior as? EngineViewScrollingBehavior)?.forceExpand(this@BrowserToolbar)
+ }
+ }
+
+ override fun collapse() {
+ (layoutParams as? CoordinatorLayout.LayoutParams)?.apply {
+ (behavior as? EngineViewScrollingBehavior)?.forceCollapse(this@BrowserToolbar)
+ }
+ }
+
+ internal fun onUrlEntered(url: String) {
+ if (urlCommitListener?.invoke(url) != false) {
+ // Return to display mode if there's no urlCommitListener or if it returned true. This lets
+ // the app control whether we should switch to display mode automatically.
+ displayMode()
+ }
+ }
+
+ private fun updateState(state: State) {
+ this.state = state
+
+ val (show, hide) = when (state) {
+ State.DISPLAY -> {
+ edit.stopEditing()
+ Pair(display.rootView, edit.rootView)
+ }
+ State.EDIT -> {
+ edit.startEditing()
+ Pair(edit.rootView, display.rootView)
+ }
+ }
+
+ show.visibility = View.VISIBLE
+ hide.visibility = View.GONE
+ }
+
+ private enum class State {
+ DISPLAY,
+ EDIT,
+ }
+
+ /**
+ * An action button to be added to the toolbar.
+ *
+ * @param imageDrawable The drawable to be shown.
+ * @param contentDescription The content description to use.
+ * @param visible Lambda that returns true or false to indicate whether this button should be shown.
+ * @param autoHide Lambda that returns true or false to indicate whether this button should auto hide.
+ * @param weight Lambda that returns an integer to indicate weight of an action. The lesser the weight,
+ * the closer it is to the url. A default weight -1 indicates, the position is not cared for
+ * and action will be appended at the end.
+ * @param background A custom (stateful) background drawable resource to be used.
+ * @param padding a custom [Padding] for this Button.
+ * @param iconTintColorResource Optional ID of color resource to tint the icon.
+ * @param longClickListener Callback that will be invoked whenever the button is long-pressed.
+ * @param listener Callback that will be invoked whenever the button is pressed
+ */
+ open class Button(
+ imageDrawable: Drawable,
+ contentDescription: String,
+ visible: () -> Boolean = { true },
+ autoHide: () -> Boolean = { false },
+ weight: () -> Int = { -1 },
+ @DrawableRes background: Int = 0,
+ val padding: Padding = DEFAULT_PADDING,
+ @ColorRes iconTintColorResource: Int = NO_ID,
+ longClickListener: (() -> Unit)? = null,
+ listener: () -> Unit,
+ ) : Toolbar.ActionButton(
+ imageDrawable,
+ contentDescription,
+ visible,
+ autoHide,
+ weight,
+ background,
+ padding,
+ iconTintColorResource,
+ longClickListener,
+ listener,
+ )
+
+ /**
+ * An action button with two states, selected and unselected. When the button is pressed, the
+ * state changes automatically.
+ *
+ * @param image The drawable to be shown if the button is in unselected state.
+ * @param imageSelected The drawable to be shown if the button is in selected state.
+ * @param contentDescription The content description to use if the button is in unselected state.
+ * @param contentDescriptionSelected The content description to use if the button is in selected state.
+ * @param visible Lambda that returns true or false to indicate whether this button should be shown.
+ * @param weight Lambda that returns an integer to indicate weight of an action. The lesser the weight,
+ * the closer it is to the url. A default weight -1 indicates, the position is not cared for
+ * and action will be appended at the end.
+ * @param selected Sets whether this button should be selected initially.
+ * @param background A custom (stateful) background drawable resource to be used.
+ * @param padding a custom [Padding] for this Button.
+ * @param listener Callback that will be invoked whenever the checked state changes.
+ */
+ open class ToggleButton(
+ image: Drawable,
+ imageSelected: Drawable,
+ contentDescription: String,
+ contentDescriptionSelected: String,
+ visible: () -> Boolean = { true },
+ weight: () -> Int = { -1 },
+ selected: Boolean = false,
+ @DrawableRes background: Int = 0,
+ val padding: Padding = DEFAULT_PADDING,
+ listener: (Boolean) -> Unit,
+ ) : Toolbar.ActionToggleButton(
+ image,
+ imageSelected,
+ contentDescription,
+ contentDescriptionSelected,
+ visible,
+ weight,
+ selected,
+ background,
+ padding,
+ listener,
+ )
+
+ /**
+ * An action that either shows an active button or an inactive button based on the provided
+ * <code>isInPrimaryState</code> lambda. All secondary characteristics default to their
+ * corresponding primary.
+ *
+ * @param primaryImage: The drawable to be shown if the button is in the primary/enabled state
+ * @param primaryContentDescription: The content description to use if the button is in the primary state.
+ * @param secondaryImage: The drawable to be shown if the button is in the secondary/disabled state.
+ * @param secondaryContentDescription: The content description to use if the button is in the secondary state.
+ * @param isInPrimaryState: Lambda that returns whether this button should be in the primary or secondary state.
+ * @param primaryImageTintResource: Optional ID of color resource to tint the icon in the primary state.
+ * @param secondaryImageTintResource: ID of color resource to tint the icon in the secondary state.
+ * @param disableInSecondaryState: Disable the button entirely when in the secondary state?
+ * @param weight Lambda that returns an integer to indicate weight of an action. The lesser the weight,
+ * the closer it is to the url. A default weight -1 indicates, the position is not cared for
+ * and action will be appended at the end.
+ * @param background A custom (stateful) background drawable resource to be used.
+ * @param longClickListener Callback that will be invoked whenever the button is long-pressed.
+ * @param listener Callback that will be invoked whenever the button is pressed.
+ */
+ open class TwoStateButton(
+ val primaryImage: Drawable,
+ val primaryContentDescription: String,
+ val secondaryImage: Drawable = primaryImage,
+ val secondaryContentDescription: String = primaryContentDescription,
+ val isInPrimaryState: () -> Boolean = { true },
+ @ColorRes val primaryImageTintResource: Int = NO_ID,
+ @ColorRes val secondaryImageTintResource: Int = primaryImageTintResource,
+ val disableInSecondaryState: Boolean = true,
+ override val weight: () -> Int = { -1 },
+ background: Int = 0,
+ longClickListener: (() -> Unit)? = null,
+ listener: () -> Unit,
+ ) : Button(
+ primaryImage,
+ primaryContentDescription,
+ weight = weight,
+ background = background,
+ longClickListener = longClickListener,
+ listener = listener,
+ ) {
+ var enabled: Boolean = false
+ private set
+
+ override fun bind(view: View) {
+ enabled = isInPrimaryState.invoke()
+
+ val button = view as ImageButton
+ if (enabled) {
+ button.setImageDrawable(primaryImage)
+ button.contentDescription = primaryContentDescription
+ button.setTintResource(primaryImageTintResource)
+ button.isEnabled = true
+ } else {
+ button.setImageDrawable(secondaryImage)
+ button.contentDescription = secondaryContentDescription
+ button.setTintResource(secondaryImageTintResource)
+ button.isEnabled = !disableInSecondaryState
+ }
+ }
+ }
+
+ companion object {
+ internal const val ACTION_PADDING_DP = 16
+ internal val DEFAULT_PADDING =
+ Padding(ACTION_PADDING_DP, ACTION_PADDING_DP, ACTION_PADDING_DP, ACTION_PADDING_DP)
+ }
+}
+
+/**
+ * Wraps [filter] execution in a coroutine context, cancelling prior executions on every invocation.
+ * [coroutineContext] must be of type that doesn't propagate cancellation of its children upwards.
+ */
+class AsyncFilterListener(
+ private val urlView: AutocompleteView,
+ override val coroutineContext: CoroutineContext,
+ private val filter: suspend (String, AutocompleteDelegate) -> Unit,
+ private val uiContext: CoroutineContext = Dispatchers.Main,
+) : OnFilterListener, CoroutineScope {
+ override fun invoke(text: String) {
+ // We got a new input, so whatever past autocomplete queries we still have running are
+ // irrelevant. We cancel them, but do not depend on cancellation to take place.
+ coroutineContext.cancelChildren()
+
+ CoroutineScope(coroutineContext).launch {
+ filter(text, AsyncAutocompleteDelegate(urlView, this, uiContext))
+ }
+ }
+}
+
+/**
+ * An autocomplete delegate which is aware of its parent scope (to check for cancellations).
+ * Responsible for processing autocompletion results and discarding stale results when [urlView] moved on.
+ */
+private class AsyncAutocompleteDelegate(
+ private val urlView: AutocompleteView,
+ private val parentScope: CoroutineScope,
+ override val coroutineContext: CoroutineContext,
+ private val logger: Logger = Logger("AsyncAutocompleteDelegate"),
+) : AutocompleteDelegate, CoroutineScope {
+ override fun applyAutocompleteResult(result: AutocompleteResult, onApplied: () -> Unit) {
+ // Bail out if we were cancelled already.
+ if (!parentScope.isActive) {
+ logger.debug("Autocomplete request cancelled. Discarding results.")
+ return
+ }
+
+ // Process results on the UI dispatcher.
+ CoroutineScope(coroutineContext).launch {
+ // Ignore this result if the query is stale.
+ if (result.input == urlView.originalText.lowercase()) {
+ urlView.applyAutocompleteResult(
+ InlineAutocompleteEditText.AutocompleteResult(
+ text = result.text,
+ source = result.source,
+ totalItems = result.totalItems,
+ ),
+ )
+ onApplied()
+ } else {
+ logger.debug("Discarding stale autocomplete result.")
+ }
+ }
+ }
+
+ override fun noAutocompleteResult(input: String) {
+ // Bail out if we were cancelled already.
+ if (!parentScope.isActive) {
+ logger.debug("Autocomplete request cancelled. Discarding 'noAutocompleteResult'.")
+ return
+ }
+
+ // Process results on the UI thread.
+ CoroutineScope(coroutineContext).launch {
+ // Ignore this result if the query is stale.
+ if (input == urlView.originalText) {
+ urlView.noAutocompleteResult()
+ } else {
+ logger.debug("Discarding stale lack of autocomplete results.")
+ }
+ }
+ }
+}
diff --git a/mobile/android/android-components/components/browser/toolbar2/src/main/java/mozilla/components/browser/toolbar2/display/DisplayToolbar.kt b/mobile/android/android-components/components/browser/toolbar2/src/main/java/mozilla/components/browser/toolbar2/display/DisplayToolbar.kt
new file mode 100644
index 0000000000..66218febbb
--- /dev/null
+++ b/mobile/android/android-components/components/browser/toolbar2/src/main/java/mozilla/components/browser/toolbar2/display/DisplayToolbar.kt
@@ -0,0 +1,711 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.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.browser.toolbar2.display
+
+import android.content.Context
+import android.graphics.Color
+import android.graphics.Typeface
+import android.graphics.drawable.Drawable
+import android.os.Build
+import android.util.TypedValue
+import android.view.View
+import android.view.accessibility.AccessibilityEvent
+import android.widget.ImageView
+import android.widget.ProgressBar
+import androidx.annotation.ColorInt
+import androidx.appcompat.content.res.AppCompatResources.getDrawable
+import androidx.constraintlayout.widget.ConstraintLayout
+import androidx.constraintlayout.widget.ConstraintSet
+import androidx.core.content.ContextCompat
+import androidx.core.view.isVisible
+import mozilla.components.browser.menu.BrowserMenuBuilder
+import mozilla.components.browser.toolbar2.BrowserToolbar
+import mozilla.components.browser.toolbar2.R
+import mozilla.components.browser.toolbar2.internal.ActionContainer
+import mozilla.components.concept.menu.MenuController
+import mozilla.components.concept.toolbar.Toolbar
+import mozilla.components.support.ktx.android.content.isScreenReaderEnabled
+import mozilla.components.ui.colors.R.color as photonColors
+
+/**
+ * Sub-component of the browser toolbar responsible for displaying the URL and related controls ("display mode").
+ *
+ * Structure:
+ * ```
+ * +-------------+------------+-----------------------+----------+------+
+ * | navigation | indicators | url [ page ] | browser | menu |
+ * | actions | | [ actions ] | actions | |
+ * +-------------+------------+-----------------------+----------+------+
+ * +------------------------progress------------------------------------+
+ * ```
+ *
+ * Navigation actions (optional):
+ * A dynamic list of clickable icons usually used for navigation on larger devices
+ * (e.g. “back”/”forward” buttons.)
+ *
+ * Indicators (optional):
+ * Tracking protection indicator icon (e.g. “shield” icon) that may show a doorhanger when clicked.
+ * Separator icon: a vertical line that separate the above and below icons.
+ * Site security indicator icon (e.g. “Lock” icon) that may show a doorhanger when clicked.
+ * Empty indicator: Icon that will be displayed if the URL is empty.
+ *
+ * URL:
+ * Section that displays the current URL (read-only)
+ *
+ * Page actions (optional):
+ * A dynamic list of clickable icons inside the URL section (e.g. “reader mode” icon)
+ *
+ * Browser actions (optional):
+ * A list of dynamic clickable icons on the toolbar (e.g. tabs tray button)
+ *
+ * Menu (optional):
+ * A button that shows an overflow menu when clicked (constructed using the browser-menu
+ * component)
+ *
+ * Progress (optional):
+ * A horizontal progress bar showing the loading progress (at the top or bottom of the toolbar).
+ */
+@Suppress("LargeClass")
+class DisplayToolbar internal constructor(
+ private val context: Context,
+ private val toolbar: BrowserToolbar,
+ internal val rootView: View,
+) {
+ /**
+ * Enum of indicators that can be displayed in the toolbar.
+ */
+ enum class Indicators {
+ SECURITY,
+ TRACKING_PROTECTION,
+ EMPTY,
+ HIGHLIGHT,
+ }
+
+ /**
+ * Data class holding the customizable colors in "display mode".
+ *
+ * @property securityIconSecure Color tint for the "secure connection" icon (lock).
+ * @property securityIconInsecure Color tint for the "insecure connection" icon (broken lock).
+ * @property emptyIcon Color tint for the icon shown when the URL is empty.
+ * @property menu Color tint for the menu icon.
+ * @property hint Text color of the hint shown when the URL is empty.
+ * @property title Text color of the website title.
+ * @property text Text color of the URL.
+ * @property trackingProtection Color tint for the tracking protection icons.
+ * @property separator Color tint for the separator shown between indicators.
+ * @property pageActionSeparator Color tint of separator dividing url and page actions.
+ * @property highlight Color tint for the highlight icon.
+ *
+ * Set/Get the site security icon colours. It uses a pair of color integers which represent the
+ * insecure and secure colours respectively.
+ */
+ data class Colors(
+ @ColorInt val securityIconSecure: Int,
+ @ColorInt val securityIconInsecure: Int,
+ @ColorInt val emptyIcon: Int,
+ @ColorInt val menu: Int,
+ @ColorInt val hint: Int,
+ @ColorInt val title: Int,
+ @ColorInt val text: Int,
+ @ColorInt val trackingProtection: Int?,
+ @ColorInt val separator: Int,
+ @ColorInt val pageActionSeparator: Int,
+ @ColorInt val highlight: Int?,
+ )
+
+ /**
+ * Data class holding the customizable icons in "display mode".
+ *
+ * @property emptyIcon An icon that is shown in front of the URL if the URL is empty.
+ * @property trackingProtectionTrackersBlocked An icon that is shown if tracking protection is
+ * enabled and trackers have been blocked.
+ * @property trackingProtectionNothingBlocked An icon that is shown if tracking protection is
+ * enabled and no trackers have been blocked.
+ * @property trackingProtectionException An icon that is shown if tracking protection is enabled
+ * but the current page is in the "exception list".
+ * @property highlight An icon that is shown if any event needs to be brought
+ * to the user's attention. Like the autoplay permission been blocked.
+ */
+ data class Icons(
+ val emptyIcon: Drawable?,
+ val trackingProtectionTrackersBlocked: Drawable,
+ val trackingProtectionNothingBlocked: Drawable,
+ val trackingProtectionException: Drawable,
+ val highlight: Drawable,
+ )
+
+ /**
+ * Gravity enum for positioning the progress bar.
+ */
+ enum class Gravity {
+ TOP,
+ BOTTOM,
+ }
+
+ internal val views = DisplayToolbarViews(
+ browserActions = rootView.findViewById(R.id.mozac_browser_toolbar_browser_actions),
+ pageActions = rootView.findViewById(R.id.mozac_browser_toolbar_page_actions),
+ navigationActions = rootView.findViewById(R.id.mozac_browser_toolbar_navigation_actions),
+ background = rootView.findViewById(R.id.mozac_browser_toolbar_background),
+ separator = rootView.findViewById(R.id.mozac_browser_toolbar_separator),
+ pageActionSeparator = rootView.findViewById(R.id.mozac_browser_toolbar_action_separator),
+ emptyIndicator = rootView.findViewById(R.id.mozac_browser_toolbar_empty_indicator),
+ menu = MenuButton(rootView.findViewById(R.id.mozac_browser_toolbar_menu)),
+ securityIndicator = rootView.findViewById(R.id.mozac_browser_toolbar_security_indicator),
+ trackingProtectionIndicator = rootView.findViewById(
+ R.id.mozac_browser_toolbar_tracking_protection_indicator,
+ ),
+ origin = rootView.findViewById<OriginView>(R.id.mozac_browser_toolbar_origin_view).also {
+ it.toolbar = toolbar
+ },
+ progress = rootView.findViewById<ProgressBar>(R.id.mozac_browser_toolbar_progress),
+ highlight = rootView.findViewById(R.id.mozac_browser_toolbar_permission_indicator),
+ )
+
+ /**
+ * Customizable colors in "display mode".
+ */
+ var colors: Colors = Colors(
+ securityIconSecure = ContextCompat.getColor(context, photonColors.photonWhite),
+ securityIconInsecure = ContextCompat.getColor(context, photonColors.photonWhite),
+ emptyIcon = ContextCompat.getColor(context, photonColors.photonWhite),
+ menu = ContextCompat.getColor(context, photonColors.photonWhite),
+ hint = views.origin.hintColor,
+ title = views.origin.titleColor,
+ text = views.origin.textColor,
+ trackingProtection = null,
+ separator = ContextCompat.getColor(context, photonColors.photonGrey80),
+ pageActionSeparator = ContextCompat.getColor(context, photonColors.photonGrey80),
+ highlight = null,
+ )
+ set(value) {
+ field = value
+
+ updateSiteSecurityIcon()
+ views.emptyIndicator.setColorFilter(value.emptyIcon)
+ views.menu.setColorFilter(value.menu)
+ views.origin.hintColor = value.hint
+ views.origin.titleColor = value.title
+ views.origin.textColor = value.text
+ views.separator.setColorFilter(value.separator)
+ views.pageActionSeparator.setBackgroundColor(value.pageActionSeparator)
+
+ if (value.trackingProtection != null) {
+ views.trackingProtectionIndicator.setTint(value.trackingProtection)
+ views.trackingProtectionIndicator.setColorFilter(value.trackingProtection)
+ }
+
+ if (value.highlight != null) {
+ views.highlight.setTint(value.highlight)
+ }
+ }
+
+ /**
+ * Customizable icons in "edit mode".
+ */
+ var icons: Icons = Icons(
+ emptyIcon = null,
+ trackingProtectionTrackersBlocked = requireNotNull(
+ getDrawable(context, TrackingProtectionIconView.DEFAULT_ICON_ON_TRACKERS_BLOCKED),
+ ),
+ trackingProtectionNothingBlocked = requireNotNull(
+ getDrawable(context, TrackingProtectionIconView.DEFAULT_ICON_ON_NO_TRACKERS_BLOCKED),
+ ),
+ trackingProtectionException = requireNotNull(
+ getDrawable(context, TrackingProtectionIconView.DEFAULT_ICON_OFF_FOR_A_SITE),
+ ),
+ highlight = requireNotNull(
+ getDrawable(context, R.drawable.mozac_dot_notification),
+ ),
+ )
+ set(value) {
+ field = value
+
+ views.emptyIndicator.setImageDrawable(value.emptyIcon)
+
+ views.trackingProtectionIndicator.setIcons(
+ value.trackingProtectionNothingBlocked,
+ value.trackingProtectionTrackersBlocked,
+ value.trackingProtectionException,
+ )
+ views.highlight.setIcon(value.highlight)
+ }
+
+ /**
+ * Allows customization of URL for display purposes.
+ */
+ var urlFormatter: ((CharSequence) -> CharSequence)? = null
+
+ /**
+ * Sets a listener to be invoked when the site security indicator icon is clicked.
+ */
+ fun setOnSiteSecurityClickedListener(listener: (() -> Unit)?) {
+ if (listener == null) {
+ views.securityIndicator.setOnClickListener(null)
+ views.securityIndicator.background = null
+ } else {
+ views.securityIndicator.setOnClickListener {
+ listener.invoke()
+ }
+
+ val outValue = TypedValue()
+ context.theme.resolveAttribute(
+ android.R.attr.selectableItemBackgroundBorderless,
+ outValue,
+ true,
+ )
+
+ views.securityIndicator.setBackgroundResource(outValue.resourceId)
+ }
+ }
+
+ /**
+ * Sets a listener to be invoked when the site tracking protection indicator icon is clicked.
+ */
+ fun setOnTrackingProtectionClickedListener(listener: (() -> Unit)?) {
+ if (listener == null) {
+ views.trackingProtectionIndicator.setOnClickListener(null)
+ views.trackingProtectionIndicator.background = null
+ } else {
+ views.trackingProtectionIndicator.setOnClickListener {
+ listener.invoke()
+ }
+
+ val outValue = TypedValue()
+ context.theme.resolveAttribute(
+ android.R.attr.selectableItemBackgroundBorderless,
+ outValue,
+ true,
+ )
+
+ views.trackingProtectionIndicator.setBackgroundResource(outValue.resourceId)
+ }
+ }
+
+ /**
+ * Sets a lambda to be invoked when the menu is dismissed
+ */
+ fun setMenuDismissAction(onDismiss: () -> Unit) {
+ views.menu.setMenuDismissAction(onDismiss)
+ }
+
+ /**
+ * List of indicators that should be displayed next to the URL.
+ */
+ var indicators: List<Indicators> = listOf(Indicators.SECURITY)
+ set(value) {
+ field = value
+
+ updateIndicatorVisibility()
+ }
+
+ var displayIndicatorSeparator: Boolean = true
+ set(value) {
+ field = value
+ updateIndicatorVisibility()
+ }
+
+ /**
+ * Sets the background that should be drawn behind the URL, page actions an indicators.
+ */
+ fun setUrlBackground(background: Drawable?) {
+ views.background.setImageDrawable(background)
+ }
+
+ /**
+ * Whether the progress bar should be drawn at the top or bottom of the toolbar.
+ */
+ var progressGravity: Gravity = Gravity.BOTTOM
+ set(value) {
+ field = value
+
+ val layout = rootView as ConstraintLayout
+ layout.hashCode()
+
+ val constraintSet = ConstraintSet()
+ constraintSet.clone(layout)
+ constraintSet.clear(views.progress.id, ConstraintSet.TOP)
+ constraintSet.clear(views.progress.id, ConstraintSet.BOTTOM)
+ constraintSet.connect(
+ views.progress.id,
+ if (value == Gravity.TOP) ConstraintSet.TOP else ConstraintSet.BOTTOM,
+ ConstraintSet.PARENT_ID,
+ if (value == Gravity.TOP) ConstraintSet.TOP else ConstraintSet.BOTTOM,
+ )
+ constraintSet.applyTo(layout)
+ }
+
+ /**
+ * Sets a lambda that will be invoked whenever the URL in display mode was clicked. Only if this
+ * lambda returns <code>true</code> the toolbar will switch to editing mode. Return
+ * <code>false</code> to not switch to editing mode and handle the click manually.
+ */
+ var onUrlClicked: () -> Boolean
+ get() = views.origin.onUrlClicked
+ set(value) {
+ views.origin.onUrlClicked = value
+ }
+
+ /**
+ * Sets the text to be displayed when the URL of the toolbar is empty.
+ */
+ var hint: String
+ get() = views.origin.hint
+ set(value) {
+ views.origin.hint = value
+ }
+
+ /**
+ * Sets the size of the text for the title displayed in the toolbar.
+ */
+ var titleTextSize: Float
+ get() = views.origin.titleTextSize
+ set(value) {
+ views.origin.titleTextSize = value
+ }
+
+ /**
+ * Sets the size of the text for the URL/search term displayed in the toolbar.
+ */
+ var textSize: Float
+ get() = views.origin.textSize
+ set(value) {
+ views.origin.textSize = value
+ }
+
+ /**
+ * Sets the typeface of the text for the URL/search term displayed in the toolbar.
+ */
+ var typeface: Typeface
+ get() = views.origin.typeface
+ set(value) {
+ views.origin.typeface = value
+ }
+
+ /**
+ * Sets a [BrowserMenuBuilder] that will be used to create a menu when the menu button is clicked.
+ * The menu button will only be visible if a builder or controller has been set.
+ */
+ var menuBuilder: BrowserMenuBuilder?
+ get() = views.menu.menuBuilder
+ set(value) {
+ views.menu.menuBuilder = value
+ }
+
+ /**
+ * Sets a [MenuController] that will be used to create a menu when the menu button is clicked.
+ * The menu button will only be visible if a builder or controller has been set.
+ * If both a [menuBuilder] and controller are present, only the controller will be used.
+ */
+ var menuController: MenuController?
+ get() = views.menu.menuController
+ set(value) {
+ views.menu.menuController = value
+ }
+
+ /**
+ * Set a LongClickListener to the urlView of the toolbar.
+ */
+ fun setOnUrlLongClickListener(handler: ((View) -> Boolean)?) = views.origin.setOnUrlLongClickListener(handler)
+
+ private fun updateIndicatorVisibility() {
+ val urlEmpty = url.isEmpty()
+
+ views.securityIndicator.visibility = if (!urlEmpty && indicators.contains(Indicators.SECURITY)) {
+ View.VISIBLE
+ } else {
+ View.GONE
+ }
+
+ views.trackingProtectionIndicator.visibility = if (
+ !urlEmpty && indicators.contains(Indicators.TRACKING_PROTECTION)
+ ) {
+ View.VISIBLE
+ } else {
+ View.GONE
+ }
+
+ views.emptyIndicator.visibility = if (urlEmpty && indicators.contains(Indicators.EMPTY)) {
+ View.VISIBLE
+ } else {
+ View.GONE
+ }
+
+ views.highlight.visibility = if (!urlEmpty && indicators.contains(Indicators.HIGHLIGHT)) {
+ setHighlight(toolbar.highlight)
+ } else {
+ View.GONE
+ }
+
+ updateSeparatorVisibility()
+ }
+
+ private fun updateSeparatorVisibility() {
+ views.separator.visibility = if (
+ displayIndicatorSeparator &&
+ views.trackingProtectionIndicator.isVisible &&
+ views.securityIndicator.isVisible
+ ) {
+ View.VISIBLE
+ } else {
+ View.GONE
+ }
+
+ // In Fenix (which is using a beta release of ConstraintLayout) we are seeing issues after
+ // early visibility changes. Children of the ConstraintLayout are not visible and have a
+ // size of 0x0 (even though they have a fixed size in the layout XML). Explicitly requesting
+ // to layout the ConstraintLayout fixes that issue. This may be a bug in the beta of
+ // ConstraintLayout and in the future we may be able to just remove this call.
+ rootView.requestLayout()
+ }
+
+ /**
+ * Updates the title to be displayed.
+ */
+ internal var title: String
+ get() = views.origin.title
+ set(value) {
+ views.origin.title = value
+ }
+
+ /**
+ * Updates the URL to be displayed.
+ */
+ internal var url: CharSequence = ""
+ set(value) {
+ field = value
+ views.origin.url = urlFormatter?.invoke(value) ?: value
+ updateIndicatorVisibility()
+ }
+
+ /**
+ * Sets the site's security icon as secure if true, else the regular globe.
+ */
+ internal var siteSecurity: Toolbar.SiteSecurity = Toolbar.SiteSecurity.INSECURE
+ set(value) {
+ field = value
+ updateSiteSecurityIcon()
+ }
+
+ private fun updateSiteSecurityIcon() {
+ @ColorInt val color = when (siteSecurity) {
+ Toolbar.SiteSecurity.INSECURE -> colors.securityIconInsecure
+ Toolbar.SiteSecurity.SECURE -> colors.securityIconSecure
+ }
+ if (color == Color.TRANSPARENT && Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
+ views.securityIndicator.clearColorFilter()
+ } else {
+ views.securityIndicator.setColorFilter(color)
+ }
+
+ views.securityIndicator.siteSecurity = siteSecurity
+ }
+
+ internal fun setTrackingProtectionState(state: Toolbar.SiteTrackingProtection) {
+ views.trackingProtectionIndicator.siteTrackingProtection = state
+ updateSeparatorVisibility()
+ }
+
+ internal fun setHighlight(state: Toolbar.Highlight): Int {
+ if (!indicators.contains(Indicators.HIGHLIGHT)) {
+ return views.highlight.visibility
+ }
+
+ views.highlight.state = state
+
+ return views.highlight.visibility
+ }
+
+ internal fun onStop() {
+ views.menu.dismissMenu()
+ }
+
+ /**
+ * Updates the progress to be displayed.
+ *
+ * Accessibility note:
+ * ProgressBars can be made accessible to TalkBack by setting `android:accessibilityLiveRegion`.
+ * They will emit TYPE_VIEW_SELECTED events. TalkBack will format those events into percentage
+ * announcements along with a pitch-change earcon. We are not using that feature here for
+ * several reasons:
+ * 1. They are dispatched via a 200ms timeout. Since loading a page can be a short process,
+ * and since we only update the bar a handful of times, these events often never fire and
+ * they don't give the user a true sense of the progress.
+ * 2. The last 100% event is dispatched after the view is hidden. This prevents the event
+ * from being fired, so the user never gets a "complete" event.
+ * 3. Live regions in TalkBack have their role announced, so the user will hear
+ * "Progress bar, 25%". For a common feature like page load this is very chatty and unintuitive.
+ * 4. We can provide custom strings instead of the less useful percentage utterance, but
+ * TalkBack will not play an earcon if an event has its own text.
+ *
+ * For all those reasons, we are going another route here with a "loading" announcement
+ * when the progress bar first appears along with scroll events that have the same
+ * pitch-change earcon in TalkBack (although they are a bit louder). This gives a concise and
+ * consistent feedback to the user that they can depend on.
+ *
+ */
+ internal fun updateProgress(progress: Int) {
+ if (!views.progress.isVisible && progress > 0) {
+ // Loading has just started, make visible.
+ views.progress.visibility = View.VISIBLE
+
+ // Announce "loading" for accessibility if it has not been completed
+ if (progress < views.progress.max) {
+ views.progress.announceForAccessibility(
+ context.getString(R.string.mozac_browser_toolbar_progress_loading),
+ )
+ }
+ }
+
+ views.progress.progress = progress
+ val event = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
+ AccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SCROLLED)
+ } else {
+ @Suppress("DEPRECATION")
+ AccessibilityEvent.obtain(AccessibilityEvent.TYPE_VIEW_SCROLLED)
+ }.apply {
+ scrollY = progress
+ maxScrollY = views.progress.max
+ }
+
+ if (context.isScreenReaderEnabled) {
+ views.progress.parent.requestSendAccessibilityEvent(views.progress, event)
+ }
+
+ if (progress >= views.progress.max) {
+ // Loading is done, hide progress bar.
+ views.progress.visibility = View.GONE
+ }
+ }
+
+ /**
+ * Declare that the actions (navigation actions, browser actions, page actions) have changed and
+ * should be updated if needed.
+ */
+ internal fun invalidateActions() {
+ views.menu.invalidateMenu()
+
+ views.browserActions.invalidateActions()
+ views.pageActions.invalidateActions()
+ views.navigationActions.invalidateActions()
+ }
+
+ /**
+ * Adds an action to be displayed on the right side of the toolbar (outside of the URL bounding
+ * box) in display mode.
+ *
+ * If there is not enough room to show all icons then some icons may be moved to an overflow
+ * menu.
+ *
+ * Related:
+ * https://developer.mozilla.org/en-US/Add-ons/WebExtensions/user_interface/Browser_action
+ */
+ internal fun addBrowserAction(action: Toolbar.Action) {
+ views.browserActions.addAction(action)
+ }
+
+ /**
+ * Removes a previously added browser action (see [addBrowserAction]). If the provided
+ * action was never added, this method has no effect.
+ *
+ * @param action the action to remove.
+ */
+ internal fun removeBrowserAction(action: Toolbar.Action) {
+ views.browserActions.removeAction(action)
+ }
+
+ /**
+ * Removes a previously added page action (see [addBrowserAction]). If the provided
+ * action was never added, this method has no effect.
+ *
+ * @param action the action to remove.
+ */
+ internal fun removePageAction(action: Toolbar.Action) {
+ views.pageActions.removeAction(action)
+ }
+
+ /**
+ * Adds an action to be displayed on the right side of the URL in display mode.
+ *
+ * Related:
+ * https://developer.mozilla.org/en-US/Add-ons/WebExtensions/user_interface/Page_actions
+ */
+ internal fun addPageAction(action: Toolbar.Action) {
+ views.pageActions.addAction(action)
+ }
+
+ /**
+ * Adds an action to be display on the far left side of the toolbar. This area is usually used
+ * on larger devices for navigation actions like "back" and "forward".
+ */
+ internal fun addNavigationAction(action: Toolbar.Action) {
+ views.navigationActions.addAction(action)
+ }
+
+ /**
+ * Removes a previously added navigation action (see [addNavigationAction]). If the provided
+ * action was never added, this method has no effect.
+ *
+ * @param action the action to remove.
+ */
+ internal fun removeNavigationAction(action: Toolbar.Action) {
+ views.navigationActions.removeAction(action)
+ }
+
+ /**
+ * Hides the menu button in display mode.
+ */
+ fun hideMenuButton() {
+ views.menu.setShouldBeHidden(true)
+ }
+
+ /**
+ * Shows the menu button in display mode.
+ */
+ internal fun showMenuButton() {
+ views.menu.setShouldBeHidden(false)
+ }
+
+ /**
+ * Sets the horizontal padding.
+ */
+ fun setHorizontalPadding(horizontalPadding: Int) {
+ rootView.setPadding(horizontalPadding, 0, horizontalPadding, 0)
+ }
+
+ /**
+ * Hides the page action separator in display mode.
+ */
+ fun hidePageActionSeparator() {
+ views.pageActionSeparator.isVisible = false
+ }
+
+ /**
+ * Shows the page action separator in display mode.
+ */
+ internal fun showPageActionSeparator() {
+ views.pageActionSeparator.isVisible = true
+ }
+}
+
+/**
+ * Internal holder for view references.
+ */
+@Suppress("LongParameterList")
+internal class DisplayToolbarViews(
+ val browserActions: ActionContainer,
+ val pageActions: ActionContainer,
+ val navigationActions: ActionContainer,
+ val background: ImageView,
+ val separator: ImageView,
+ val pageActionSeparator: View,
+ val emptyIndicator: ImageView,
+ val menu: MenuButton,
+ val securityIndicator: SiteSecurityIconView,
+ val trackingProtectionIndicator: TrackingProtectionIconView,
+ val origin: OriginView,
+ val progress: ProgressBar,
+ val highlight: HighlightView,
+)
diff --git a/mobile/android/android-components/components/browser/toolbar2/src/main/java/mozilla/components/browser/toolbar2/display/DisplayToolbarView.kt b/mobile/android/android-components/components/browser/toolbar2/src/main/java/mozilla/components/browser/toolbar2/display/DisplayToolbarView.kt
new file mode 100644
index 0000000000..5bd684a07e
--- /dev/null
+++ b/mobile/android/android-components/components/browser/toolbar2/src/main/java/mozilla/components/browser/toolbar2/display/DisplayToolbarView.kt
@@ -0,0 +1,51 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.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.browser.toolbar2.display
+
+import android.content.Context
+import android.graphics.Canvas
+import android.util.AttributeSet
+import android.view.View
+import android.widget.ImageView
+import androidx.constraintlayout.widget.ConstraintLayout
+import mozilla.components.browser.toolbar2.R
+
+/**
+ * Custom ConstraintLayout for DisplayToolbar that allows us to draw ripple backgrounds on the toolbar
+ * by setting a background to transparent.
+ */
+class DisplayToolbarView @JvmOverloads constructor(
+ context: Context,
+ attrs: AttributeSet? = null,
+ defStyleAttr: Int = 0,
+) : ConstraintLayout(context, attrs, defStyleAttr) {
+ init {
+ // Forcing transparent background so that draw methods will get called and ripple effect
+ // for children will be drawn on this layout.
+ setBackgroundColor(0x00000000)
+ }
+
+ lateinit var backgroundView: ImageView
+
+ override fun onFinishInflate() {
+ backgroundView = findViewById(R.id.mozac_browser_toolbar_background)
+ backgroundView.visibility = View.INVISIBLE
+
+ super.onFinishInflate()
+ }
+
+ // Overriding draw instead of onDraw since we want to draw the background before the actual
+ // (transparent) background (with a ripple effect) is drawn.
+ override fun draw(canvas: Canvas) {
+ canvas.save()
+ canvas.translate(backgroundView.x, backgroundView.y)
+
+ backgroundView.drawable?.draw(canvas)
+
+ canvas.restore()
+
+ super.draw(canvas)
+ }
+}
diff --git a/mobile/android/android-components/components/browser/toolbar2/src/main/java/mozilla/components/browser/toolbar2/display/HighlightView.kt b/mobile/android/android-components/components/browser/toolbar2/src/main/java/mozilla/components/browser/toolbar2/display/HighlightView.kt
new file mode 100644
index 0000000000..240da038ec
--- /dev/null
+++ b/mobile/android/android-components/components/browser/toolbar2/src/main/java/mozilla/components/browser/toolbar2/display/HighlightView.kt
@@ -0,0 +1,91 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.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.browser.toolbar2.display
+
+import android.content.Context
+import android.graphics.drawable.Drawable
+import android.util.AttributeSet
+import androidx.annotation.VisibleForTesting
+import androidx.appcompat.content.res.AppCompatResources
+import androidx.appcompat.widget.AppCompatImageView
+import androidx.core.view.isVisible
+import mozilla.components.browser.toolbar2.R
+import mozilla.components.concept.toolbar.Toolbar.Highlight
+import mozilla.components.concept.toolbar.Toolbar.Highlight.NONE
+import mozilla.components.concept.toolbar.Toolbar.Highlight.PERMISSIONS_CHANGED
+
+/**
+ * Internal widget to display a dot notification.
+ */
+internal class HighlightView @JvmOverloads constructor(
+ context: Context,
+ attrs: AttributeSet? = null,
+ defStyleAttr: Int = 0,
+) : AppCompatImageView(context, attrs, defStyleAttr) {
+
+ init {
+ visibility = GONE
+ }
+
+ var state: Highlight = NONE
+ set(value) {
+ if (value != field) {
+ field = value
+ updateIcon()
+ }
+ }
+
+ @VisibleForTesting
+ internal var highlightTint: Int? = null
+
+ private var highlightIcon: Drawable =
+ requireNotNull(AppCompatResources.getDrawable(context, DEFAULT_ICON))
+
+ fun setTint(tint: Int) {
+ highlightTint = tint
+ setColorFilter(tint)
+ }
+
+ fun setIcon(icons: Drawable) {
+ this.highlightIcon = icons
+
+ updateIcon()
+ }
+
+ @Synchronized
+ @VisibleForTesting
+ internal fun updateIcon() {
+ val update = state.toUpdate()
+
+ isVisible = update.visible
+
+ contentDescription = if (update.contentDescription != null) {
+ context.getString(update.contentDescription)
+ } else {
+ null
+ }
+
+ highlightTint?.let { setColorFilter(it) }
+ setImageDrawable(update.drawable)
+ }
+
+ companion object {
+ val DEFAULT_ICON = R.drawable.mozac_dot_notification
+ }
+
+ private fun Highlight.toUpdate(): Update = when (this) {
+ PERMISSIONS_CHANGED -> Update(
+ highlightIcon,
+ R.string.mozac_browser_toolbar_content_description_autoplay_blocked,
+ true,
+ )
+
+ NONE -> Update(
+ null,
+ null,
+ false,
+ )
+ }
+}
diff --git a/mobile/android/android-components/components/browser/toolbar2/src/main/java/mozilla/components/browser/toolbar2/display/MenuButton.kt b/mobile/android/android-components/components/browser/toolbar2/src/main/java/mozilla/components/browser/toolbar2/display/MenuButton.kt
new file mode 100644
index 0000000000..6c2a919d00
--- /dev/null
+++ b/mobile/android/android-components/components/browser/toolbar2/src/main/java/mozilla/components/browser/toolbar2/display/MenuButton.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.browser.toolbar2.display
+
+import androidx.annotation.ColorInt
+import androidx.annotation.VisibleForTesting
+import androidx.core.view.isVisible
+import mozilla.components.browser.menu.BrowserMenuBuilder
+import mozilla.components.browser.menu.ext.asCandidateList
+import mozilla.components.browser.menu.ext.getHighlight
+import mozilla.components.browser.toolbar2.facts.emitOpenMenuFact
+import mozilla.components.concept.menu.MenuController
+
+internal class MenuButton(
+ @get:VisibleForTesting internal val impl: mozilla.components.browser.menu.view.MenuButton,
+) {
+
+ init {
+ impl.isVisible = false
+ impl.register(
+ object : mozilla.components.concept.menu.MenuButton.Observer {
+ override fun onShow() {
+ emitOpenMenuFact(impl.menuBuilder?.extras)
+ }
+ },
+ )
+ }
+
+ /**
+ * Reference to the [MenuController].
+ * If present, [menuBuilder] will be ignored.
+ */
+ var menuController: MenuController?
+ get() = impl.menuController
+ set(value) {
+ impl.menuController = value
+ impl.isVisible = shouldBeVisible()
+ }
+
+ /**
+ * Legacy [BrowserMenuBuilder] reference.
+ * Used to build the menu.
+ */
+ var menuBuilder: BrowserMenuBuilder?
+ get() = impl.menuBuilder
+ set(value) {
+ impl.menuBuilder = value
+ impl.isVisible = shouldBeVisible()
+ }
+
+ /**
+ * Declare that the menu items should be updated if needed.
+ * This should only be used once a [menuBuilder] is set.
+ * To update items in the [menuController], call [MenuController.submitList] directly.
+ */
+ fun invalidateMenu() {
+ val menuController = menuController
+ if (menuController != null) {
+ // Convert the menu builder items into a menu candidate list,
+ // if the menu builder is present
+ menuBuilder?.items?.let { items ->
+ val list = items.asCandidateList(impl.context)
+ menuController.submitList(list)
+ }
+ } else {
+ // Invalidate the BrowserMenu
+ impl.invalidateBrowserMenu()
+ impl.setHighlight(menuBuilder?.items?.getHighlight())
+ }
+ }
+
+ fun dismissMenu() {
+ val menuController = menuController
+ if (menuController != null) {
+ // Use the controller to dismiss the menu
+ menuController.dismiss()
+ } else {
+ // Use the button to dismiss the legacy menu
+ impl.dismissMenu()
+ }
+ }
+
+ /**
+ * Sets a lambda to be invoked when the menu is dismissed
+ */
+ @Suppress("Deprecation")
+ fun setMenuDismissAction(onDismiss: () -> Unit) {
+ impl.onDismiss = onDismiss
+ }
+
+ fun setColorFilter(@ColorInt color: Int) = impl.setColorFilter(color)
+
+ /**
+ * Hides the menu button.
+ *
+ * @param shouldBeHidden A [Boolean] that determines the visibility of the menu button.
+ */
+ fun setShouldBeHidden(shouldBeHidden: Boolean) {
+ impl.isVisible = !shouldBeHidden && shouldBeVisible()
+ }
+
+ @VisibleForTesting
+ internal fun shouldBeVisible() = impl.menuBuilder != null || impl.menuController != null
+}
diff --git a/mobile/android/android-components/components/browser/toolbar2/src/main/java/mozilla/components/browser/toolbar2/display/OriginView.kt b/mobile/android/android-components/components/browser/toolbar2/src/main/java/mozilla/components/browser/toolbar2/display/OriginView.kt
new file mode 100644
index 0000000000..3cd70d0dc9
--- /dev/null
+++ b/mobile/android/android-components/components/browser/toolbar2/src/main/java/mozilla/components/browser/toolbar2/display/OriginView.kt
@@ -0,0 +1,198 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.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.browser.toolbar2.display
+
+import android.animation.LayoutTransition
+import android.content.Context
+import android.graphics.Typeface
+import android.util.AttributeSet
+import android.util.TypedValue
+import android.view.Gravity
+import android.view.View
+import android.widget.LinearLayout
+import android.widget.TextView
+import androidx.annotation.VisibleForTesting
+import androidx.core.view.isVisible
+import mozilla.components.browser.toolbar2.BrowserToolbar
+import mozilla.components.browser.toolbar2.R
+
+private const val TITLE_VIEW_WEIGHT = 5.7f
+private const val URL_VIEW_WEIGHT = 4.3f
+
+/**
+ * View displaying the URL and optionally the title of a website.
+ */
+internal class OriginView @JvmOverloads constructor(
+ context: Context,
+ attrs: AttributeSet? = null,
+ defStyleAttr: Int = 0,
+) : LinearLayout(context, attrs, defStyleAttr) {
+ internal lateinit var toolbar: BrowserToolbar
+
+ private val textSizeUrlNormal = context.resources.getDimension(
+ R.dimen.mozac_browser_toolbar_url_textsize,
+ )
+ private val textSizeUrlWithTitle = context.resources.getDimension(
+ R.dimen.mozac_browser_toolbar_url_with_title_textsize,
+ )
+ private val textSizeTitle = context.resources.getDimension(
+ R.dimen.mozac_browser_toolbar_title_textsize,
+ )
+
+ @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
+ internal val urlView = TextView(context).apply {
+ id = R.id.mozac_browser_toolbar_url_view
+ setTextSize(TypedValue.COMPLEX_UNIT_PX, textSizeUrlNormal)
+ gravity = Gravity.CENTER_VERTICAL
+
+ setSingleLine()
+ isClickable = true
+ isFocusable = true
+
+ setOnClickListener {
+ if (onUrlClicked()) {
+ toolbar.editMode()
+ }
+ }
+
+ val fadingEdgeSize = resources.getDimensionPixelSize(
+ R.dimen.mozac_browser_toolbar_url_fading_edge_size,
+ )
+
+ setFadingEdgeLength(fadingEdgeSize)
+ isHorizontalFadingEdgeEnabled = fadingEdgeSize > 0
+ }
+
+ @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
+ internal val titleView = TextView(context).apply {
+ id = R.id.mozac_browser_toolbar_title_view
+ visibility = View.GONE
+
+ setTextSize(
+ TypedValue.COMPLEX_UNIT_PX,
+ textSizeTitle,
+ )
+ gravity = Gravity.CENTER_VERTICAL
+
+ setSingleLine()
+
+ val fadingEdgeSize = resources.getDimensionPixelSize(
+ R.dimen.mozac_browser_toolbar_url_fading_edge_size,
+ )
+
+ setFadingEdgeLength(fadingEdgeSize)
+ isHorizontalFadingEdgeEnabled = fadingEdgeSize > 0
+ }
+
+ init {
+ orientation = VERTICAL
+
+ addView(
+ titleView,
+ LayoutParams(
+ LayoutParams.MATCH_PARENT,
+ 0,
+ TITLE_VIEW_WEIGHT,
+ ),
+ )
+
+ addView(
+ urlView,
+ LayoutParams(
+ LayoutParams.MATCH_PARENT,
+ 0,
+ URL_VIEW_WEIGHT,
+ ),
+ )
+
+ layoutTransition = LayoutTransition()
+ }
+
+ internal var title: String
+ get() = titleView.text.toString()
+ set(value) {
+ titleView.text = value
+
+ titleView.isVisible = value.isNotEmpty()
+
+ urlView.setTextSize(
+ TypedValue.COMPLEX_UNIT_PX,
+ if (value.isNotEmpty()) {
+ textSizeUrlWithTitle
+ } else {
+ textSizeUrlNormal
+ },
+ )
+ }
+
+ internal var onUrlClicked: () -> Boolean = { true }
+
+ fun setOnUrlLongClickListener(handler: ((View) -> Boolean)?) {
+ urlView.isLongClickable = true
+ titleView.isLongClickable = true
+
+ urlView.setOnLongClickListener(handler)
+ titleView.setOnLongClickListener(handler)
+ }
+
+ internal var url: CharSequence
+ get() = urlView.text
+ set(value) { urlView.text = value }
+
+ /**
+ * Sets the colour of the text to be displayed when the URL of the toolbar is empty.
+ */
+ var hintColor: Int
+ get() = urlView.currentHintTextColor
+ set(value) {
+ urlView.setHintTextColor(value)
+ }
+
+ /**
+ * Sets the text to be displayed when the URL of the toolbar is empty.
+ */
+ var hint: String
+ get() = urlView.hint.toString()
+ set(value) { urlView.hint = value }
+
+ /**
+ * Sets the colour of the text for title displayed in the toolbar.
+ */
+ var titleColor: Int
+ get() = urlView.currentTextColor
+ set(value) { titleView.setTextColor(value) }
+
+ /**
+ * Sets the colour of the text for the URL/search term displayed in the toolbar.
+ */
+ var textColor: Int
+ get() = urlView.currentTextColor
+ set(value) { urlView.setTextColor(value) }
+
+ /**
+ * Sets the size of the text for the title displayed in the toolbar.
+ */
+ var titleTextSize: Float
+ get() = titleView.textSize
+ set(value) { titleView.textSize = value }
+
+ /**
+ * Sets the size of the text for the URL/search term displayed in the toolbar.
+ */
+ var textSize: Float
+ get() = urlView.textSize
+ set(value) {
+ urlView.textSize = value
+ }
+
+ /**
+ * Sets the typeface of the text for the URL/search term displayed in the toolbar.
+ */
+ var typeface: Typeface
+ get() = urlView.typeface
+ set(value) {
+ urlView.typeface = value
+ }
+}
diff --git a/mobile/android/android-components/components/browser/toolbar2/src/main/java/mozilla/components/browser/toolbar2/display/SiteSecurityIconView.kt b/mobile/android/android-components/components/browser/toolbar2/src/main/java/mozilla/components/browser/toolbar2/display/SiteSecurityIconView.kt
new file mode 100644
index 0000000000..6ebde5a885
--- /dev/null
+++ b/mobile/android/android-components/components/browser/toolbar2/src/main/java/mozilla/components/browser/toolbar2/display/SiteSecurityIconView.kt
@@ -0,0 +1,48 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.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.browser.toolbar2.display
+
+import android.content.Context
+import android.util.AttributeSet
+import android.view.View
+import androidx.appcompat.widget.AppCompatImageView
+import mozilla.components.browser.toolbar2.R
+import mozilla.components.concept.toolbar.Toolbar.SiteSecurity
+
+/**
+ * Internal widget to display the different icons of site security, relies on the
+ * [SiteSecurity] state of each page.
+ */
+internal class SiteSecurityIconView @JvmOverloads constructor(
+ context: Context,
+ attrs: AttributeSet? = null,
+ defStyleAttr: Int = 0,
+) : AppCompatImageView(context, attrs, defStyleAttr) {
+
+ // We allow null here because in some situations, onCreateDrawableState is getting called from
+ // the super() constructor on the View class, way before this class properties get
+ // initialized causing a null pointer exception.
+ // See for more details: https://github.com/mozilla-mobile/android-components/issues/4058
+ var siteSecurity: SiteSecurity? = SiteSecurity.INSECURE
+ set(value) {
+ if (value != field) {
+ field = value
+ refreshDrawableState()
+ }
+
+ field = value
+ }
+
+ override fun onCreateDrawableState(extraSpace: Int): IntArray {
+ return when (siteSecurity) {
+ SiteSecurity.INSECURE, null -> super.onCreateDrawableState(extraSpace)
+ SiteSecurity.SECURE -> {
+ val drawableState = super.onCreateDrawableState(extraSpace + 1)
+ View.mergeDrawableStates(drawableState, intArrayOf(R.attr.state_site_secure))
+ drawableState
+ }
+ }
+ }
+}
diff --git a/mobile/android/android-components/components/browser/toolbar2/src/main/java/mozilla/components/browser/toolbar2/display/TrackingProtectionIconView.kt b/mobile/android/android-components/components/browser/toolbar2/src/main/java/mozilla/components/browser/toolbar2/display/TrackingProtectionIconView.kt
new file mode 100644
index 0000000000..654f4edadb
--- /dev/null
+++ b/mobile/android/android-components/components/browser/toolbar2/src/main/java/mozilla/components/browser/toolbar2/display/TrackingProtectionIconView.kt
@@ -0,0 +1,135 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.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.browser.toolbar2.display
+
+import android.content.Context
+import android.graphics.drawable.Animatable
+import android.graphics.drawable.Drawable
+import android.util.AttributeSet
+import androidx.annotation.StringRes
+import androidx.annotation.VisibleForTesting
+import androidx.appcompat.content.res.AppCompatResources
+import androidx.appcompat.widget.AppCompatImageView
+import androidx.core.view.isVisible
+import mozilla.components.browser.toolbar2.R
+import mozilla.components.concept.toolbar.Toolbar.SiteTrackingProtection
+import mozilla.components.concept.toolbar.Toolbar.SiteTrackingProtection.OFF_FOR_A_SITE
+import mozilla.components.concept.toolbar.Toolbar.SiteTrackingProtection.OFF_GLOBALLY
+import mozilla.components.concept.toolbar.Toolbar.SiteTrackingProtection.ON_NO_TRACKERS_BLOCKED
+import mozilla.components.concept.toolbar.Toolbar.SiteTrackingProtection.ON_TRACKERS_BLOCKED
+
+/**
+ * Internal widget to display the different icons of tracking protection, relies on the
+ * [SiteTrackingProtection] state of each page.
+ */
+internal class TrackingProtectionIconView @JvmOverloads constructor(
+ context: Context,
+ attrs: AttributeSet? = null,
+ defStyleAttr: Int = 0,
+) : AppCompatImageView(context, attrs, defStyleAttr) {
+ var siteTrackingProtection: SiteTrackingProtection? = null
+ set(value) {
+ if (value != field) {
+ field = value
+ updateIcon()
+ }
+ }
+
+ @VisibleForTesting
+ internal var trackingProtectionTint: Int? = null
+
+ private var iconOnNoTrackersBlocked: Drawable =
+ requireNotNull(AppCompatResources.getDrawable(context, DEFAULT_ICON_ON_NO_TRACKERS_BLOCKED))
+ private var iconOnTrackersBlocked: Drawable =
+ requireNotNull(AppCompatResources.getDrawable(context, DEFAULT_ICON_ON_TRACKERS_BLOCKED))
+ private var disabledForSite: Drawable =
+ requireNotNull(AppCompatResources.getDrawable(context, DEFAULT_ICON_OFF_FOR_A_SITE))
+
+ fun setTint(tint: Int) {
+ trackingProtectionTint = tint
+ }
+
+ fun setIcons(
+ iconOnNoTrackersBlocked: Drawable,
+ iconOnTrackersBlocked: Drawable,
+ disabledForSite: Drawable,
+ ) {
+ this.iconOnNoTrackersBlocked = iconOnNoTrackersBlocked
+ this.iconOnTrackersBlocked = iconOnTrackersBlocked
+ this.disabledForSite = disabledForSite
+
+ updateIcon()
+ }
+
+ @Synchronized
+ private fun updateIcon() {
+ val update = siteTrackingProtection?.toUpdate() ?: return
+
+ isVisible = update.visible
+
+ contentDescription = if (update.contentDescription != null) {
+ context.getString(update.contentDescription)
+ } else {
+ null
+ }
+
+ setOrClearColorFilter(update.drawable)
+ setImageDrawable(update.drawable)
+
+ if (update.drawable is Animatable) {
+ update.drawable.start()
+ }
+ }
+
+ @VisibleForTesting
+ internal fun setOrClearColorFilter(drawable: Drawable?) {
+ if (drawable is Animatable) {
+ clearColorFilter()
+ } else {
+ trackingProtectionTint?.let { setColorFilter(it) }
+ }
+ }
+
+ companion object {
+ val DEFAULT_ICON_ON_NO_TRACKERS_BLOCKED =
+ R.drawable.mozac_ic_tracking_protection_on_no_trackers_blocked
+ val DEFAULT_ICON_ON_TRACKERS_BLOCKED =
+ R.drawable.mozac_ic_tracking_protection_on_trackers_blocked
+ val DEFAULT_ICON_OFF_FOR_A_SITE =
+ R.drawable.mozac_ic_tracking_protection_off_for_a_site
+ }
+
+ private fun SiteTrackingProtection.toUpdate(): Update = when (this) {
+ ON_NO_TRACKERS_BLOCKED -> Update(
+ iconOnNoTrackersBlocked,
+ R.string.mozac_browser_toolbar_content_description_tracking_protection_on_no_trackers_blocked,
+ true,
+ )
+
+ ON_TRACKERS_BLOCKED -> Update(
+ iconOnTrackersBlocked,
+ R.string.mozac_browser_toolbar_content_description_tracking_protection_on_trackers_blocked1,
+ true,
+ )
+
+ OFF_FOR_A_SITE -> Update(
+ disabledForSite,
+ R.string.mozac_browser_toolbar_content_description_tracking_protection_off_for_a_site1,
+ true,
+ )
+
+ OFF_GLOBALLY -> Update(
+ null,
+ null,
+ false,
+ )
+ }
+}
+
+internal class Update(
+ val drawable: Drawable?,
+ @StringRes val contentDescription: Int?,
+ val visible: Boolean,
+)
diff --git a/mobile/android/android-components/components/browser/toolbar2/src/main/java/mozilla/components/browser/toolbar2/edit/EditToolbar.kt b/mobile/android/android-components/components/browser/toolbar2/src/main/java/mozilla/components/browser/toolbar2/edit/EditToolbar.kt
new file mode 100644
index 0000000000..2595ab66e2
--- /dev/null
+++ b/mobile/android/android-components/components/browser/toolbar2/src/main/java/mozilla/components/browser/toolbar2/edit/EditToolbar.kt
@@ -0,0 +1,415 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.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.browser.toolbar2.edit
+
+import android.content.Context
+import android.graphics.Typeface
+import android.graphics.drawable.Drawable
+import android.os.Build
+import android.view.KeyEvent
+import android.view.View
+import android.widget.ImageView
+import androidx.annotation.ColorInt
+import androidx.annotation.VisibleForTesting
+import androidx.annotation.VisibleForTesting.Companion.PRIVATE
+import androidx.constraintlayout.widget.ConstraintLayout
+import androidx.constraintlayout.widget.ConstraintSet
+import androidx.core.content.ContextCompat
+import androidx.core.view.inputmethod.EditorInfoCompat
+import androidx.core.view.isVisible
+import kotlinx.coroutines.CoroutineExceptionHandler
+import kotlinx.coroutines.SupervisorJob
+import kotlinx.coroutines.asCoroutineDispatcher
+import mozilla.components.browser.toolbar2.AsyncFilterListener
+import mozilla.components.browser.toolbar2.BrowserToolbar
+import mozilla.components.browser.toolbar2.R
+import mozilla.components.browser.toolbar2.facts.emitCommitFact
+import mozilla.components.browser.toolbar2.internal.ActionContainer
+import mozilla.components.concept.toolbar.AutocompleteDelegate
+import mozilla.components.concept.toolbar.Toolbar
+import mozilla.components.support.base.log.logger.Logger
+import mozilla.components.support.base.utils.NamedThreadFactory
+import mozilla.components.support.ktx.android.view.showKeyboard
+import mozilla.components.ui.autocomplete.InlineAutocompleteEditText
+import java.util.concurrent.Executors
+import mozilla.components.ui.colors.R as colorsR
+
+private const val AUTOCOMPLETE_QUERY_THREADS = 3
+
+/**
+ * Sub-component of the browser toolbar responsible for allowing the user to edit the URL ("edit mode").
+ *
+ * Structure:
+ * +------+--------------------+---------------------------+------------------+------+
+ * | icon | edit actions start | url | edit actions end | exit |
+ * +------+--------------------+---------------------------+------------------+------+
+ *
+ * - icon: Optional icon that will be shown in front of the URL.
+ * - edit actions start: Optional action icons injected by other components in front of the URL
+ * (e.g. search engines).
+ * - url: Editable URL of the currently displayed website.
+ * - edit actions end: Optional action icons injected by other components after the URL
+ * (e.g. barcode scanner).
+ * - exit: Button that switches back to display mode or invoke an app-defined callback.
+ */
+@Suppress("LargeClass")
+class EditToolbar internal constructor(
+ context: Context,
+ private val toolbar: BrowserToolbar,
+ internal val rootView: View,
+) {
+ private val logger = Logger("EditToolbar")
+
+ /**
+ * Data class holding the customizable colors in "edit mode".
+ *
+ * @property clear Color tint used for the "cancel" icon to leave "edit mode".
+ * @property icon Color tint of the icon displayed in front of the URL.
+ * @property hint Text color of the hint shown when the URL field is empty.
+ * @property text Text color of the URL.
+ * @property suggestionBackground The background color used for autocomplete suggestions.
+ * @property suggestionForeground The foreground color used for autocomplete suggestions.
+ * @property pageActionSeparator Color tint of separator dividing page actions.
+ */
+ data class Colors(
+ @ColorInt val clear: Int,
+ @ColorInt val erase: Int,
+ @ColorInt val icon: Int?,
+ @ColorInt val hint: Int,
+ @ColorInt val text: Int,
+ @ColorInt val suggestionBackground: Int,
+ @ColorInt val suggestionForeground: Int?,
+ @ColorInt val pageActionSeparator: Int,
+ )
+
+ private val autocompleteDispatcher = SupervisorJob() +
+ Executors.newFixedThreadPool(
+ AUTOCOMPLETE_QUERY_THREADS,
+ NamedThreadFactory("EditToolbar"),
+ ).asCoroutineDispatcher() +
+ CoroutineExceptionHandler { _, throwable ->
+ logger.error("Error while processing autocomplete input", throwable)
+ }
+
+ @VisibleForTesting(otherwise = PRIVATE)
+ internal val views = EditToolbarViews(
+ background = rootView.findViewById(R.id.mozac_browser_toolbar_background),
+ icon = rootView.findViewById(R.id.mozac_browser_toolbar_edit_icon),
+ editActionsStart = rootView.findViewById(R.id.mozac_browser_toolbar_edit_actions_start),
+ editActionsEnd = rootView.findViewById(R.id.mozac_browser_toolbar_edit_actions_end),
+ clear = rootView.findViewById<ImageView>(R.id.mozac_browser_toolbar_clear_view).apply {
+ setOnClickListener {
+ onClear()
+ }
+ },
+ erase = rootView.findViewById<ImageView>(R.id.mozac_browser_toolbar_erase_view).apply {
+ setOnClickListener {
+ onClear()
+ }
+ },
+ url = rootView.findViewById<InlineAutocompleteEditText>(
+ R.id.mozac_browser_toolbar_edit_url_view,
+ ).apply {
+ setOnCommitListener {
+ // We emit the fact before notifying the listener because otherwise the listener may cause a focus
+ // change which may reset the autocomplete state that we want to report here.
+ emitCommitFact(autocompleteResult)
+
+ toolbar.onUrlEntered(text.toString())
+ }
+
+ setOnTextChangeListener { text, _ ->
+ onTextChanged(text)
+ }
+
+ setUrlGoneMargin(
+ ConstraintSet.END,
+ context.resources.getDimensionPixelSize(R.dimen.mozac_browser_toolbar_url_gone_margin_end),
+ )
+
+ setOnDispatchKeyEventPreImeListener { event ->
+ if (event?.keyCode == KeyEvent.KEYCODE_BACK && editListener?.onCancelEditing() != false) {
+ toolbar.displayMode()
+ }
+ false
+ }
+ },
+ pageActionSeparator = rootView.findViewById(R.id.mozac_browser_action_separator),
+ )
+
+ /**
+ * Customizable colors in "edit mode".
+ */
+ var colors: Colors = Colors(
+ clear = ContextCompat.getColor(context, colorsR.color.photonWhite),
+ erase = ContextCompat.getColor(context, colorsR.color.photonWhite),
+ icon = null,
+ hint = views.url.currentHintTextColor,
+ text = views.url.currentTextColor,
+ suggestionBackground = views.url.autoCompleteBackgroundColor,
+ suggestionForeground = views.url.autoCompleteForegroundColor,
+ pageActionSeparator = ContextCompat.getColor(context, colorsR.color.photonGrey80),
+ )
+ set(value) {
+ field = value
+
+ views.clear.setColorFilter(value.clear)
+
+ views.erase.setColorFilter(value.erase)
+
+ if (value.icon != null) {
+ views.icon.setColorFilter(value.icon)
+ }
+
+ views.url.setHintTextColor(value.hint)
+ views.url.setTextColor(value.text)
+ views.url.autoCompleteBackgroundColor = value.suggestionBackground
+ views.url.autoCompleteForegroundColor = value.suggestionForeground
+ views.pageActionSeparator.setBackgroundColor(value.pageActionSeparator)
+ }
+
+ /**
+ * Sets the background that will be drawn behind the URL, icon and edit actions.
+ */
+ fun setUrlBackground(background: Drawable?) {
+ views.background.setImageDrawable(background)
+ }
+
+ /**
+ * Sets an icon that will be drawn in front of the URL.
+ */
+ fun setIcon(icon: Drawable, contentDescription: String) {
+ views.icon.setImageDrawable(icon)
+ views.icon.contentDescription = contentDescription
+ views.icon.visibility = View.VISIBLE
+ }
+
+ /**
+ * Sets a click listener on the icon view
+ */
+ fun setIconClickListener(listener: ((View) -> Unit)?) {
+ views.icon.setOnClickListener(listener)
+ }
+
+ /**
+ * Sets the text to be displayed when the URL of the toolbar is empty.
+ */
+ var hint: String
+ get() = views.url.hint.toString()
+ set(value) { views.url.hint = value }
+
+ /**
+ * Sets the size of the text for the URL/search term displayed in the toolbar.
+ */
+ var textSize: Float
+ get() = views.url.textSize
+ set(value) {
+ views.url.textSize = value
+ }
+
+ /**
+ * Sets the typeface of the text for the URL/search term displayed in the toolbar.
+ */
+ var typeface: Typeface
+ get() = views.url.typeface
+ set(value) { views.url.typeface = value }
+
+ /**
+ * Sets a listener to be invoked when focus of the URL input view (in edit mode) changed.
+ */
+ fun setOnEditFocusChangeListener(listener: (Boolean) -> Unit) {
+ views.url.onFocusChangeListener = View.OnFocusChangeListener { _, hasFocus ->
+ listener.invoke(hasFocus)
+ }
+ }
+
+ /**
+ * Focuses the url input field and shows the virtual keyboard if needed.
+ */
+ fun focus() {
+ views.url.run {
+ if (!hasFocus()) {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) {
+ // On Android 14 this needs to be called before requestFocus() in order to receive focus.
+ isFocusableInTouchMode = true
+ }
+ requestFocus()
+ showKeyboard()
+ }
+ }
+ }
+
+ internal fun stopEditing() {
+ editListener?.onStopEditing()
+ }
+
+ internal fun startEditing() {
+ editListener?.onStartEditing()
+ }
+
+ internal var editListener: Toolbar.OnEditListener? = null
+
+ internal fun setAutocompleteListener(filter: suspend (String, AutocompleteDelegate) -> Unit) {
+ views.url.setOnFilterListener(
+ AsyncFilterListener(views.url, autocompleteDispatcher, filter),
+ )
+ }
+
+ /**
+ * Attempt to restart the autocomplete functionality with the current user input.
+ */
+ internal fun refreshAutocompleteSuggestion() {
+ views.url.refreshAutocompleteSuggestions()
+ }
+
+ internal fun invalidateActions() {
+ views.editActionsStart.invalidateActions()
+ views.editActionsEnd.invalidateActions()
+ }
+
+ internal fun addEditActionStart(action: Toolbar.Action) {
+ views.editActionsStart.addAction(action)
+ }
+
+ internal fun addEditActionEnd(action: Toolbar.Action) {
+ views.editActionsEnd.addAction(action)
+ }
+
+ internal fun removeEditActionEnd(action: Toolbar.Action) {
+ views.editActionsEnd.removeAction(action)
+ }
+
+ /**
+ * Updates the text of the URL input field. Note: this does *not* affect the value of url itself
+ * and is only a visual change
+ */
+ fun updateUrl(
+ url: String,
+ shouldAutoComplete: Boolean = false,
+ shouldHighlight: Boolean = false,
+ shouldAppend: Boolean = false,
+ ): String {
+ if (shouldAppend) {
+ views.url.appendText(url, shouldAutoComplete)
+ } else {
+ views.url.setText(url, shouldAutoComplete)
+ }
+ views.clear.isVisible = url.isNotBlank() && !toolbar.isNavBarEnabled
+ views.erase.isVisible = url.isNotBlank() && toolbar.isNavBarEnabled
+
+ if (shouldHighlight) {
+ views.url.setSelection(views.url.text.length - url.length, views.url.text.length)
+ }
+ return views.url.text.toString()
+ }
+
+ /**
+ * Select the entire text in the URL input field.
+ */
+ internal fun selectAll() {
+ views.url.selectAll()
+ }
+
+ /**
+ * Places the cursor at the end of the URL input field.
+ */
+ internal fun selectEnd() {
+ views.url.setSelection(views.url.text.length)
+ }
+
+ /**
+ * Applies the given search terms for further editing, requesting new suggestions along the way.
+ */
+ internal fun editSuggestion(searchTerms: String) {
+ updateUrl(searchTerms)
+ views.url.setSelection(views.url.text.length)
+ focus()
+
+ editListener?.onTextChanged(searchTerms)
+ }
+
+ /**
+ * Sets/gets private mode.
+ *
+ * In private mode the IME should not update any personalized data such as typing history and personalized language
+ * model based on what the user typed.
+ */
+ internal var private: Boolean
+ get() = (views.url.imeOptions and EditorInfoCompat.IME_FLAG_NO_PERSONALIZED_LEARNING) != 0
+ set(value) {
+ views.url.imeOptions = if (value) {
+ views.url.imeOptions or EditorInfoCompat.IME_FLAG_NO_PERSONALIZED_LEARNING
+ } else {
+ views.url.imeOptions and (EditorInfoCompat.IME_FLAG_NO_PERSONALIZED_LEARNING.inv())
+ }
+ }
+
+ private fun onClear() {
+ // We set text to an empty string instead of using clear to avoid #3612.
+ views.url.setText("")
+ editListener?.onInputCleared()
+ }
+
+ private fun setUrlGoneMargin(anchor: Int, dimen: Int) {
+ val set = ConstraintSet()
+ val container = rootView.findViewById<ConstraintLayout>(
+ R.id.mozac_browser_toolbar_container,
+ )
+ set.clone(container)
+ set.setGoneMargin(R.id.mozac_browser_toolbar_edit_url_view, anchor, dimen)
+ set.applyTo(container)
+ }
+
+ private fun onTextChanged(text: String) {
+ views.clear.isVisible = text.isNotBlank() && !toolbar.isNavBarEnabled
+ views.erase.isVisible = text.isNotBlank() && toolbar.isNavBarEnabled
+ views.editActionsEnd.autoHideAction(text.isEmpty())
+
+ /*
+ We use margin_gone instead of margin to take into account both the actionContainer(which in
+ most cases is gone) and the clear button.
+ */
+ if (text.isNotBlank()) {
+ setUrlGoneMargin(ConstraintSet.END, 0)
+ } else {
+ setUrlGoneMargin(
+ ConstraintSet.END,
+ rootView.resources.getDimensionPixelSize(
+ R.dimen.mozac_browser_toolbar_url_gone_margin_end,
+ ),
+ )
+ }
+ editListener?.onTextChanged(text)
+ }
+
+ /**
+ * Hides the page action separator in edit mode.
+ */
+ fun hidePageActionSeparator() {
+ views.pageActionSeparator.isVisible = false
+ }
+
+ /**
+ * Shows the page action separator in edit mode.
+ */
+ fun showPageActionSeparator() {
+ views.pageActionSeparator.isVisible = true
+ }
+}
+
+/**
+ * Internal holder for view references.
+ */
+@Suppress("LongParameterList")
+internal class EditToolbarViews(
+ val background: ImageView,
+ val icon: ImageView,
+ val editActionsStart: ActionContainer,
+ val editActionsEnd: ActionContainer,
+ val clear: ImageView,
+ val erase: ImageView,
+ val url: InlineAutocompleteEditText,
+ val pageActionSeparator: View,
+)
diff --git a/mobile/android/android-components/components/browser/toolbar2/src/main/java/mozilla/components/browser/toolbar2/facts/ToolbarFacts.kt b/mobile/android/android-components/components/browser/toolbar2/src/main/java/mozilla/components/browser/toolbar2/facts/ToolbarFacts.kt
new file mode 100644
index 0000000000..06f09ea18d
--- /dev/null
+++ b/mobile/android/android-components/components/browser/toolbar2/src/main/java/mozilla/components/browser/toolbar2/facts/ToolbarFacts.kt
@@ -0,0 +1,60 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.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.browser.toolbar2.facts
+
+import mozilla.components.support.base.Component
+import mozilla.components.support.base.facts.Action
+import mozilla.components.support.base.facts.Fact
+import mozilla.components.support.base.facts.collect
+import mozilla.components.ui.autocomplete.InlineAutocompleteEditText
+
+/**
+ * Facts emitted for telemetry related to [ToolbarFeature]
+ */
+class ToolbarFacts {
+ /**
+ * Items that specify which portion of the [ToolbarFeature] was interacted with
+ */
+ object Items {
+ const val TOOLBAR = "toolbar"
+ const val MENU = "menu"
+ }
+}
+
+private fun emitToolbarFact(
+ action: Action,
+ item: String,
+ value: String? = null,
+ metadata: Map<String, Any>? = null,
+) {
+ Fact(
+ Component.BROWSER_TOOLBAR,
+ action,
+ item,
+ value,
+ metadata,
+ ).collect()
+}
+
+internal fun emitOpenMenuFact(extras: Map<String, Any>?) {
+ emitToolbarFact(Action.CLICK, ToolbarFacts.Items.MENU, metadata = extras)
+}
+
+internal fun emitCommitFact(
+ autocompleteResult: InlineAutocompleteEditText.AutocompleteResult?,
+) {
+ val metadata = if (autocompleteResult == null) {
+ mapOf(
+ "autocomplete" to false,
+ )
+ } else {
+ mapOf(
+ "autocomplete" to true,
+ "source" to autocompleteResult.source,
+ )
+ }
+
+ emitToolbarFact(Action.COMMIT, ToolbarFacts.Items.TOOLBAR, metadata = metadata)
+}
diff --git a/mobile/android/android-components/components/browser/toolbar2/src/main/java/mozilla/components/browser/toolbar2/internal/ActionContainer.kt b/mobile/android/android-components/components/browser/toolbar2/src/main/java/mozilla/components/browser/toolbar2/internal/ActionContainer.kt
new file mode 100644
index 0000000000..7907dba520
--- /dev/null
+++ b/mobile/android/android-components/components/browser/toolbar2/src/main/java/mozilla/components/browser/toolbar2/internal/ActionContainer.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.browser.toolbar2.internal
+
+import android.content.Context
+import android.transition.TransitionManager
+import android.util.AttributeSet
+import android.view.Gravity
+import android.view.View
+import android.widget.LinearLayout
+import androidx.annotation.VisibleForTesting
+import androidx.core.view.isVisible
+import mozilla.components.browser.toolbar2.R
+import mozilla.components.concept.toolbar.Toolbar
+
+/**
+ * A container [View] for displaying [Toolbar.Action] objects.
+ */
+internal class ActionContainer @JvmOverloads constructor(
+ context: Context,
+ attrs: AttributeSet? = null,
+ defStyleAttr: Int = 0,
+) : LinearLayout(context, attrs, defStyleAttr) {
+ private val actions = mutableListOf<ActionWrapper>()
+ private var actionSize: Int? = null
+
+ init {
+ gravity = Gravity.CENTER_VERTICAL
+ orientation = HORIZONTAL
+ visibility = View.GONE
+
+ context.obtainStyledAttributes(
+ attrs,
+ R.styleable.ActionContainer,
+ defStyleAttr,
+ 0,
+ ).run {
+ actionSize = attrs?.let {
+ getDimensionPixelSize(R.styleable.ActionContainer_actionContainerItemSize, 0)
+ }
+
+ recycle()
+ }
+ }
+
+ fun addAction(action: Toolbar.Action) {
+ val wrapper = ActionWrapper(action)
+
+ if (action.visible()) {
+ visibility = View.VISIBLE
+
+ action.createView(this).let {
+ wrapper.view = it
+ val insertionIndex = calculateInsertionIndex(action)
+ addActionView(it, insertionIndex)
+ }
+ }
+
+ actions.add(wrapper)
+ }
+
+ /**
+ * Essentially calculates the index of an action on toolbar based on a
+ * map [visibleActionIndicesWithWeights] that holds the order
+ * of visible action indices to their weights sorted by weights.
+ * An index is now calculated by finding the immediate next larger weight
+ * compared to the new action's weight. Index of this find becomes the index of the new action.
+ * If not found, action is appended at the end.
+ */
+ @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
+ internal fun calculateInsertionIndex(newAction: Toolbar.Action): Int {
+ if (newAction.weight() == -1) {
+ return -1
+ }
+ val visibleActionIndicesWithWeights = actions.filter { it.actual.visible() }
+ .mapNotNull { actionWrapper ->
+ val index = indexOfChild(actionWrapper.view)
+ if (index != -1) index to actionWrapper.actual.weight() else null
+ }.sortedBy { it.second }
+
+ val insertionIndex = visibleActionIndicesWithWeights.firstOrNull { it.second > newAction.weight() }?.first
+
+ return insertionIndex ?: childCount
+ }
+
+ fun removeAction(action: Toolbar.Action) {
+ actions.find { it.actual == action }?.let {
+ actions.remove(it)
+ removeView(it.view)
+ }
+ }
+
+ fun invalidateActions() {
+ TransitionManager.beginDelayedTransition(this)
+ var updatedVisibility = View.GONE
+
+ for (action in actions) {
+ val visible = action.actual.visible()
+
+ if (visible) {
+ updatedVisibility = View.VISIBLE
+ }
+
+ if (!visible && action.view != null) {
+ removeView(action.view)
+ action.view = null
+ } else if (visible && action.view == null) {
+ action.actual.createView(this).let {
+ action.view = it
+ val insertionIndex = calculateInsertionIndex(action.actual)
+ addActionView(it, insertionIndex)
+ }
+ }
+
+ action.view?.let { action.actual.bind(it) }
+ }
+
+ visibility = updatedVisibility
+ }
+
+ fun autoHideAction(isVisible: Boolean) {
+ for (action in actions) {
+ if (action.actual.autoHide()) {
+ action.view?.isVisible = isVisible
+ }
+ }
+ }
+
+ private fun addActionView(view: View, index: Int) {
+ addView(view, index, LayoutParams(actionSize ?: 0, actionSize ?: 0))
+ }
+}
diff --git a/mobile/android/android-components/components/browser/toolbar2/src/main/java/mozilla/components/browser/toolbar2/internal/ActionWrapper.kt b/mobile/android/android-components/components/browser/toolbar2/src/main/java/mozilla/components/browser/toolbar2/internal/ActionWrapper.kt
new file mode 100644
index 0000000000..8600372f1e
--- /dev/null
+++ b/mobile/android/android-components/components/browser/toolbar2/src/main/java/mozilla/components/browser/toolbar2/internal/ActionWrapper.kt
@@ -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/. */
+
+package mozilla.components.browser.toolbar2.internal
+
+import android.view.View
+import mozilla.components.concept.toolbar.Toolbar
+
+/**
+ * A wrapper helper to pair a Toolbar.Action with an optional View.
+ */
+internal class ActionWrapper(
+ var actual: Toolbar.Action,
+ var view: View? = null,
+)
diff --git a/mobile/android/android-components/components/browser/toolbar2/src/main/res/drawable/mozac_browser_toolbar_icons_vertical_separator.xml b/mobile/android/android-components/components/browser/toolbar2/src/main/res/drawable/mozac_browser_toolbar_icons_vertical_separator.xml
new file mode 100644
index 0000000000..2e366640df
--- /dev/null
+++ b/mobile/android/android-components/components/browser/toolbar2/src/main/res/drawable/mozac_browser_toolbar_icons_vertical_separator.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">
+ <size android:width="@dimen/mozac_browser_toolbar_icons_separator_width"
+ android:height="@dimen/mozac_browser_toolbar_icons_separator_height" />
+ <solid android:color="#aaaaaa" />
+</shape> \ No newline at end of file
diff --git a/mobile/android/android-components/components/browser/toolbar2/src/main/res/drawable/mozac_dot_notification.xml b/mobile/android/android-components/components/browser/toolbar2/src/main/res/drawable/mozac_dot_notification.xml
new file mode 100644
index 0000000000..5469b822af
--- /dev/null
+++ b/mobile/android/android-components/components/browser/toolbar2/src/main/res/drawable/mozac_dot_notification.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/. -->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="8dp"
+ android:height="8dp"
+ android:viewportWidth="10"
+ android:viewportHeight="10">
+ <path
+ android:pathData="M1,5a4,4 0 1,0 8,0a4,4 0 1,0 -8,0"
+ android:strokeWidth="1"
+ android:strokeAlpha=".2"
+ android:fillColor="#fff"
+ android:strokeColor="#000" />
+</vector>
diff --git a/mobile/android/android-components/components/browser/toolbar2/src/main/res/drawable/mozac_ic_site_security.xml b/mobile/android/android-components/components/browser/toolbar2/src/main/res/drawable/mozac_ic_site_security.xml
new file mode 100644
index 0000000000..ab2b8d0e37
--- /dev/null
+++ b/mobile/android/android-components/components/browser/toolbar2/src/main/res/drawable/mozac_ic_site_security.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/. -->
+<selector xmlns:android="http://schemas.android.com/apk/res/android" xmlns:ac="http://schemas.android.com/apk/res-auto">
+ <item
+ android:drawable="@drawable/mozac_ic_lock_24"
+ ac:state_site_secure="true" />
+ <item
+ android:drawable="@drawable/mozac_ic_broken_lock" />
+</selector>
diff --git a/mobile/android/android-components/components/browser/toolbar2/src/main/res/drawable/mozac_ic_tracking_protection_off_for_a_site.xml b/mobile/android/android-components/components/browser/toolbar2/src/main/res/drawable/mozac_ic_tracking_protection_off_for_a_site.xml
new file mode 100644
index 0000000000..250bfbfc4c
--- /dev/null
+++ b/mobile/android/android-components/components/browser/toolbar2/src/main/res/drawable/mozac_ic_tracking_protection_off_for_a_site.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/. -->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ <path android:fillColor="@color/mozac_ui_icons_fill"
+ android:pathData="M17.9,10.83c-0.27,2.81 -0.75,4.18 -2,5.86A6.48,6.48 0,0 1,12 19a7,7 0,0 1,-2.32 -0.92l-1.44,1.43A8.44,8.44 0,0 0,11.89 21h0.22a8.36,8.36 0,0 0,5.33 -3.08c1.53,-2 2.14,-3.72 2.45,-6.89C20,10.28 20,9 20,7.76l-2,2c-0.06,0.47 -0.08,0.82 -0.1,1.07zM20.21,3.83a1,1 0,0 0,-1.42 0l-0.3,0.31a1.86,1.86 0,0 0,-0.31 -0.1L12,3 5.82,4A2.14,2.14 0,0 0,4 6.1c0,1.67 0,3.9 0.11,4.9a12.43,12.43 0,0 0,1.69 5.79l-2,2a1,1 0,0 0,0 1.42,1 1,0 0,0 1.42,0l15,-15a1,1 0,0 0,-0.01 -1.42zM12,10.59L12,7l-4,0.7c0,2 0.07,2.74 0.09,3a11.65,11.65 0,0 0,0.63 3.17l-1.46,1.46a11.13,11.13 0,0 1,-1.16 -4.5C6,10.08 6,8.4 6,6.11A0.15,0.15 0,0 1,6.14 6L12,5l4.79,0.79z" />
+</vector>
diff --git a/mobile/android/android-components/components/browser/toolbar2/src/main/res/drawable/mozac_ic_tracking_protection_on_no_trackers_blocked.xml b/mobile/android/android-components/components/browser/toolbar2/src/main/res/drawable/mozac_ic_tracking_protection_on_no_trackers_blocked.xml
new file mode 100644
index 0000000000..4f81a5602b
--- /dev/null
+++ b/mobile/android/android-components/components/browser/toolbar2/src/main/res/drawable/mozac_ic_tracking_protection_on_no_trackers_blocked.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/. -->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ <path android:fillColor="@color/mozac_ui_icons_fill"
+ android:pathData="M20 6c0-1-0.8-1.9-1.8-2L12 3 5.8 4C4.8 4 4 5 4 6l0.1 5c0.3 3.2 1 5 2.5 7a8.4 8.4 0 0 0 5.3 3h0.2c2.1-0.3 4-1.4 5.3-3 1.6-2 2.2-3.8 2.5-7l0.1-5zm-2.1 4.8a10 10 0 0 1-2 6c-1 1.1-2.4 2-3.9 2.3a6.5 6.5 0 0 1-3.9-2.4 9.9 9.9 0 0 1-2-5.9 67.3 67.3 0 0 1 0-4.9L12 5l5.9 1 0.1 0.2-0.1 4.7zM8 7.6v3c0.3 2.7 0.8 3.7 1.7 5 0.6 0.6 1.4 1.2 2.3 1.4V7l-4 0.6z" />
+</vector>
diff --git a/mobile/android/android-components/components/browser/toolbar2/src/main/res/drawable/mozac_ic_tracking_protection_on_trackers_blocked.xml b/mobile/android/android-components/components/browser/toolbar2/src/main/res/drawable/mozac_ic_tracking_protection_on_trackers_blocked.xml
new file mode 100644
index 0000000000..4f81a5602b
--- /dev/null
+++ b/mobile/android/android-components/components/browser/toolbar2/src/main/res/drawable/mozac_ic_tracking_protection_on_trackers_blocked.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/. -->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ <path android:fillColor="@color/mozac_ui_icons_fill"
+ android:pathData="M20 6c0-1-0.8-1.9-1.8-2L12 3 5.8 4C4.8 4 4 5 4 6l0.1 5c0.3 3.2 1 5 2.5 7a8.4 8.4 0 0 0 5.3 3h0.2c2.1-0.3 4-1.4 5.3-3 1.6-2 2.2-3.8 2.5-7l0.1-5zm-2.1 4.8a10 10 0 0 1-2 6c-1 1.1-2.4 2-3.9 2.3a6.5 6.5 0 0 1-3.9-2.4 9.9 9.9 0 0 1-2-5.9 67.3 67.3 0 0 1 0-4.9L12 5l5.9 1 0.1 0.2-0.1 4.7zM8 7.6v3c0.3 2.7 0.8 3.7 1.7 5 0.6 0.6 1.4 1.2 2.3 1.4V7l-4 0.6z" />
+</vector>
diff --git a/mobile/android/android-components/components/browser/toolbar2/src/main/res/layout/mozac_browser_toolbar_displaytoolbar.xml b/mobile/android/android-components/components/browser/toolbar2/src/main/res/layout/mozac_browser_toolbar_displaytoolbar.xml
new file mode 100644
index 0000000000..5a5f779a70
--- /dev/null
+++ b/mobile/android/android-components/components/browser/toolbar2/src/main/res/layout/mozac_browser_toolbar_displaytoolbar.xml
@@ -0,0 +1,175 @@
+<?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/. -->
+<mozilla.components.browser.toolbar2.display.DisplayToolbarView xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:app="http://schemas.android.com/apk/res-auto"
+ xmlns:mozac="http://schemas.android.com/apk/res-auto"
+ xmlns:tools="http://schemas.android.com/tools"
+ android:layout_width="match_parent"
+ android:layout_height="56dp"
+ android:orientation="vertical">
+
+ <!-- Navigation -->
+
+ <mozilla.components.browser.toolbar2.internal.ActionContainer
+ android:id="@+id/mozac_browser_toolbar_navigation_actions"
+ android:layout_width="wrap_content"
+ android:layout_height="48dp"
+ android:layout_marginTop="4dp"
+ app:layout_constraintStart_toStartOf="parent"
+ app:layout_constraintTop_toTopOf="parent"
+ mozac:actionContainerItemSize="48dp"
+ tools:layout_width="48dp" />
+
+ <!-- URL container -->
+
+ <ImageView
+ android:id="@+id/mozac_browser_toolbar_background"
+ android:layout_width="0dp"
+ android:layout_height="40dp"
+ android:layout_marginTop="8dp"
+ android:layout_marginEnd="8dp"
+ android:importantForAccessibility="no"
+ app:layout_constraintEnd_toStartOf="@+id/mozac_browser_toolbar_browser_actions"
+ app:layout_constraintStart_toEndOf="@+id/mozac_browser_toolbar_navigation_actions"
+ app:layout_constraintTop_toTopOf="parent"
+ app:layout_goneMarginEnd="0dp" />
+
+ <!-- URL indicators (lock, tracking protection, ..) -->
+
+ <ImageView
+ android:id="@+id/mozac_browser_toolbar_empty_indicator"
+ android:layout_width="40dp"
+ android:layout_height="40dp"
+ android:layout_marginTop="8dp"
+ android:scaleType="center"
+ android:visibility="gone"
+ app:layout_constraintStart_toStartOf="@id/mozac_browser_toolbar_background"
+ app:layout_constraintTop_toTopOf="parent"
+ app:srcCompat="@drawable/mozac_ic_search_24"
+ tools:ignore="ContentDescription" />
+
+ <mozilla.components.browser.toolbar2.display.TrackingProtectionIconView
+ android:id="@+id/mozac_browser_toolbar_tracking_protection_indicator"
+ android:layout_width="40dp"
+ android:layout_height="40dp"
+ android:layout_marginTop="8dp"
+ android:scaleType="center"
+ android:visibility="gone"
+ app:layout_constraintStart_toEndOf="@id/mozac_browser_toolbar_empty_indicator"
+ app:layout_constraintTop_toTopOf="parent"
+ app:srcCompat="@drawable/mozac_ic_tracking_protection_on_no_trackers_blocked" />
+
+ <ImageView
+ android:id="@+id/mozac_browser_toolbar_separator"
+ android:layout_width="@dimen/mozac_browser_toolbar_icons_separator_width"
+ android:layout_height="40dp"
+ android:layout_marginTop="8dp"
+ android:importantForAccessibility="no"
+ android:scaleType="center"
+ android:visibility="gone"
+ app:layout_constraintStart_toEndOf="@+id/mozac_browser_toolbar_tracking_protection_indicator"
+ app:layout_constraintTop_toTopOf="parent"
+ app:srcCompat="@drawable/mozac_browser_toolbar_icons_vertical_separator" />
+
+ <mozilla.components.browser.toolbar2.display.SiteSecurityIconView
+ android:id="@+id/mozac_browser_toolbar_security_indicator"
+ android:layout_width="40dp"
+ android:layout_height="40dp"
+ android:layout_marginTop="8dp"
+ android:contentDescription="@string/mozac_browser_toolbar_content_description_site_info"
+ android:scaleType="center"
+ app:layout_constraintStart_toEndOf="@+id/mozac_browser_toolbar_separator"
+ app:layout_constraintTop_toTopOf="parent"
+ app:srcCompat="@drawable/mozac_ic_site_security" />
+
+ <mozilla.components.browser.toolbar2.display.HighlightView
+ android:id="@+id/mozac_browser_toolbar_permission_indicator"
+ android:layout_width="10dp"
+ android:layout_height="10dp"
+ android:importantForAccessibility="no"
+ app:layout_constraintBottom_toBottomOf="@+id/mozac_browser_toolbar_security_indicator"
+ app:layout_constraintEnd_toEndOf="@+id/mozac_browser_toolbar_security_indicator"
+ android:layout_marginEnd="8dp"
+ android:layout_marginBottom="8dp"
+ android:visibility="gone"
+ android:tint="@color/photonBlue40"
+ app:srcCompat="@drawable/mozac_dot_notification" />
+
+ <!-- URL & Title -->
+
+ <mozilla.components.browser.toolbar2.display.OriginView
+ android:id="@+id/mozac_browser_toolbar_origin_view"
+ android:layout_width="0dp"
+ android:layout_height="40dp"
+ android:layout_marginTop="8dp"
+ android:paddingEnd="@dimen/mozac_browser_toolbar_origin_padding_end"
+ app:layout_constraintEnd_toStartOf="@+id/mozac_browser_toolbar_action_separator"
+ app:layout_constraintStart_toEndOf="@+id/mozac_browser_toolbar_security_indicator"
+ app:layout_constraintTop_toTopOf="parent"
+ app:layout_goneMarginStart="8dp"
+ app:layout_goneMarginTop="8dp" />
+
+ <View
+ android:id="@+id/mozac_browser_toolbar_action_separator"
+ android:layout_width="@dimen/mozac_browser_toolbar_page_action_separator_width"
+ android:layout_height="40dp"
+ android:layout_marginTop="8dp"
+ android:layout_marginStart="8dp"
+ android:visibility="gone"
+ android:importantForAccessibility="no"
+ android:scaleType="center"
+ app:layout_constraintStart_toEndOf="@+id/mozac_browser_toolbar_origin_view"
+ app:layout_constraintEnd_toStartOf="@id/mozac_browser_toolbar_page_actions"
+ app:layout_constraintTop_toTopOf="parent" />
+
+ <!-- Page actions -->
+
+ <mozilla.components.browser.toolbar2.internal.ActionContainer
+ android:id="@+id/mozac_browser_toolbar_page_actions"
+ android:layout_width="wrap_content"
+ android:layout_height="48dp"
+ android:layout_marginTop="4dp"
+ android:scaleType="center"
+ app:layout_constraintEnd_toEndOf="@+id/mozac_browser_toolbar_background"
+ app:layout_constraintTop_toTopOf="parent"
+ mozac:actionContainerItemSize="48dp"
+ tools:layout_width="48dp" />
+
+ <!-- Browser Actions -->
+
+ <mozilla.components.browser.toolbar2.internal.ActionContainer
+ android:id="@+id/mozac_browser_toolbar_browser_actions"
+ android:layout_width="wrap_content"
+ android:layout_height="48dp"
+ android:layout_marginTop="4dp"
+ app:layout_constraintEnd_toStartOf="@id/mozac_browser_toolbar_menu"
+ app:layout_constraintTop_toTopOf="parent"
+ mozac:actionContainerItemSize="48dp"
+ tools:layout_width="48dp" />
+
+ <!-- Menu -->
+
+ <mozilla.components.browser.menu.view.MenuButton
+ android:id="@+id/mozac_browser_toolbar_menu"
+ android:layout_width="36dp"
+ android:layout_height="48dp"
+ android:layout_marginTop="4dp"
+ android:background="?android:attr/selectableItemBackgroundBorderless"
+ app:layout_constraintEnd_toEndOf="parent"
+ app:layout_constraintTop_toTopOf="parent" />
+
+ <!-- Progress Bar -->
+
+ <ProgressBar
+ android:id="@+id/mozac_browser_toolbar_progress"
+ style="?android:attr/progressBarStyleHorizontal"
+ android:layout_width="0dp"
+ android:layout_height="@dimen/mozac_browser_toolbar_progress_bar_height"
+ android:visibility="gone"
+ app:layout_constraintBottom_toBottomOf="parent"
+ app:layout_constraintEnd_toEndOf="parent"
+ app:layout_constraintStart_toStartOf="parent" />
+
+</mozilla.components.browser.toolbar2.display.DisplayToolbarView>
diff --git a/mobile/android/android-components/components/browser/toolbar2/src/main/res/layout/mozac_browser_toolbar_edittoolbar.xml b/mobile/android/android-components/components/browser/toolbar2/src/main/res/layout/mozac_browser_toolbar_edittoolbar.xml
new file mode 100644
index 0000000000..3325cd099f
--- /dev/null
+++ b/mobile/android/android-components/components/browser/toolbar2/src/main/res/layout/mozac_browser_toolbar_edittoolbar.xml
@@ -0,0 +1,116 @@
+<?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/. -->
+<androidx.constraintlayout.widget.ConstraintLayout
+ android:id="@+id/mozac_browser_toolbar_container"
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:app="http://schemas.android.com/apk/res-auto"
+ xmlns:mozac="http://schemas.android.com/apk/res-auto"
+ xmlns:tools="http://schemas.android.com/tools"
+ android:layout_width="match_parent"
+ android:orientation="vertical"
+ android:layout_height="56dp">
+
+ <ImageView
+ android:id="@+id/mozac_browser_toolbar_background"
+ android:layout_width="0dp"
+ android:layout_height="40dp"
+ android:layout_marginTop="8dp"
+ android:layout_marginStart="8dp"
+ android:layout_marginEnd="8dp"
+ android:importantForAccessibility="no"
+ app:layout_constraintStart_toStartOf="parent"
+ app:layout_constraintEnd_toEndOf="parent"
+ app:layout_constraintTop_toTopOf="parent" />
+
+ <ImageView
+ android:id="@+id/mozac_browser_toolbar_edit_icon"
+ android:layout_width="40dp"
+ android:layout_height="40dp"
+ android:scaleType="center"
+ app:layout_constraintTop_toTopOf="parent"
+ app:layout_constraintStart_toStartOf="@id/mozac_browser_toolbar_background"
+ app:srcCompat="@drawable/mozac_ic_search_24"
+ android:visibility="gone"
+ tools:ignore="ContentDescription"
+ android:layout_marginTop="8dp" />
+
+ <mozilla.components.browser.toolbar2.internal.ActionContainer
+ android:id="@+id/mozac_browser_toolbar_edit_actions_start"
+ android:layout_width="wrap_content"
+ android:layout_height="40dp"
+ android:layout_marginTop="8dp"
+ app:layout_constraintTop_toTopOf="parent"
+ app:layout_constraintStart_toEndOf="@id/mozac_browser_toolbar_edit_icon"
+ mozac:actionContainerItemSize="56dp"
+ tools:layout_width="56dp" />
+
+ <mozilla.components.ui.autocomplete.InlineAutocompleteEditText
+ android:id="@+id/mozac_browser_toolbar_edit_url_view"
+ android:layout_width="0dp"
+ android:layout_marginTop="8dp"
+ android:layout_height="40dp"
+ android:width="100dp"
+ android:height="100dp"
+ android:imeOptions="actionGo|flagNoExtractUi|flagNoFullscreen"
+ android:inputType="textUri|text"
+ android:lines="1"
+ android:gravity="center_vertical"
+ android:background="#00000000"
+ android:textSize="15sp"
+ app:layout_goneMarginStart="8dp"
+ app:layout_constraintStart_toEndOf="@id/mozac_browser_toolbar_edit_actions_start"
+ app:layout_constraintEnd_toStartOf="@id/mozac_browser_toolbar_erase_view"
+ app:layout_constraintTop_toTopOf="parent" />
+
+ <ImageView
+ android:id="@+id/mozac_browser_toolbar_erase_view"
+ android:layout_width="44dp"
+ android:layout_height="44dp"
+ android:contentDescription="@string/mozac_clear_button_description"
+ android:scaleType="center"
+ app:srcCompat="@drawable/mozac_ic_cross_circle_fill_20"
+ android:visibility="gone"
+ app:layout_constraintBottom_toBottomOf="parent"
+ app:layout_constraintStart_toEndOf="@+id/mozac_browser_toolbar_edit_url_view"
+ app:layout_constraintEnd_toStartOf="@id/mozac_browser_action_separator"
+ app:layout_constraintTop_toTopOf="parent" />
+
+ <View
+ android:id="@+id/mozac_browser_action_separator"
+ android:layout_width="@dimen/mozac_browser_toolbar_page_action_separator_width"
+ android:layout_height="40dp"
+ android:layout_marginTop="8dp"
+ android:visibility="gone"
+ android:importantForAccessibility="no"
+ android:scaleType="center"
+ app:layout_constraintStart_toEndOf="@+id/mozac_browser_toolbar_erase_view"
+ app:layout_constraintEnd_toStartOf="@id/mozac_browser_toolbar_edit_actions_end"
+ app:layout_constraintTop_toTopOf="parent" />
+
+ <mozilla.components.browser.toolbar2.internal.ActionContainer
+ android:id="@+id/mozac_browser_toolbar_edit_actions_end"
+ android:layout_width="wrap_content"
+ android:layout_height="40dp"
+ android:layout_marginTop="8dp"
+ app:layout_constraintTop_toTopOf="parent"
+ app:layout_constraintEnd_toStartOf="@id/mozac_browser_toolbar_clear_view"
+ mozac:actionContainerItemSize="40dp"
+ tools:layout_width="48dp" />
+
+ <ImageView
+ android:id="@+id/mozac_browser_toolbar_clear_view"
+ android:layout_width="40dp"
+ android:layout_height="40dp"
+ android:width="100dp"
+ android:height="100dp"
+ android:contentDescription="@string/mozac_clear_button_description"
+ android:scaleType="center"
+ app:srcCompat="@drawable/mozac_ic_cross_circle_fill_24"
+ android:visibility="gone"
+ app:layout_constraintBottom_toBottomOf="parent"
+ app:layout_constraintEnd_toEndOf="@+id/mozac_browser_toolbar_background"
+ app:layout_constraintTop_toTopOf="parent" />
+
+</androidx.constraintlayout.widget.ConstraintLayout>
diff --git a/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-am/strings.xml b/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-am/strings.xml
new file mode 100644
index 0000000000..eda99f879b
--- /dev/null
+++ b/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-am/strings.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description (not visible, for screen readers etc.): Description for the overflow menu button in the browser toolbar. -->
+ <string name="mozac_browser_toolbar_menu_button">ምናሌ</string>
+ <string name="mozac_clear_button_description">አጽዳ</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection enabled, but none trackers have been blocked or detected. -->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_on_no_trackers_blocked">የመከታተያ ጥበቃ በርቷል</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection enabled, and trackers have been blocked or detected.-->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_on_trackers_blocked1">የክትትል ጥበቃ መከታተያዎችን አግዷል</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection disabled.-->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_off_for_a_site1">የክትትል ጥበቃ ለዚህ ድረ-ገፅ ጠፍቷል</string>
+ <!-- Content description: For the site security information icon (the site security icon).-->
+ <string name="mozac_browser_toolbar_content_description_site_info">የድረ-ገፅ መረጃ</string>
+ <!-- Announcement made by the screen reader when the progress bar is shown and a page is loading -->
+ <string name="mozac_browser_toolbar_progress_loading">በመጫን ላይ</string>
+ <!-- Content description: For the autoplay toolbar icon, it is set when the auto play permission is blocking content playing.-->
+ <string name="mozac_browser_toolbar_content_description_autoplay_blocked">አንዳንድ ይዘቶች በራስ አጫውት ቅንብር ታግደዋል</string>
+</resources>
diff --git a/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-an/strings.xml b/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-an/strings.xml
new file mode 100644
index 0000000000..14b40de38e
--- /dev/null
+++ b/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-an/strings.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description (not visible, for screen readers etc.): Description for the overflow menu button in the browser toolbar. -->
+ <string name="mozac_browser_toolbar_menu_button">Menú</string>
+ <string name="mozac_clear_button_description">Borrar</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection enabled, but none trackers have been blocked or detected. -->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_on_no_trackers_blocked">La protección contra seguimiento ye activada</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection enabled, and trackers have been blocked or detected.-->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_on_trackers_blocked1">Las protección contra seguimiento ha blocau elementos de seguimiento</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection disabled.-->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_off_for_a_site1">La protección de seguimiento ye desactivada en este puesto</string>
+ <!-- Content description: For the site security information icon (the site security icon).-->
+ <string name="mozac_browser_toolbar_content_description_site_info">Información d’o puesto</string>
+ <!-- Announcement made by the screen reader when the progress bar is shown and a page is loading -->
+ <string name="mozac_browser_toolbar_progress_loading">Se ye cargando</string>
+ </resources>
diff --git a/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-ar/strings.xml b/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-ar/strings.xml
new file mode 100644
index 0000000000..a4a01aa836
--- /dev/null
+++ b/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-ar/strings.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description (not visible, for screen readers etc.): Description for the overflow menu button in the browser toolbar. -->
+ <string name="mozac_browser_toolbar_menu_button">القائمة</string>
+ <string name="mozac_clear_button_description">امسح</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection enabled, but none trackers have been blocked or detected. -->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_on_no_trackers_blocked">الحماية من التعقّب مفعّلة</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection enabled, and trackers have been blocked or detected.-->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_on_trackers_blocked1">حجبت الحماية من التعقّب بعض المتعقّبات</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection disabled.-->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_off_for_a_site1">عُطّلت الحماية من التعقب في هذا الموقع</string>
+ <!-- Content description: For the site security information icon (the site security icon).-->
+ <string name="mozac_browser_toolbar_content_description_site_info">معلومات الموقع</string>
+ <!-- Announcement made by the screen reader when the progress bar is shown and a page is loading -->
+ <string name="mozac_browser_toolbar_progress_loading">يُحمّل</string>
+ <!-- Content description: For the autoplay toolbar icon, it is set when the auto play permission is blocking content playing.-->
+ <string name="mozac_browser_toolbar_content_description_autoplay_blocked">حجب إعداد التشغيل التلقائي بعض المحتوى</string>
+</resources>
diff --git a/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-ast/strings.xml b/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-ast/strings.xml
new file mode 100644
index 0000000000..6cb4e96a9a
--- /dev/null
+++ b/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-ast/strings.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description (not visible, for screen readers etc.): Description for the overflow menu button in the browser toolbar. -->
+ <string name="mozac_browser_toolbar_menu_button">Menú</string>
+ <string name="mozac_clear_button_description">Borrar</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection enabled, but none trackers have been blocked or detected. -->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_on_no_trackers_blocked">La proteición antirrastrexu ta activada</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection enabled, and trackers have been blocked or detected.-->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_on_trackers_blocked1">La proteición antirrastrexu bloquió rastrexadores</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection disabled.-->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_off_for_a_site1">La proteición antirrastrexu ta desactivada nesti sitiu</string>
+ <!-- Content description: For the site security information icon (the site security icon).-->
+ <string name="mozac_browser_toolbar_content_description_site_info">Información del sitiu</string>
+ <!-- Announcement made by the screen reader when the progress bar is shown and a page is loading -->
+ <string name="mozac_browser_toolbar_progress_loading">Cargando</string>
+ <!-- Content description: For the autoplay toolbar icon, it is set when the auto play permission is blocking content playing.-->
+ <string name="mozac_browser_toolbar_content_description_autoplay_blocked">La configuración de la reproducción automática bloquió parte del conteníu</string>
+</resources>
diff --git a/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-az/strings.xml b/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-az/strings.xml
new file mode 100644
index 0000000000..0ccb692a99
--- /dev/null
+++ b/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-az/strings.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description (not visible, for screen readers etc.): Description for the overflow menu button in the browser toolbar. -->
+ <string name="mozac_browser_toolbar_menu_button">Menyu</string>
+ <string name="mozac_clear_button_description">Təmizlə</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection enabled, but none trackers have been blocked or detected. -->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_on_no_trackers_blocked">İzlənmə Qoruması açıqdır</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection enabled, and trackers have been blocked or detected.-->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_on_trackers_blocked1">İzlənmə Qoruması izləyiciləri əngəllədi</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection disabled.-->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_off_for_a_site1">İzlənmə Qoruması bu sayt üçün sönülüdür</string>
+ <!-- Content description: For the site security information icon (the site security icon).-->
+ <string name="mozac_browser_toolbar_content_description_site_info">Sayt məlumatları</string>
+ <!-- Announcement made by the screen reader when the progress bar is shown and a page is loading -->
+ <string name="mozac_browser_toolbar_progress_loading">Yüklənir</string>
+ </resources>
diff --git a/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-azb/strings.xml b/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-azb/strings.xml
new file mode 100644
index 0000000000..d2901fff35
--- /dev/null
+++ b/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-azb/strings.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description (not visible, for screen readers etc.): Description for the overflow menu button in the browser toolbar. -->
+ <string name="mozac_browser_toolbar_menu_button">منو</string>
+ <!-- Content description: For the clear URL text button. -->
+ <string name="mozac_clear_button_description">پوز</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection enabled, but none trackers have been blocked or detected. -->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_on_no_trackers_blocked">ایزله‌مه قورونماسی آچیق‌دیر</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection enabled, and trackers have been blocked or detected.-->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_on_trackers_blocked1">تعقیب قوروماسی تعقیب‌چی‌لری مسدود ائدیپ‌دیر</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection disabled.-->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_off_for_a_site1">بو سایت اوچون ایزله‌مه قورونماسی باغلیدیر.</string>
+ <!-- Content description: For the site security information icon (the site security icon).-->
+ <string name="mozac_browser_toolbar_content_description_site_info">سایت بیلگی‌لری</string>
+ <!-- Announcement made by the screen reader when the progress bar is shown and a page is loading -->
+ <string name="mozac_browser_toolbar_progress_loading">دولور</string>
+ <!-- Content description: For the autoplay toolbar icon, it is set when the auto play permission is blocking content playing.-->
+ <string name="mozac_browser_toolbar_content_description_autoplay_blocked">بعضی محتوا اتوْماتیک‌چال تنظیمی ایله بلوْکلانیب</string>
+</resources>
diff --git a/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-ban/strings.xml b/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-ban/strings.xml
new file mode 100644
index 0000000000..037114093f
--- /dev/null
+++ b/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-ban/strings.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description (not visible, for screen readers etc.): Description for the overflow menu button in the browser toolbar. -->
+ <string name="mozac_browser_toolbar_menu_button">Menu</string>
+ <string name="mozac_clear_button_description">Puyung</string>
+ <!-- Announcement made by the screen reader when the progress bar is shown and a page is loading -->
+ <string name="mozac_browser_toolbar_progress_loading">Jantosang dumun</string>
+ </resources>
diff --git a/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-be/strings.xml b/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-be/strings.xml
new file mode 100644
index 0000000000..5042e0d03d
--- /dev/null
+++ b/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-be/strings.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description (not visible, for screen readers etc.): Description for the overflow menu button in the browser toolbar. -->
+ <string name="mozac_browser_toolbar_menu_button">Меню</string>
+ <!-- Content description: For the clear URL text button. -->
+ <string name="mozac_clear_button_description">Ачысціць</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection enabled, but none trackers have been blocked or detected. -->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_on_no_trackers_blocked">Ахова ад сачэння ўключана</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection enabled, and trackers have been blocked or detected.-->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_on_trackers_blocked1">Ахова ад сачэння заблакавала трэкеры</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection disabled.-->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_off_for_a_site1">Ахова ад сачэння выключана на гэтым сайце</string>
+ <!-- Content description: For the site security information icon (the site security icon).-->
+ <string name="mozac_browser_toolbar_content_description_site_info">Інфармацыя пра сайт</string>
+ <!-- Announcement made by the screen reader when the progress bar is shown and a page is loading -->
+ <string name="mozac_browser_toolbar_progress_loading">Загрузка</string>
+ <!-- Content description: For the autoplay toolbar icon, it is set when the auto play permission is blocking content playing.-->
+ <string name="mozac_browser_toolbar_content_description_autoplay_blocked">Некаторае змесціва было заблакавана наладамі аўтапрайгравання</string>
+</resources>
diff --git a/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-bg/strings.xml b/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-bg/strings.xml
new file mode 100644
index 0000000000..6f6d6ecbe0
--- /dev/null
+++ b/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-bg/strings.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description (not visible, for screen readers etc.): Description for the overflow menu button in the browser toolbar. -->
+ <string name="mozac_browser_toolbar_menu_button">Меню</string>
+ <!-- Content description: For the clear URL text button. -->
+ <string name="mozac_clear_button_description">Изчистване</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection enabled, but none trackers have been blocked or detected. -->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_on_no_trackers_blocked">Защита от проследяване включена</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection enabled, and trackers have been blocked or detected.-->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_on_trackers_blocked1">Защитата от проследяване е спряла проследяване</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection disabled.-->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_off_for_a_site1">Защитата от проследяване е изключена за сайта</string>
+ <!-- Content description: For the site security information icon (the site security icon).-->
+ <string name="mozac_browser_toolbar_content_description_site_info">Показване на информация за сайта</string>
+ <!-- Announcement made by the screen reader when the progress bar is shown and a page is loading -->
+ <string name="mozac_browser_toolbar_progress_loading">Зареждане</string>
+ <!-- Content description: For the autoplay toolbar icon, it is set when the auto play permission is blocking content playing.-->
+ <string name="mozac_browser_toolbar_content_description_autoplay_blocked">Част от съдържанието е спряно от настройките за автоматично възпроизвеждане</string>
+</resources>
diff --git a/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-bn/strings.xml b/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-bn/strings.xml
new file mode 100644
index 0000000000..8c93a8c6e7
--- /dev/null
+++ b/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-bn/strings.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description (not visible, for screen readers etc.): Description for the overflow menu button in the browser toolbar. -->
+ <string name="mozac_browser_toolbar_menu_button">মেনু</string>
+ <string name="mozac_clear_button_description">পরিষ্কার করুন</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection enabled, but none trackers have been blocked or detected. -->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_on_no_trackers_blocked">ট্র্যাকিং সুরক্ষা চালু আছে</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection enabled, and trackers have been blocked or detected.-->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_on_trackers_blocked1">ট্র্যাকিং সুরক্ষা ট্র্যাকারদের অবরুদ্ধ করেছে</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection disabled.-->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_off_for_a_site1">এই সাইটের জন্য ট্র্যাকিং সুরক্ষা বন্ধ</string>
+ <!-- Content description: For the site security information icon (the site security icon).-->
+ <string name="mozac_browser_toolbar_content_description_site_info">সাইটের তথ্য</string>
+ <!-- Announcement made by the screen reader when the progress bar is shown and a page is loading -->
+ <string name="mozac_browser_toolbar_progress_loading">লোড হচ্ছে</string>
+ <!-- Content description: For the autoplay toolbar icon, it is set when the auto play permission is blocking content playing.-->
+ <string name="mozac_browser_toolbar_content_description_autoplay_blocked">কিছু বিষয়বস্তু অটোপ্লে সেটিং দ্বারা ব্লক করা হয়েছে</string>
+</resources>
diff --git a/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-br/strings.xml b/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-br/strings.xml
new file mode 100644
index 0000000000..c5f9c203fd
--- /dev/null
+++ b/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-br/strings.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description (not visible, for screen readers etc.): Description for the overflow menu button in the browser toolbar. -->
+ <string name="mozac_browser_toolbar_menu_button">Lañser</string>
+ <!-- Content description: For the clear URL text button. -->
+ <string name="mozac_clear_button_description">Skarzhañ</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection enabled, but none trackers have been blocked or detected. -->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_on_no_trackers_blocked">Gweredekaet eo ar gware heuliañ</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection enabled, and trackers have been blocked or detected.-->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_on_trackers_blocked1">Stanket ez eus bet heulierien gant ar gwarez heuliañ</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection disabled.-->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_off_for_a_site1">Diweredekaet eo bet ar gwarez heuliañ evit al lecʼhienn-mañ</string>
+ <!-- Content description: For the site security information icon (the site security icon).-->
+ <string name="mozac_browser_toolbar_content_description_site_info">Titouroù al lecʼhienn</string>
+ <!-- Announcement made by the screen reader when the progress bar is shown and a page is loading -->
+ <string name="mozac_browser_toolbar_progress_loading">O kargañ</string>
+ <!-- Content description: For the autoplay toolbar icon, it is set when the auto play permission is blocking content playing.-->
+ <string name="mozac_browser_toolbar_content_description_autoplay_blocked">Elfennoù ’zo a zo bet stanket gant arventenn al lenn emgefreek</string>
+</resources>
diff --git a/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-bs/strings.xml b/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-bs/strings.xml
new file mode 100644
index 0000000000..473bf58af2
--- /dev/null
+++ b/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-bs/strings.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description (not visible, for screen readers etc.): Description for the overflow menu button in the browser toolbar. -->
+ <string name="mozac_browser_toolbar_menu_button">Meni</string>
+ <!-- Content description: For the clear URL text button. -->
+ <string name="mozac_clear_button_description">Očisti</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection enabled, but none trackers have been blocked or detected. -->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_on_no_trackers_blocked">Zaštita od praćenja uključena</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection enabled, and trackers have been blocked or detected.-->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_on_trackers_blocked1">Zaštita od praćenja je blokirala pratioce</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection disabled.-->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_off_for_a_site1">Zaštita od praćenja je isključena za ovu stranicu</string>
+ <!-- Content description: For the site security information icon (the site security icon).-->
+ <string name="mozac_browser_toolbar_content_description_site_info">Informacije o stranici</string>
+ <!-- Announcement made by the screen reader when the progress bar is shown and a page is loading -->
+ <string name="mozac_browser_toolbar_progress_loading">Učitavanje</string>
+ <!-- Content description: For the autoplay toolbar icon, it is set when the auto play permission is blocking content playing.-->
+ <string name="mozac_browser_toolbar_content_description_autoplay_blocked">Neki sadržaj je blokiran postavkom automatske reprodukcije</string>
+</resources>
diff --git a/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-ca/strings.xml b/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-ca/strings.xml
new file mode 100644
index 0000000000..44f350dcf2
--- /dev/null
+++ b/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-ca/strings.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description (not visible, for screen readers etc.): Description for the overflow menu button in the browser toolbar. -->
+ <string name="mozac_browser_toolbar_menu_button">Menú</string>
+ <string name="mozac_clear_button_description">Esborra</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection enabled, but none trackers have been blocked or detected. -->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_on_no_trackers_blocked">La protecció contra el seguiment està activada</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection enabled, and trackers have been blocked or detected.-->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_on_trackers_blocked1">La protecció contra el seguiment ha blocat elements de seguiment coneguts</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection disabled.-->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_off_for_a_site1">S’ha desactivat la protecció contra el seguiment per a aquest lloc</string>
+ <!-- Content description: For the site security information icon (the site security icon).-->
+ <string name="mozac_browser_toolbar_content_description_site_info">Informació del lloc</string>
+ <!-- Announcement made by the screen reader when the progress bar is shown and a page is loading -->
+ <string name="mozac_browser_toolbar_progress_loading">S’està carregant</string>
+ <!-- Content description: For the autoplay toolbar icon, it is set when the auto play permission is blocking content playing.-->
+ <string name="mozac_browser_toolbar_content_description_autoplay_blocked">Una part del contingut s’ha blocat per la configuració de la reproducció automàtica</string>
+</resources>
diff --git a/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-cak/strings.xml b/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-cak/strings.xml
new file mode 100644
index 0000000000..ae15567dc0
--- /dev/null
+++ b/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-cak/strings.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description (not visible, for screen readers etc.): Description for the overflow menu button in the browser toolbar. -->
+ <string name="mozac_browser_toolbar_menu_button">K\'utsamaj</string>
+ <!-- Content description: For the clear URL text button. -->
+ <string name="mozac_clear_button_description">Tijosq\'ïx</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection enabled, but none trackers have been blocked or detected. -->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_on_no_trackers_blocked">Tzijïl ri Chajinïk Chuwäch Ojqanïk</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection enabled, and trackers have been blocked or detected.-->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_on_trackers_blocked1">Eruq\'aton ojqanela\' ri i Chajinïk chuwäch Ojqanïk</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection disabled.-->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_off_for_a_site1">Chupül ri Chajinïk chuwäch Ojqanem pa re ruxaq re\'</string>
+ <!-- Content description: For the site security information icon (the site security icon).-->
+ <string name="mozac_browser_toolbar_content_description_site_info">Rutzijol ruxaq</string>
+ <!-- Announcement made by the screen reader when the progress bar is shown and a page is loading -->
+ <string name="mozac_browser_toolbar_progress_loading">Nusamajij</string>
+ <!-- Content description: For the autoplay toolbar icon, it is set when the auto play permission is blocking content playing.-->
+ <string name="mozac_browser_toolbar_content_description_autoplay_blocked">Jun peraj chi re ri rupam xq\'at ruma ri runuk\'ulem ri ruyon nitzij</string>
+</resources>
diff --git a/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-ceb/strings.xml b/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-ceb/strings.xml
new file mode 100644
index 0000000000..4a03205a32
--- /dev/null
+++ b/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-ceb/strings.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description (not visible, for screen readers etc.): Description for the overflow menu button in the browser toolbar. -->
+ <string name="mozac_browser_toolbar_menu_button">Menu</string>
+ <string name="mozac_clear_button_description">Panas</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection enabled, but none trackers have been blocked or detected. -->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_on_no_trackers_blocked">Ang Tracking Protection on</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection enabled, and trackers have been blocked or detected.-->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_on_trackers_blocked1">Ang Tracking Protection nibara ug tracker</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection disabled.-->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_off_for_a_site1">Wala\'y Tracking Protection ani nga site</string>
+ <!-- Content description: For the site security information icon (the site security icon).-->
+ <string name="mozac_browser_toolbar_content_description_site_info">Detalye sa site</string>
+ <!-- Announcement made by the screen reader when the progress bar is shown and a page is loading -->
+ <string name="mozac_browser_toolbar_progress_loading">Loading</string>
+ <!-- Content description: For the autoplay toolbar icon, it is set when the auto play permission is blocking content playing.-->
+ <string name="mozac_browser_toolbar_content_description_autoplay_blocked">Ang uban content gibara sa setting sa autoplay</string>
+</resources>
diff --git a/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-ckb/strings.xml b/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-ckb/strings.xml
new file mode 100644
index 0000000000..95e99bea91
--- /dev/null
+++ b/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-ckb/strings.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description (not visible, for screen readers etc.): Description for the overflow menu button in the browser toolbar. -->
+ <string name="mozac_browser_toolbar_menu_button">پێڕست</string>
+ <string name="mozac_clear_button_description">پاککردنەوە</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection enabled, but none trackers have been blocked or detected. -->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_on_no_trackers_blocked">پارێزگاری لە چاودێری کارایە</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection enabled, and trackers have been blocked or detected.-->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_on_trackers_blocked1">پارێزگاری چاودێری توانی چەند چاودێریکەرێک بلۆک بکات</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection disabled.-->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_off_for_a_site1">پارێزگاری لە چاودێری ناکارایە بۆ ئەم ماڵپەڕە</string>
+ <!-- Content description: For the site security information icon (the site security icon).-->
+ <string name="mozac_browser_toolbar_content_description_site_info">زانیاری ماڵپەڕ</string>
+ <!-- Announcement made by the screen reader when the progress bar is shown and a page is loading -->
+ <string name="mozac_browser_toolbar_progress_loading">باردەکرێت</string>
+ <!-- Content description: For the autoplay toolbar icon, it is set when the auto play permission is blocking content playing.-->
+ <string name="mozac_browser_toolbar_content_description_autoplay_blocked">هەندێک ناوەڕۆک بلۆک کران لە لایەن ڕێکخستنی خۆپێکردنەوە</string>
+</resources>
diff --git a/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-co/strings.xml b/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-co/strings.xml
new file mode 100644
index 0000000000..2a309bb0b3
--- /dev/null
+++ b/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-co/strings.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description (not visible, for screen readers etc.): Description for the overflow menu button in the browser toolbar. -->
+ <string name="mozac_browser_toolbar_menu_button">Listinu</string>
+ <!-- Content description: For the clear URL text button. -->
+ <string name="mozac_clear_button_description">Squassà</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection enabled, but none trackers have been blocked or detected. -->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_on_no_trackers_blocked">A prutezzione contr’à u spiunagiu hè attivata</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection enabled, and trackers have been blocked or detected.-->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_on_trackers_blocked1">A prutezzione contr’à u spiunagiu hà bluccatu perseguitatori</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection disabled.-->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_off_for_a_site1">A prutezzione contr’à u spiunagiu hè disattivata per stu situ</string>
+ <!-- Content description: For the site security information icon (the site security icon).-->
+ <string name="mozac_browser_toolbar_content_description_site_info">Infurmazioni nant’à u situ</string>
+ <!-- Announcement made by the screen reader when the progress bar is shown and a page is loading -->
+ <string name="mozac_browser_toolbar_progress_loading">Caricamentu in corsu</string>
+ <!-- Content description: For the autoplay toolbar icon, it is set when the auto play permission is blocking content playing.-->
+ <string name="mozac_browser_toolbar_content_description_autoplay_blocked">Certi cuntenuti sò stati bluccati da a preferenza di lettura autumatica</string>
+</resources>
diff --git a/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-cs/strings.xml b/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-cs/strings.xml
new file mode 100644
index 0000000000..a2c3e0d17a
--- /dev/null
+++ b/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-cs/strings.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description (not visible, for screen readers etc.): Description for the overflow menu button in the browser toolbar. -->
+ <string name="mozac_browser_toolbar_menu_button">Nabídka</string>
+ <!-- Content description: For the clear URL text button. -->
+ <string name="mozac_clear_button_description">Vymazat</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection enabled, but none trackers have been blocked or detected. -->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_on_no_trackers_blocked">Ochrana proti sledování je zapnuta</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection enabled, and trackers have been blocked or detected.-->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_on_trackers_blocked1">Ochrana proti sledování zablokovala sledovací prvky</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection disabled.-->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_off_for_a_site1">Ochrana proti sledování je pro tento web vypnuta</string>
+ <!-- Content description: For the site security information icon (the site security icon).-->
+ <string name="mozac_browser_toolbar_content_description_site_info">Informace o stránce</string>
+ <!-- Announcement made by the screen reader when the progress bar is shown and a page is loading -->
+ <string name="mozac_browser_toolbar_progress_loading">Načítání</string>
+ <!-- Content description: For the autoplay toolbar icon, it is set when the auto play permission is blocking content playing.-->
+ <string name="mozac_browser_toolbar_content_description_autoplay_blocked">Část obsahu byla zablokována nastavením automatického přehrávání</string>
+</resources>
diff --git a/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-cy/strings.xml b/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-cy/strings.xml
new file mode 100644
index 0000000000..3689bb4004
--- /dev/null
+++ b/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-cy/strings.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description (not visible, for screen readers etc.): Description for the overflow menu button in the browser toolbar. -->
+ <string name="mozac_browser_toolbar_menu_button">Dewislen</string>
+ <!-- Content description: For the clear URL text button. -->
+ <string name="mozac_clear_button_description">Clirio</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection enabled, but none trackers have been blocked or detected. -->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_on_no_trackers_blocked">Mae Diogelwch rhag Tracio ymlaen</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection enabled, and trackers have been blocked or detected.-->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_on_trackers_blocked1">Mae Diogelwch rhag Tracio wedi rhwystro tracwyr</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection disabled.-->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_off_for_a_site1">Mae Diogelwch rhag Tracio wedi ei ddiffodd ar gyfer y wefan hon</string>
+ <!-- Content description: For the site security information icon (the site security icon).-->
+ <string name="mozac_browser_toolbar_content_description_site_info">Manylion y wefan</string>
+ <!-- Announcement made by the screen reader when the progress bar is shown and a page is loading -->
+ <string name="mozac_browser_toolbar_progress_loading">Llwytho</string>
+ <!-- Content description: For the autoplay toolbar icon, it is set when the auto play permission is blocking content playing.-->
+ <string name="mozac_browser_toolbar_content_description_autoplay_blocked">Mae rhywfaint o gynnwys wedi’i rwystro gan osodiadau awtochwarae</string>
+</resources>
diff --git a/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-da/strings.xml b/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-da/strings.xml
new file mode 100644
index 0000000000..b8d4ba146f
--- /dev/null
+++ b/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-da/strings.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description (not visible, for screen readers etc.): Description for the overflow menu button in the browser toolbar. -->
+ <string name="mozac_browser_toolbar_menu_button">Menu</string>
+ <!-- Content description: For the clear URL text button. -->
+ <string name="mozac_clear_button_description">Ryd</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection enabled, but none trackers have been blocked or detected. -->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_on_no_trackers_blocked">Beskyttelse mod sporing er slået til</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection enabled, and trackers have been blocked or detected.-->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_on_trackers_blocked1">Beskyttelse mod sporing har blokeret sporings-tjenester</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection disabled.-->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_off_for_a_site1">Beskyttelse mod sporing er slået fra for dette websted</string>
+ <!-- Content description: For the site security information icon (the site security icon).-->
+ <string name="mozac_browser_toolbar_content_description_site_info">Information om webstedet</string>
+ <!-- Announcement made by the screen reader when the progress bar is shown and a page is loading -->
+ <string name="mozac_browser_toolbar_progress_loading">Indlæser</string>
+ <!-- Content description: For the autoplay toolbar icon, it is set when the auto play permission is blocking content playing.-->
+ <string name="mozac_browser_toolbar_content_description_autoplay_blocked">Noget indhold er blevet blokeret af indstillingen for automatisk afspilning</string>
+</resources>
diff --git a/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-de/strings.xml b/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-de/strings.xml
new file mode 100644
index 0000000000..2db37ddfd5
--- /dev/null
+++ b/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-de/strings.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description (not visible, for screen readers etc.): Description for the overflow menu button in the browser toolbar. -->
+ <string name="mozac_browser_toolbar_menu_button">Menü</string>
+ <!-- Content description: For the clear URL text button. -->
+ <string name="mozac_clear_button_description">Leeren</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection enabled, but none trackers have been blocked or detected. -->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_on_no_trackers_blocked">Schutz vor Aktivitätenverfolgung ist an</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection enabled, and trackers have been blocked or detected.-->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_on_trackers_blocked1">Der Tracking-Schutz hat Tracker blockiert</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection disabled.-->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_off_for_a_site1">Der Tracking-Schutz ist für diese Website deaktiviert</string>
+ <!-- Content description: For the site security information icon (the site security icon).-->
+ <string name="mozac_browser_toolbar_content_description_site_info">Seiteninformation</string>
+ <!-- Announcement made by the screen reader when the progress bar is shown and a page is loading -->
+ <string name="mozac_browser_toolbar_progress_loading">Wird geladen…</string>
+ <!-- Content description: For the autoplay toolbar icon, it is set when the auto play permission is blocking content playing.-->
+ <string name="mozac_browser_toolbar_content_description_autoplay_blocked">Einige Inhalte wurden durch die Einstellung zur automatischen Wiedergabe blockiert</string>
+</resources>
diff --git a/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-dsb/strings.xml b/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-dsb/strings.xml
new file mode 100644
index 0000000000..5f13b6571d
--- /dev/null
+++ b/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-dsb/strings.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description (not visible, for screen readers etc.): Description for the overflow menu button in the browser toolbar. -->
+ <string name="mozac_browser_toolbar_menu_button">Meni</string>
+ <!-- Content description: For the clear URL text button. -->
+ <string name="mozac_clear_button_description">Lašowaś</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection enabled, but none trackers have been blocked or detected. -->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_on_no_trackers_blocked">Slědowański šćit jo zašaltowany</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection enabled, and trackers have been blocked or detected.-->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_on_trackers_blocked1">Slědowański šćit jo blokěrował pśeslědowaki</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection disabled.-->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_off_for_a_site1">Slědowański šćit jo něnto znjemóžnjony za toś to sedło</string>
+ <!-- Content description: For the site security information icon (the site security icon).-->
+ <string name="mozac_browser_toolbar_content_description_site_info">Sedłowe informacije</string>
+ <!-- Announcement made by the screen reader when the progress bar is shown and a page is loading -->
+ <string name="mozac_browser_toolbar_progress_loading">Zacytujo se</string>
+ <!-- Content description: For the autoplay toolbar icon, it is set when the auto play permission is blocking content playing.-->
+ <string name="mozac_browser_toolbar_content_description_autoplay_blocked">Někake wopśimjeśe jo se pśez wótgrawańske nastajenje zablokěrował</string>
+</resources>
diff --git a/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-el/strings.xml b/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-el/strings.xml
new file mode 100644
index 0000000000..8960320249
--- /dev/null
+++ b/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-el/strings.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description (not visible, for screen readers etc.): Description for the overflow menu button in the browser toolbar. -->
+ <string name="mozac_browser_toolbar_menu_button">Μενού</string>
+ <!-- Content description: For the clear URL text button. -->
+ <string name="mozac_clear_button_description">Απαλοιφή</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection enabled, but none trackers have been blocked or detected. -->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_on_no_trackers_blocked">Η προστασία από καταγραφή είναι ενεργή</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection enabled, and trackers have been blocked or detected.-->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_on_trackers_blocked1">Η προστασία από καταγραφή έχει αποκλείσει ιχνηλάτες</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection disabled.-->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_off_for_a_site1">Η προστασία από καταγραφή είναι ανενεργή για τον ιστότοπο</string>
+ <!-- Content description: For the site security information icon (the site security icon).-->
+ <string name="mozac_browser_toolbar_content_description_site_info">Πληροφορίες ιστοτόπου</string>
+ <!-- Announcement made by the screen reader when the progress bar is shown and a page is loading -->
+ <string name="mozac_browser_toolbar_progress_loading">Φόρτωση</string>
+ <!-- Content description: For the autoplay toolbar icon, it is set when the auto play permission is blocking content playing.-->
+ <string name="mozac_browser_toolbar_content_description_autoplay_blocked">Ορισμένο περιεχόμενο έχει αποκλειστεί από τη ρύθμιση αυτόματης αναπαραγωγής</string>
+</resources>
diff --git a/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-en-rCA/strings.xml b/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-en-rCA/strings.xml
new file mode 100644
index 0000000000..29866e8096
--- /dev/null
+++ b/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-en-rCA/strings.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description (not visible, for screen readers etc.): Description for the overflow menu button in the browser toolbar. -->
+ <string name="mozac_browser_toolbar_menu_button">Menu</string>
+ <!-- Content description: For the clear URL text button. -->
+ <string name="mozac_clear_button_description">Clear</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection enabled, but none trackers have been blocked or detected. -->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_on_no_trackers_blocked">Tracking Protection is on</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection enabled, and trackers have been blocked or detected.-->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_on_trackers_blocked1">Tracking Protection has blocked trackers</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection disabled.-->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_off_for_a_site1">Tracking Protection is off for this site</string>
+ <!-- Content description: For the site security information icon (the site security icon).-->
+ <string name="mozac_browser_toolbar_content_description_site_info">Site information</string>
+ <!-- Announcement made by the screen reader when the progress bar is shown and a page is loading -->
+ <string name="mozac_browser_toolbar_progress_loading">Loading</string>
+ <!-- Content description: For the autoplay toolbar icon, it is set when the auto play permission is blocking content playing.-->
+ <string name="mozac_browser_toolbar_content_description_autoplay_blocked">Some content has been blocked by the autoplay setting</string>
+</resources>
diff --git a/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-en-rGB/strings.xml b/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-en-rGB/strings.xml
new file mode 100644
index 0000000000..29866e8096
--- /dev/null
+++ b/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-en-rGB/strings.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description (not visible, for screen readers etc.): Description for the overflow menu button in the browser toolbar. -->
+ <string name="mozac_browser_toolbar_menu_button">Menu</string>
+ <!-- Content description: For the clear URL text button. -->
+ <string name="mozac_clear_button_description">Clear</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection enabled, but none trackers have been blocked or detected. -->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_on_no_trackers_blocked">Tracking Protection is on</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection enabled, and trackers have been blocked or detected.-->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_on_trackers_blocked1">Tracking Protection has blocked trackers</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection disabled.-->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_off_for_a_site1">Tracking Protection is off for this site</string>
+ <!-- Content description: For the site security information icon (the site security icon).-->
+ <string name="mozac_browser_toolbar_content_description_site_info">Site information</string>
+ <!-- Announcement made by the screen reader when the progress bar is shown and a page is loading -->
+ <string name="mozac_browser_toolbar_progress_loading">Loading</string>
+ <!-- Content description: For the autoplay toolbar icon, it is set when the auto play permission is blocking content playing.-->
+ <string name="mozac_browser_toolbar_content_description_autoplay_blocked">Some content has been blocked by the autoplay setting</string>
+</resources>
diff --git a/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-eo/strings.xml b/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-eo/strings.xml
new file mode 100644
index 0000000000..5f31034648
--- /dev/null
+++ b/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-eo/strings.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description (not visible, for screen readers etc.): Description for the overflow menu button in the browser toolbar. -->
+ <string name="mozac_browser_toolbar_menu_button">Menuo</string>
+ <!-- Content description: For the clear URL text button. -->
+ <string name="mozac_clear_button_description">Viŝi</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection enabled, but none trackers have been blocked or detected. -->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_on_no_trackers_blocked">Protekto kontraŭ spurado ŝaltita</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection enabled, and trackers have been blocked or detected.-->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_on_trackers_blocked1">La protekto kontraŭ spurado blokis spurilojn</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection disabled.-->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_off_for_a_site1">Protekto kontraŭ spurado malŝaltita por tiu ĉi retejo</string>
+ <!-- Content description: For the site security information icon (the site security icon).-->
+ <string name="mozac_browser_toolbar_content_description_site_info">Informo pri retejo</string>
+ <!-- Announcement made by the screen reader when the progress bar is shown and a page is loading -->
+ <string name="mozac_browser_toolbar_progress_loading">Ŝargado</string>
+ <!-- Content description: For the autoplay toolbar icon, it is set when the auto play permission is blocking content playing.-->
+ <string name="mozac_browser_toolbar_content_description_autoplay_blocked">Parto de la enhavo estis blokita de la agordo pri aŭtomata ludado</string>
+</resources>
diff --git a/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-es-rAR/strings.xml b/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-es-rAR/strings.xml
new file mode 100644
index 0000000000..d5fa1f30f0
--- /dev/null
+++ b/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-es-rAR/strings.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description (not visible, for screen readers etc.): Description for the overflow menu button in the browser toolbar. -->
+ <string name="mozac_browser_toolbar_menu_button">Menú</string>
+ <!-- Content description: For the clear URL text button. -->
+ <string name="mozac_clear_button_description">Limpiar</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection enabled, but none trackers have been blocked or detected. -->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_on_no_trackers_blocked">La protección contra rastreo está habilitada</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection enabled, and trackers have been blocked or detected.-->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_on_trackers_blocked1">La protección contra rastreo bloqueó los rastreadores</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection disabled.-->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_off_for_a_site1">La protección de rastreo está deshabilitada para este sitio</string>
+ <!-- Content description: For the site security information icon (the site security icon).-->
+ <string name="mozac_browser_toolbar_content_description_site_info">Información del sitio</string>
+ <!-- Announcement made by the screen reader when the progress bar is shown and a page is loading -->
+ <string name="mozac_browser_toolbar_progress_loading">Cargando</string>
+ <!-- Content description: For the autoplay toolbar icon, it is set when the auto play permission is blocking content playing.-->
+ <string name="mozac_browser_toolbar_content_description_autoplay_blocked">Se bloquearon algunos contenidos debido a la configuración de reproducción automática</string>
+</resources>
diff --git a/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-es-rCL/strings.xml b/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-es-rCL/strings.xml
new file mode 100644
index 0000000000..107843b536
--- /dev/null
+++ b/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-es-rCL/strings.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description (not visible, for screen readers etc.): Description for the overflow menu button in the browser toolbar. -->
+ <string name="mozac_browser_toolbar_menu_button">Menú</string>
+ <!-- Content description: For the clear URL text button. -->
+ <string name="mozac_clear_button_description">Limpiar</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection enabled, but none trackers have been blocked or detected. -->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_on_no_trackers_blocked">Protección de seguimiento activada</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection enabled, and trackers have been blocked or detected.-->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_on_trackers_blocked1">La Protección de seguimiento ha bloqueado rastreadores</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection disabled.-->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_off_for_a_site1">Protección de seguimiento desactivada para este sitio</string>
+ <!-- Content description: For the site security information icon (the site security icon).-->
+ <string name="mozac_browser_toolbar_content_description_site_info">Información del sitio</string>
+ <!-- Announcement made by the screen reader when the progress bar is shown and a page is loading -->
+ <string name="mozac_browser_toolbar_progress_loading">Cargando</string>
+ <!-- Content description: For the autoplay toolbar icon, it is set when the auto play permission is blocking content playing.-->
+ <string name="mozac_browser_toolbar_content_description_autoplay_blocked">Algunos contenidos han sido bloqueados por los ajustes de reproducción automática</string>
+</resources>
diff --git a/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-es-rES/strings.xml b/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-es-rES/strings.xml
new file mode 100644
index 0000000000..9c4263b840
--- /dev/null
+++ b/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-es-rES/strings.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description (not visible, for screen readers etc.): Description for the overflow menu button in the browser toolbar. -->
+ <string name="mozac_browser_toolbar_menu_button">Menú</string>
+ <!-- Content description: For the clear URL text button. -->
+ <string name="mozac_clear_button_description">Limpiar</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection enabled, but none trackers have been blocked or detected. -->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_on_no_trackers_blocked">La protección contra rastreo está activada</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection enabled, and trackers have been blocked or detected.-->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_on_trackers_blocked1">La protección contra rastreo ha bloqueado rastreadores</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection disabled.-->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_off_for_a_site1">La protección contra rastreo está desactivada para este sitio web</string>
+ <!-- Content description: For the site security information icon (the site security icon).-->
+ <string name="mozac_browser_toolbar_content_description_site_info">Información del sitio</string>
+ <!-- Announcement made by the screen reader when the progress bar is shown and a page is loading -->
+ <string name="mozac_browser_toolbar_progress_loading">Cargando</string>
+ <!-- Content description: For the autoplay toolbar icon, it is set when the auto play permission is blocking content playing.-->
+ <string name="mozac_browser_toolbar_content_description_autoplay_blocked">Algunos contenidos han sido bloqueados por los ajustes de reproducción automática</string>
+</resources>
diff --git a/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-es-rMX/strings.xml b/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-es-rMX/strings.xml
new file mode 100644
index 0000000000..cd4388769d
--- /dev/null
+++ b/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-es-rMX/strings.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description (not visible, for screen readers etc.): Description for the overflow menu button in the browser toolbar. -->
+ <string name="mozac_browser_toolbar_menu_button">Menú</string>
+ <string name="mozac_clear_button_description">Limpiar</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection enabled, but none trackers have been blocked or detected. -->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_on_no_trackers_blocked">La protección contra rastreo está activada</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection enabled, and trackers have been blocked or detected.-->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_on_trackers_blocked1">La protección contra rastreo ha bloqueado rastreadores</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection disabled.-->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_off_for_a_site1">La protección contra rastreo está desactivada para este sitio</string>
+ <!-- Content description: For the site security information icon (the site security icon).-->
+ <string name="mozac_browser_toolbar_content_description_site_info">Información del sitio</string>
+ <!-- Announcement made by the screen reader when the progress bar is shown and a page is loading -->
+ <string name="mozac_browser_toolbar_progress_loading">Cargando</string>
+ <!-- Content description: For the autoplay toolbar icon, it is set when the auto play permission is blocking content playing.-->
+ <string name="mozac_browser_toolbar_content_description_autoplay_blocked">Parte del contenido ha sido bloqueado por la configuración de reproducción automática</string>
+</resources>
diff --git a/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-es/strings.xml b/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-es/strings.xml
new file mode 100644
index 0000000000..9c4263b840
--- /dev/null
+++ b/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-es/strings.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description (not visible, for screen readers etc.): Description for the overflow menu button in the browser toolbar. -->
+ <string name="mozac_browser_toolbar_menu_button">Menú</string>
+ <!-- Content description: For the clear URL text button. -->
+ <string name="mozac_clear_button_description">Limpiar</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection enabled, but none trackers have been blocked or detected. -->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_on_no_trackers_blocked">La protección contra rastreo está activada</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection enabled, and trackers have been blocked or detected.-->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_on_trackers_blocked1">La protección contra rastreo ha bloqueado rastreadores</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection disabled.-->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_off_for_a_site1">La protección contra rastreo está desactivada para este sitio web</string>
+ <!-- Content description: For the site security information icon (the site security icon).-->
+ <string name="mozac_browser_toolbar_content_description_site_info">Información del sitio</string>
+ <!-- Announcement made by the screen reader when the progress bar is shown and a page is loading -->
+ <string name="mozac_browser_toolbar_progress_loading">Cargando</string>
+ <!-- Content description: For the autoplay toolbar icon, it is set when the auto play permission is blocking content playing.-->
+ <string name="mozac_browser_toolbar_content_description_autoplay_blocked">Algunos contenidos han sido bloqueados por los ajustes de reproducción automática</string>
+</resources>
diff --git a/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-et/strings.xml b/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-et/strings.xml
new file mode 100644
index 0000000000..7fb1096fd7
--- /dev/null
+++ b/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-et/strings.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description (not visible, for screen readers etc.): Description for the overflow menu button in the browser toolbar. -->
+ <string name="mozac_browser_toolbar_menu_button">Menüü</string>
+ <string name="mozac_clear_button_description">Tühjenda</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection enabled, but none trackers have been blocked or detected. -->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_on_no_trackers_blocked">Jälitamisvastane kaitse on sees</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection enabled, and trackers have been blocked or detected.-->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_on_trackers_blocked1">Jälitamisvastane kaitse on jälitajaid blokkinud</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection disabled.-->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_off_for_a_site1">Täiustatud jälitamisvastane kaitse on sellel saidil väljas</string>
+ <!-- Content description: For the site security information icon (the site security icon).-->
+ <string name="mozac_browser_toolbar_content_description_site_info">Saidi teave</string>
+ <!-- Announcement made by the screen reader when the progress bar is shown and a page is loading -->
+ <string name="mozac_browser_toolbar_progress_loading">Laadimine</string>
+ <!-- Content description: For the autoplay toolbar icon, it is set when the auto play permission is blocking content playing.-->
+ <string name="mozac_browser_toolbar_content_description_autoplay_blocked">Osa sisu on automaatse esitamise sättega blokitud</string>
+</resources>
diff --git a/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-eu/strings.xml b/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-eu/strings.xml
new file mode 100644
index 0000000000..fb0520f183
--- /dev/null
+++ b/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-eu/strings.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description (not visible, for screen readers etc.): Description for the overflow menu button in the browser toolbar. -->
+ <string name="mozac_browser_toolbar_menu_button">Menua</string>
+ <!-- Content description: For the clear URL text button. -->
+ <string name="mozac_clear_button_description">Garbitu</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection enabled, but none trackers have been blocked or detected. -->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_on_no_trackers_blocked">Jarraipenaren babesa gaituta dago</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection enabled, and trackers have been blocked or detected.-->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_on_trackers_blocked1">Jarraipenaren babesak jarraipen-elementuak blokeatu ditu</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection disabled.-->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_off_for_a_site1">Jarraipenaren babesa desgaituta dago webgune honetarako</string>
+ <!-- Content description: For the site security information icon (the site security icon).-->
+ <string name="mozac_browser_toolbar_content_description_site_info">Gunearen informazioa</string>
+ <!-- Announcement made by the screen reader when the progress bar is shown and a page is loading -->
+ <string name="mozac_browser_toolbar_progress_loading">Kargatzen</string>
+ <!-- Content description: For the autoplay toolbar icon, it is set when the auto play permission is blocking content playing.-->
+ <string name="mozac_browser_toolbar_content_description_autoplay_blocked">Eduki batzuk blokeatu egin dira erreprodukzio automatikoko ezarpenetan oinarrituta</string>
+</resources>
diff --git a/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-fa/strings.xml b/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-fa/strings.xml
new file mode 100644
index 0000000000..f381a2069f
--- /dev/null
+++ b/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-fa/strings.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description (not visible, for screen readers etc.): Description for the overflow menu button in the browser toolbar. -->
+ <string name="mozac_browser_toolbar_menu_button">منو</string>
+ <string name="mozac_clear_button_description">پاک کردن</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection enabled, but none trackers have been blocked or detected. -->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_on_no_trackers_blocked">حفاظت در برابر ردیابی روشن است</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection enabled, and trackers have been blocked or detected.-->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_on_trackers_blocked1">حفاظت در برابر ردیابی، ردیاب‌ها را مسدود کرده است</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection disabled.-->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_off_for_a_site1">حفاظت در برابر ردیابی برای این پایگاه خاموش است</string>
+ <!-- Content description: For the site security information icon (the site security icon).-->
+ <string name="mozac_browser_toolbar_content_description_site_info">اطلاعات پایگاه</string>
+ <!-- Announcement made by the screen reader when the progress bar is shown and a page is loading -->
+ <string name="mozac_browser_toolbar_progress_loading">در حال بار کردن</string>
+ <!-- Content description: For the autoplay toolbar icon, it is set when the auto play permission is blocking content playing.-->
+ <string name="mozac_browser_toolbar_content_description_autoplay_blocked">برخی از محتواها توسط تنظیمات پخش خودکار مسدود شده‌اند</string>
+</resources>
diff --git a/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-ff/strings.xml b/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-ff/strings.xml
new file mode 100644
index 0000000000..b774316dfb
--- /dev/null
+++ b/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-ff/strings.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description (not visible, for screen readers etc.): Description for the overflow menu button in the browser toolbar. -->
+ <string name="mozac_browser_toolbar_menu_button">Dosol</string>
+ <string name="mozac_clear_button_description">Momtu</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection enabled, but none trackers have been blocked or detected. -->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_on_no_trackers_blocked">Ndeenka Dewindol nani e</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection enabled, and trackers have been blocked or detected.-->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_on_trackers_blocked1">Ndeenka Dewindol faliima rewindotooɓe</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection disabled.-->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_off_for_a_site1">Ndeenka Dewindol ko ko ñifi e ndee lowre</string>
+ <!-- Content description: For the site security information icon (the site security icon).-->
+ <string name="mozac_browser_toolbar_content_description_site_info">Humpito lowre</string>
+ <!-- Announcement made by the screen reader when the progress bar is shown and a page is loading -->
+ <string name="mozac_browser_toolbar_progress_loading">Nana loowa</string>
+ </resources>
diff --git a/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-fi/strings.xml b/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-fi/strings.xml
new file mode 100644
index 0000000000..b47d8af7bc
--- /dev/null
+++ b/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-fi/strings.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description (not visible, for screen readers etc.): Description for the overflow menu button in the browser toolbar. -->
+ <string name="mozac_browser_toolbar_menu_button">Valikko</string>
+ <!-- Content description: For the clear URL text button. -->
+ <string name="mozac_clear_button_description">Tyhjennä</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection enabled, but none trackers have been blocked or detected. -->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_on_no_trackers_blocked">Seurannan suojaus on päällä</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection enabled, and trackers have been blocked or detected.-->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_on_trackers_blocked1">Seurannan suojaus on estänyt seuraimia</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection disabled.-->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_off_for_a_site1">Seurannan suojaus ei ole käytössä tällä sivustolla</string>
+ <!-- Content description: For the site security information icon (the site security icon).-->
+ <string name="mozac_browser_toolbar_content_description_site_info">Sivustotiedot</string>
+ <!-- Announcement made by the screen reader when the progress bar is shown and a page is loading -->
+ <string name="mozac_browser_toolbar_progress_loading">Ladataan</string>
+ <!-- Content description: For the autoplay toolbar icon, it is set when the auto play permission is blocking content playing.-->
+ <string name="mozac_browser_toolbar_content_description_autoplay_blocked">Automaattisen toiston asetus on estänyt osan sisällöstä</string>
+</resources>
diff --git a/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-fr/strings.xml b/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-fr/strings.xml
new file mode 100644
index 0000000000..072941bc03
--- /dev/null
+++ b/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-fr/strings.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description (not visible, for screen readers etc.): Description for the overflow menu button in the browser toolbar. -->
+ <string name="mozac_browser_toolbar_menu_button">Menu</string>
+ <!-- Content description: For the clear URL text button. -->
+ <string name="mozac_clear_button_description">Effacer</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection enabled, but none trackers have been blocked or detected. -->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_on_no_trackers_blocked">La protection contre le pistage est activée</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection enabled, and trackers have been blocked or detected.-->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_on_trackers_blocked1">La protection contre le pistage a bloqué des traqueurs</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection disabled.-->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_off_for_a_site1">La protection contre le pistage est désactivée pour ce site</string>
+ <!-- Content description: For the site security information icon (the site security icon).-->
+ <string name="mozac_browser_toolbar_content_description_site_info">Informations sur le site</string>
+ <!-- Announcement made by the screen reader when the progress bar is shown and a page is loading -->
+ <string name="mozac_browser_toolbar_progress_loading">Chargement en cours</string>
+ <!-- Content description: For the autoplay toolbar icon, it is set when the auto play permission is blocking content playing.-->
+ <string name="mozac_browser_toolbar_content_description_autoplay_blocked">Certains contenus ont été bloqués par le paramètre de lecture automatique</string>
+</resources>
diff --git a/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-fur/strings.xml b/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-fur/strings.xml
new file mode 100644
index 0000000000..19900e6bc0
--- /dev/null
+++ b/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-fur/strings.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description (not visible, for screen readers etc.): Description for the overflow menu button in the browser toolbar. -->
+ <string name="mozac_browser_toolbar_menu_button">Menù</string>
+ <!-- Content description: For the clear URL text button. -->
+ <string name="mozac_clear_button_description">Nete</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection enabled, but none trackers have been blocked or detected. -->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_on_no_trackers_blocked">La protezion da lis spiis e je ative</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection enabled, and trackers have been blocked or detected.-->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_on_trackers_blocked1">La protezion da lis spiis e à blocât spiis</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection disabled.-->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_off_for_a_site1">La protezion da lis spiis e je disativade par chest sît</string>
+ <!-- Content description: For the site security information icon (the site security icon).-->
+ <string name="mozac_browser_toolbar_content_description_site_info">Informazions sît</string>
+ <!-- Announcement made by the screen reader when the progress bar is shown and a page is loading -->
+ <string name="mozac_browser_toolbar_progress_loading">Daûr a cjamâ</string>
+ <!-- Content description: For the autoplay toolbar icon, it is set when the auto play permission is blocking content playing.-->
+ <string name="mozac_browser_toolbar_content_description_autoplay_blocked">Cualchi contignût al è stât blocât de impostazion pe riproduzion automatiche</string>
+</resources>
diff --git a/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-fy-rNL/strings.xml b/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-fy-rNL/strings.xml
new file mode 100644
index 0000000000..9aca189901
--- /dev/null
+++ b/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-fy-rNL/strings.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description (not visible, for screen readers etc.): Description for the overflow menu button in the browser toolbar. -->
+ <string name="mozac_browser_toolbar_menu_button">Menu</string>
+ <!-- Content description: For the clear URL text button. -->
+ <string name="mozac_clear_button_description">Wiskje</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection enabled, but none trackers have been blocked or detected. -->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_on_no_trackers_blocked">Beskerming tsjin folgjen is ynskeakele</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection enabled, and trackers have been blocked or detected.-->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_on_trackers_blocked1">Beskerming tsjin folgjen hat trackers blokkearre</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection disabled.-->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_off_for_a_site1">Beskerming tsjin folgjen is út foar dizze website</string>
+ <!-- Content description: For the site security information icon (the site security icon).-->
+ <string name="mozac_browser_toolbar_content_description_site_info">Website-ynformaasje</string>
+ <!-- Announcement made by the screen reader when the progress bar is shown and a page is loading -->
+ <string name="mozac_browser_toolbar_progress_loading">Lade</string>
+ <!-- Content description: For the autoplay toolbar icon, it is set when the auto play permission is blocking content playing.-->
+ <string name="mozac_browser_toolbar_content_description_autoplay_blocked">Guon ynhâld is blokkearre troch de ynstelling foar automatysk ôfspyljen</string>
+</resources>
diff --git a/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-ga-rIE/strings.xml b/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-ga-rIE/strings.xml
new file mode 100644
index 0000000000..ba4f41d62f
--- /dev/null
+++ b/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-ga-rIE/strings.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description (not visible, for screen readers etc.): Description for the overflow menu button in the browser toolbar. -->
+ <string name="mozac_browser_toolbar_menu_button">Roghchlár</string>
+ <string name="mozac_clear_button_description">Bánaigh</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection enabled, but none trackers have been blocked or detected. -->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_on_no_trackers_blocked">Tá Cosaint ar Lorgaireacht ar siúl</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection enabled, and trackers have been blocked or detected.-->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_on_trackers_blocked1">Chuir Cosaint ar Lorgaireacht cosc ar lorgairí</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection disabled.-->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_off_for_a_site1">Tá Cosaint ar Lorgaireacht múchta don suíomh seo</string>
+ <!-- Content description: For the site security information icon (the site security icon).-->
+ <string name="mozac_browser_toolbar_content_description_site_info">Eolas faoin suíomh</string>
+ <!-- Announcement made by the screen reader when the progress bar is shown and a page is loading -->
+ <string name="mozac_browser_toolbar_progress_loading">Á lódáil</string>
+ </resources>
diff --git a/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-gd/strings.xml b/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-gd/strings.xml
new file mode 100644
index 0000000000..d694698b3d
--- /dev/null
+++ b/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-gd/strings.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description (not visible, for screen readers etc.): Description for the overflow menu button in the browser toolbar. -->
+ <string name="mozac_browser_toolbar_menu_button">Clàr-taice</string>
+ <string name="mozac_clear_button_description">Falamhaich</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection enabled, but none trackers have been blocked or detected. -->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_on_no_trackers_blocked">Tha an dìon o thracadh air</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection enabled, and trackers have been blocked or detected.-->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_on_trackers_blocked1">Bhac gleus an dìon o thracadh tracaichean</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection disabled.-->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_off_for_a_site1">Tha an dìon o thracadh dheth air an làrach seo</string>
+ <!-- Content description: For the site security information icon (the site security icon).-->
+ <string name="mozac_browser_toolbar_content_description_site_info">Fiosrachadh mun làrach</string>
+ <!-- Announcement made by the screen reader when the progress bar is shown and a page is loading -->
+ <string name="mozac_browser_toolbar_progress_loading">Ga luchdadh</string>
+ <!-- Content description: For the autoplay toolbar icon, it is set when the auto play permission is blocking content playing.-->
+ <string name="mozac_browser_toolbar_content_description_autoplay_blocked">Chaidh cuid dhen t-susbaint a bhacadh an cois roghainn na fèin-chluich</string>
+</resources>
diff --git a/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-gl/strings.xml b/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-gl/strings.xml
new file mode 100644
index 0000000000..990d910d08
--- /dev/null
+++ b/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-gl/strings.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description (not visible, for screen readers etc.): Description for the overflow menu button in the browser toolbar. -->
+ <string name="mozac_browser_toolbar_menu_button">Menú</string>
+ <!-- Content description: For the clear URL text button. -->
+ <string name="mozac_clear_button_description">Borrar</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection enabled, but none trackers have been blocked or detected. -->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_on_no_trackers_blocked">Protección contra o rastrexo activada</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection enabled, and trackers have been blocked or detected.-->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_on_trackers_blocked1">A protección contra o rastrexo bloqueou rastrexadores</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection disabled.-->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_off_for_a_site1">A protección contra o rastrexo está desactivada para este sitio</string>
+ <!-- Content description: For the site security information icon (the site security icon).-->
+ <string name="mozac_browser_toolbar_content_description_site_info">Información sobre o sitio</string>
+ <!-- Announcement made by the screen reader when the progress bar is shown and a page is loading -->
+ <string name="mozac_browser_toolbar_progress_loading">Cargando</string>
+ <!-- Content description: For the autoplay toolbar icon, it is set when the auto play permission is blocking content playing.-->
+ <string name="mozac_browser_toolbar_content_description_autoplay_blocked">A configuración de reprodución automática bloqueou algúns contidos</string>
+</resources>
diff --git a/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-gn/strings.xml b/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-gn/strings.xml
new file mode 100644
index 0000000000..7798e540da
--- /dev/null
+++ b/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-gn/strings.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description (not visible, for screen readers etc.): Description for the overflow menu button in the browser toolbar. -->
+ <string name="mozac_browser_toolbar_menu_button">Poravorã</string>
+ <!-- Content description: For the clear URL text button. -->
+ <string name="mozac_clear_button_description">Mopotĩ</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection enabled, but none trackers have been blocked or detected. -->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_on_no_trackers_blocked">Tapykuehoha ñemo’ã oñemyandy</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection enabled, and trackers have been blocked or detected.-->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_on_trackers_blocked1">Ñemo’ã jehekaha ojoko tapykuehohápe</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection disabled.-->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_off_for_a_site1">Ñemo’ã jehekaha ndoikovéima ko tendápe g̃uarã</string>
+ <!-- Content description: For the site security information icon (the site security icon).-->
+ <string name="mozac_browser_toolbar_content_description_site_info">Marandu tenda rehegua</string>
+ <!-- Announcement made by the screen reader when the progress bar is shown and a page is loading -->
+ <string name="mozac_browser_toolbar_progress_loading">Henyhẽhína</string>
+ <!-- Content description: For the autoplay toolbar icon, it is set when the auto play permission is blocking content playing.-->
+ <string name="mozac_browser_toolbar_content_description_autoplay_blocked">Ojejoko ndahetái tetepy ñemboheta ijeheguíva ñemboheko rupive</string>
+</resources>
diff --git a/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-gu-rIN/strings.xml b/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-gu-rIN/strings.xml
new file mode 100644
index 0000000000..a6ff2d26b0
--- /dev/null
+++ b/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-gu-rIN/strings.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description (not visible, for screen readers etc.): Description for the overflow menu button in the browser toolbar. -->
+ <string name="mozac_browser_toolbar_menu_button">મેનુ</string>
+ <string name="mozac_clear_button_description">સાફ કરો</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection enabled, but none trackers have been blocked or detected. -->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_on_no_trackers_blocked">ટ્રેકિંગ સુરક્ષા ચાલુ છે</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection enabled, and trackers have been blocked or detected.-->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_on_trackers_blocked1">ટ્રેકિંગ સુરક્ષા દ્વારા ટ્રેકર્સને અવરોધિત કરવામાં આવ્યા છે</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection disabled.-->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_off_for_a_site1">આ સાઇટ માટે ટ્રેકિંગ સુરક્ષા બંધ છે</string>
+ <!-- Content description: For the site security information icon (the site security icon).-->
+ <string name="mozac_browser_toolbar_content_description_site_info">સાઇટ માહિતી</string>
+ <!-- Announcement made by the screen reader when the progress bar is shown and a page is loading -->
+ <string name="mozac_browser_toolbar_progress_loading">લોડ કરી રહ્યું છે</string>
+ </resources>
diff --git a/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-hi-rIN/strings.xml b/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-hi-rIN/strings.xml
new file mode 100644
index 0000000000..2d3c7d9b42
--- /dev/null
+++ b/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-hi-rIN/strings.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description (not visible, for screen readers etc.): Description for the overflow menu button in the browser toolbar. -->
+ <string name="mozac_browser_toolbar_menu_button">मेन्यू</string>
+ <string name="mozac_clear_button_description">साफ करें</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection enabled, but none trackers have been blocked or detected. -->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_on_no_trackers_blocked">ट्रैकिंग सुरक्षा चालू है</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection enabled, and trackers have been blocked or detected.-->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_on_trackers_blocked1">ट्रैकिंग सुरक्षा ने ट्रैकरों को अवरुद्ध कर दिया है</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection disabled.-->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_off_for_a_site1">इस साइट के लिए ट्रैकिंग सुरक्षा बंद है</string>
+ <!-- Content description: For the site security information icon (the site security icon).-->
+ <string name="mozac_browser_toolbar_content_description_site_info">साइट सूचना</string>
+ <!-- Announcement made by the screen reader when the progress bar is shown and a page is loading -->
+ <string name="mozac_browser_toolbar_progress_loading">लोड हो रहा है</string>
+ </resources>
diff --git a/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-hil/strings.xml b/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-hil/strings.xml
new file mode 100644
index 0000000000..b02bc03a94
--- /dev/null
+++ b/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-hil/strings.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description (not visible, for screen readers etc.): Description for the overflow menu button in the browser toolbar. -->
+ <string name="mozac_browser_toolbar_menu_button">Menu</string>
+ <string name="mozac_clear_button_description">Klaro</string>
+ <!-- Announcement made by the screen reader when the progress bar is shown and a page is loading -->
+ <string name="mozac_browser_toolbar_progress_loading">Loading</string>
+ </resources>
diff --git a/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-hr/strings.xml b/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-hr/strings.xml
new file mode 100644
index 0000000000..420583468b
--- /dev/null
+++ b/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-hr/strings.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description (not visible, for screen readers etc.): Description for the overflow menu button in the browser toolbar. -->
+ <string name="mozac_browser_toolbar_menu_button">Izbornik</string>
+ <string name="mozac_clear_button_description">Izbriši</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection enabled, but none trackers have been blocked or detected. -->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_on_no_trackers_blocked">Zaštita od praćenja je uključena</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection enabled, and trackers have been blocked or detected.-->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_on_trackers_blocked1">Zaštita od praćenja je blokirala programe za praćenje</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection disabled.-->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_off_for_a_site1">Zaštita od praćenja je isključena za ovu stranicu</string>
+ <!-- Content description: For the site security information icon (the site security icon).-->
+ <string name="mozac_browser_toolbar_content_description_site_info">Informacije o web mjestu</string>
+ <!-- Announcement made by the screen reader when the progress bar is shown and a page is loading -->
+ <string name="mozac_browser_toolbar_progress_loading">Učitavanje</string>
+ <!-- Content description: For the autoplay toolbar icon, it is set when the auto play permission is blocking content playing.-->
+ <string name="mozac_browser_toolbar_content_description_autoplay_blocked">Neki sadržaji su blokirani zbog postavki automatske reprodukcije</string>
+</resources>
diff --git a/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-hsb/strings.xml b/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-hsb/strings.xml
new file mode 100644
index 0000000000..2c03305e16
--- /dev/null
+++ b/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-hsb/strings.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description (not visible, for screen readers etc.): Description for the overflow menu button in the browser toolbar. -->
+ <string name="mozac_browser_toolbar_menu_button">Meni</string>
+ <!-- Content description: For the clear URL text button. -->
+ <string name="mozac_clear_button_description">Zhašeć</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection enabled, but none trackers have been blocked or detected. -->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_on_no_trackers_blocked">Slědowanski škit je zmóžnjeny</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection enabled, and trackers have been blocked or detected.-->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_on_trackers_blocked1">Slědowanski škit je přesćěhowaki blokował</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection disabled.-->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_off_for_a_site1">Slědowanski škit je znjemóžnjeny za tute sydło</string>
+ <!-- Content description: For the site security information icon (the site security icon).-->
+ <string name="mozac_browser_toolbar_content_description_site_info">Sydłowe informacije</string>
+ <!-- Announcement made by the screen reader when the progress bar is shown and a page is loading -->
+ <string name="mozac_browser_toolbar_progress_loading">Začituje so</string>
+ <!-- Content description: For the autoplay toolbar icon, it is set when the auto play permission is blocking content playing.-->
+ <string name="mozac_browser_toolbar_content_description_autoplay_blocked">Někajki wobsah je so přez wothrawanske nastajenje zablokował</string>
+</resources>
diff --git a/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-hu/strings.xml b/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-hu/strings.xml
new file mode 100644
index 0000000000..eef3c81920
--- /dev/null
+++ b/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-hu/strings.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description (not visible, for screen readers etc.): Description for the overflow menu button in the browser toolbar. -->
+ <string name="mozac_browser_toolbar_menu_button">Menü</string>
+ <!-- Content description: For the clear URL text button. -->
+ <string name="mozac_clear_button_description">Törlés</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection enabled, but none trackers have been blocked or detected. -->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_on_no_trackers_blocked">Követés elleni védelem bekapcsolva</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection enabled, and trackers have been blocked or detected.-->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_on_trackers_blocked1">A követés elleni védelem nyomkövetőket blokkolt</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection disabled.-->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_off_for_a_site1">A követés elleni védelem le van tiltva ezen az oldalon</string>
+ <!-- Content description: For the site security information icon (the site security icon).-->
+ <string name="mozac_browser_toolbar_content_description_site_info">Oldalinformációk</string>
+ <!-- Announcement made by the screen reader when the progress bar is shown and a page is loading -->
+ <string name="mozac_browser_toolbar_progress_loading">Betöltés</string>
+ <!-- Content description: For the autoplay toolbar icon, it is set when the auto play permission is blocking content playing.-->
+ <string name="mozac_browser_toolbar_content_description_autoplay_blocked">Bizonyos tartalmakat letiltott az automatikus lejátszási beállítás</string>
+</resources>
diff --git a/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-hy-rAM/strings.xml b/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-hy-rAM/strings.xml
new file mode 100644
index 0000000000..668ae3425c
--- /dev/null
+++ b/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-hy-rAM/strings.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description (not visible, for screen readers etc.): Description for the overflow menu button in the browser toolbar. -->
+ <string name="mozac_browser_toolbar_menu_button">Ցանկ</string>
+ <!-- Content description: For the clear URL text button. -->
+ <string name="mozac_clear_button_description">Մաքրել</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection enabled, but none trackers have been blocked or detected. -->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_on_no_trackers_blocked">Հետագծման պաշտպանությունը միաց. է</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection enabled, and trackers have been blocked or detected.-->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_on_trackers_blocked1">Հետագծման պաշտպանությունն արգելափակել է հետագծիչները</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection disabled.-->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_off_for_a_site1">Հետագծման պաշտպանությունն անջ. է այս կայքի համար</string>
+ <!-- Content description: For the site security information icon (the site security icon).-->
+ <string name="mozac_browser_toolbar_content_description_site_info">Կայքի տեղեկատվություն</string>
+ <!-- Announcement made by the screen reader when the progress bar is shown and a page is loading -->
+ <string name="mozac_browser_toolbar_progress_loading">Բեռնում</string>
+ <!-- Content description: For the autoplay toolbar icon, it is set when the auto play permission is blocking content playing.-->
+ <string name="mozac_browser_toolbar_content_description_autoplay_blocked">Որոշ բովանդակություն արգելափակվել է ինքնանվագարկման կարգավորումով</string>
+</resources>
diff --git a/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-ia/strings.xml b/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-ia/strings.xml
new file mode 100644
index 0000000000..8a27cf8a5a
--- /dev/null
+++ b/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-ia/strings.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description (not visible, for screen readers etc.): Description for the overflow menu button in the browser toolbar. -->
+ <string name="mozac_browser_toolbar_menu_button">Menu</string>
+ <!-- Content description: For the clear URL text button. -->
+ <string name="mozac_clear_button_description">Vacuar</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection enabled, but none trackers have been blocked or detected. -->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_on_no_trackers_blocked">Protection contra le traciamento active</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection enabled, and trackers have been blocked or detected.-->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_on_trackers_blocked1">Le protection contra le traciamento ha blocate traciatores</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection disabled.-->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_off_for_a_site1">Le protection contra le traciamento es disactivate pro iste sito</string>
+ <!-- Content description: For the site security information icon (the site security icon).-->
+ <string name="mozac_browser_toolbar_content_description_site_info">Informationes del sito</string>
+ <!-- Announcement made by the screen reader when the progress bar is shown and a page is loading -->
+ <string name="mozac_browser_toolbar_progress_loading">Cargamento</string>
+ <!-- Content description: For the autoplay toolbar icon, it is set when the auto play permission is blocking content playing.-->
+ <string name="mozac_browser_toolbar_content_description_autoplay_blocked">Alcun contento ha essite blocate per le parametros del reproduction automatic</string>
+</resources>
diff --git a/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-in/strings.xml b/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-in/strings.xml
new file mode 100644
index 0000000000..2d7074c6ba
--- /dev/null
+++ b/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-in/strings.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description (not visible, for screen readers etc.): Description for the overflow menu button in the browser toolbar. -->
+ <string name="mozac_browser_toolbar_menu_button">Menu</string>
+ <string name="mozac_clear_button_description">Bersihkan</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection enabled, but none trackers have been blocked or detected. -->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_on_no_trackers_blocked">Perlindungan Pelacakan aktif</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection enabled, and trackers have been blocked or detected.-->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_on_trackers_blocked1">Perlindungan Pelacakan telah memblokir pelacak</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection disabled.-->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_off_for_a_site1">Perlindungan Pelacakan dinonaktifkan untuk situs ini</string>
+ <!-- Content description: For the site security information icon (the site security icon).-->
+ <string name="mozac_browser_toolbar_content_description_site_info">Informasi situs</string>
+ <!-- Announcement made by the screen reader when the progress bar is shown and a page is loading -->
+ <string name="mozac_browser_toolbar_progress_loading">Memuat</string>
+ <!-- Content description: For the autoplay toolbar icon, it is set when the auto play permission is blocking content playing.-->
+ <string name="mozac_browser_toolbar_content_description_autoplay_blocked">Beberapa konten telah diblokir dengan pengaturan putar-otomatis</string>
+</resources>
diff --git a/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-is/strings.xml b/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-is/strings.xml
new file mode 100644
index 0000000000..653bc2c4d0
--- /dev/null
+++ b/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-is/strings.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description (not visible, for screen readers etc.): Description for the overflow menu button in the browser toolbar. -->
+ <string name="mozac_browser_toolbar_menu_button">Valmynd</string>
+ <!-- Content description: For the clear URL text button. -->
+ <string name="mozac_clear_button_description">Hreinsa</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection enabled, but none trackers have been blocked or detected. -->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_on_no_trackers_blocked">Vörn gegn gagnasöfnun virk</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection enabled, and trackers have been blocked or detected.-->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_on_trackers_blocked1">Vörn gegn gagnasöfnun hefur lokað á rekjara</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection disabled.-->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_off_for_a_site1">Vörn gegn gagnasöfnun er ekki virk fyrir þetta svæði</string>
+ <!-- Content description: For the site security information icon (the site security icon).-->
+ <string name="mozac_browser_toolbar_content_description_site_info">Upplýsingar um vefsvæði</string>
+ <!-- Announcement made by the screen reader when the progress bar is shown and a page is loading -->
+ <string name="mozac_browser_toolbar_progress_loading">Hleður</string>
+ <!-- Content description: For the autoplay toolbar icon, it is set when the auto play permission is blocking content playing.-->
+ <string name="mozac_browser_toolbar_content_description_autoplay_blocked">Lokað hefur verið sumt efni með stillingum fyrir sjálfvirka afspilun</string>
+</resources>
diff --git a/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-it/strings.xml b/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-it/strings.xml
new file mode 100644
index 0000000000..33d9f28220
--- /dev/null
+++ b/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-it/strings.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description (not visible, for screen readers etc.): Description for the overflow menu button in the browser toolbar. -->
+ <string name="mozac_browser_toolbar_menu_button">Menu</string>
+ <!-- Content description: For the clear URL text button. -->
+ <string name="mozac_clear_button_description">Cancella</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection enabled, but none trackers have been blocked or detected. -->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_on_no_trackers_blocked">La protezione antitracciamento è attiva</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection enabled, and trackers have been blocked or detected.-->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_on_trackers_blocked1">La protezione antitracciamento ha bloccato contenuti traccianti</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection disabled.-->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_off_for_a_site1">La protezione antitracciamento è disattivata per questo sito</string>
+ <!-- Content description: For the site security information icon (the site security icon).-->
+ <string name="mozac_browser_toolbar_content_description_site_info">Informazioni sito</string>
+ <!-- Announcement made by the screen reader when the progress bar is shown and a page is loading -->
+ <string name="mozac_browser_toolbar_progress_loading">Caricamento…</string>
+ <!-- Content description: For the autoplay toolbar icon, it is set when the auto play permission is blocking content playing.-->
+ <string name="mozac_browser_toolbar_content_description_autoplay_blocked">Alcuni contenuti sono stati bloccati dall’impostazione per la riproduzione automatica</string>
+</resources>
diff --git a/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-iw/strings.xml b/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-iw/strings.xml
new file mode 100644
index 0000000000..51477ead53
--- /dev/null
+++ b/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-iw/strings.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description (not visible, for screen readers etc.): Description for the overflow menu button in the browser toolbar. -->
+ <string name="mozac_browser_toolbar_menu_button">תפריט</string>
+ <!-- Content description: For the clear URL text button. -->
+ <string name="mozac_clear_button_description">ניקוי</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection enabled, but none trackers have been blocked or detected. -->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_on_no_trackers_blocked">הגנת מעקב פעילה</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection enabled, and trackers have been blocked or detected.-->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_on_trackers_blocked1">הגנת מעקב חסמה רכיבי מעקב</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection disabled.-->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_off_for_a_site1">הגנת מעקב כבויה עבור אתר זה</string>
+ <!-- Content description: For the site security information icon (the site security icon).-->
+ <string name="mozac_browser_toolbar_content_description_site_info">פרטי האתר</string>
+ <!-- Announcement made by the screen reader when the progress bar is shown and a page is loading -->
+ <string name="mozac_browser_toolbar_progress_loading">בטעינה</string>
+ <!-- Content description: For the autoplay toolbar icon, it is set when the auto play permission is blocking content playing.-->
+ <string name="mozac_browser_toolbar_content_description_autoplay_blocked">תוכן מסויים נחסם על־ידי ההגדרה של הניגון האוטומטי</string>
+</resources>
diff --git a/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-ja/strings.xml b/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-ja/strings.xml
new file mode 100644
index 0000000000..4707063495
--- /dev/null
+++ b/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-ja/strings.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description (not visible, for screen readers etc.): Description for the overflow menu button in the browser toolbar. -->
+ <string name="mozac_browser_toolbar_menu_button">メニュー</string>
+ <!-- Content description: For the clear URL text button. -->
+ <string name="mozac_clear_button_description">消去</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection enabled, but none trackers have been blocked or detected. -->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_on_no_trackers_blocked">トラッキング防止はオンです</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection enabled, and trackers have been blocked or detected.-->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_on_trackers_blocked1">トラッキング防止によりトラッカーをブロックしました</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection disabled.-->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_off_for_a_site1">このサイトではトラッキング防止がオフです</string>
+ <!-- Content description: For the site security information icon (the site security icon).-->
+ <string name="mozac_browser_toolbar_content_description_site_info">サイト情報</string>
+ <!-- Announcement made by the screen reader when the progress bar is shown and a page is loading -->
+ <string name="mozac_browser_toolbar_progress_loading">読み込み中</string>
+ <!-- Content description: For the autoplay toolbar icon, it is set when the auto play permission is blocking content playing.-->
+ <string name="mozac_browser_toolbar_content_description_autoplay_blocked">一部のコンテンツは自動再生設定によってブロックされています</string>
+</resources>
diff --git a/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-ka/strings.xml b/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-ka/strings.xml
new file mode 100644
index 0000000000..bf438a8ed7
--- /dev/null
+++ b/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-ka/strings.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description (not visible, for screen readers etc.): Description for the overflow menu button in the browser toolbar. -->
+ <string name="mozac_browser_toolbar_menu_button">მენიუ</string>
+ <string name="mozac_clear_button_description">გასუფთავება</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection enabled, but none trackers have been blocked or detected. -->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_on_no_trackers_blocked">თვალთვალისგან დაცვა ჩართულია</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection enabled, and trackers have been blocked or detected.-->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_on_trackers_blocked1">თვალთვალისგან დაცვამ შეზღუდა მეთვალყურეები</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection disabled.-->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_off_for_a_site1">თვალთვალისგან დაცვა გამორთულია ამ საიტზე</string>
+ <!-- Content description: For the site security information icon (the site security icon).-->
+ <string name="mozac_browser_toolbar_content_description_site_info">საიტის მონაცემები</string>
+ <!-- Announcement made by the screen reader when the progress bar is shown and a page is loading -->
+ <string name="mozac_browser_toolbar_progress_loading">იტვირთება</string>
+ <!-- Content description: For the autoplay toolbar icon, it is set when the auto play permission is blocking content playing.-->
+ <string name="mozac_browser_toolbar_content_description_autoplay_blocked">ზოგიერთი მასალა შეიზღუდა თვითგაშვების პარამეტრებით</string>
+</resources>
diff --git a/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-kaa/strings.xml b/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-kaa/strings.xml
new file mode 100644
index 0000000000..e4ad1073b0
--- /dev/null
+++ b/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-kaa/strings.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description (not visible, for screen readers etc.): Description for the overflow menu button in the browser toolbar. -->
+ <string name="mozac_browser_toolbar_menu_button">Menyu</string>
+ <string name="mozac_clear_button_description">Tazalaw</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection enabled, but none trackers have been blocked or detected. -->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_on_no_trackers_blocked">Baqlaw qorǵanıwı qosılǵan</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection enabled, and trackers have been blocked or detected.-->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_on_trackers_blocked1">Baqlaw qorǵanıw funkciyası trekkerlerdi blokladı</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection disabled.-->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_off_for_a_site1">Bul sayt ushın baqlaw qorǵanıwı óshirilgen</string>
+ <!-- Content description: For the site security information icon (the site security icon).-->
+ <string name="mozac_browser_toolbar_content_description_site_info">Sayt maǵlıwmatları</string>
+ <!-- Announcement made by the screen reader when the progress bar is shown and a page is loading -->
+ <string name="mozac_browser_toolbar_progress_loading">Júklenbekte</string>
+ <!-- Content description: For the autoplay toolbar icon, it is set when the auto play permission is blocking content playing.-->
+ <string name="mozac_browser_toolbar_content_description_autoplay_blocked">Ayrım kontentler avtomatik sazlawlar tárepinen bloklanǵan</string>
+</resources>
diff --git a/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-kab/strings.xml b/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-kab/strings.xml
new file mode 100644
index 0000000000..034ec09580
--- /dev/null
+++ b/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-kab/strings.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description (not visible, for screen readers etc.): Description for the overflow menu button in the browser toolbar. -->
+ <string name="mozac_browser_toolbar_menu_button">Umuɣ</string>
+ <!-- Content description: For the clear URL text button. -->
+ <string name="mozac_clear_button_description">Sfeḍ</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection enabled, but none trackers have been blocked or detected. -->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_on_no_trackers_blocked">Ammesten mgal aḍfaṛ yermed</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection enabled, and trackers have been blocked or detected.-->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_on_trackers_blocked1">Ammesten mgal aḍfaṛ yessewḥel ineḍfaṛen</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection disabled.-->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_off_for_a_site1">Ammesten mgal aḍfaṛ insa akka tura i usmel-a</string>
+ <!-- Content description: For the site security information icon (the site security icon).-->
+ <string name="mozac_browser_toolbar_content_description_site_info">Asmel n telɣut</string>
+ <!-- Announcement made by the screen reader when the progress bar is shown and a page is loading -->
+ <string name="mozac_browser_toolbar_progress_loading">Asali</string>
+ <!-- Content description: For the autoplay toolbar icon, it is set when the auto play permission is blocking content playing.-->
+ <string name="mozac_browser_toolbar_content_description_autoplay_blocked">Yettusewḥel kra n yigburen s aɣewwar n tɣuri tawurmant</string>
+</resources>
diff --git a/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-kk/strings.xml b/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-kk/strings.xml
new file mode 100644
index 0000000000..17b7710fac
--- /dev/null
+++ b/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-kk/strings.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description (not visible, for screen readers etc.): Description for the overflow menu button in the browser toolbar. -->
+ <string name="mozac_browser_toolbar_menu_button">Мәзір</string>
+ <!-- Content description: For the clear URL text button. -->
+ <string name="mozac_clear_button_description">Тазарту</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection enabled, but none trackers have been blocked or detected. -->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_on_no_trackers_blocked">Бақылаудан қорғаныс іске қосулы</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection enabled, and trackers have been blocked or detected.-->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_on_trackers_blocked1">Бақылаудан қорғаныс трекерлерді бұғаттады</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection disabled.-->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_off_for_a_site1">Бақылаудан қорғаныс бұл сайт үшін сөндірілген</string>
+ <!-- Content description: For the site security information icon (the site security icon).-->
+ <string name="mozac_browser_toolbar_content_description_site_info">Сайт ақпараты</string>
+ <!-- Announcement made by the screen reader when the progress bar is shown and a page is loading -->
+ <string name="mozac_browser_toolbar_progress_loading">Жүктелуде</string>
+ <!-- Content description: For the autoplay toolbar icon, it is set when the auto play permission is blocking content playing.-->
+ <string name="mozac_browser_toolbar_content_description_autoplay_blocked">Кейбір құрама автоойнату баптауларымен бұғатталған</string>
+</resources>
diff --git a/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-kmr/strings.xml b/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-kmr/strings.xml
new file mode 100644
index 0000000000..29542924a0
--- /dev/null
+++ b/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-kmr/strings.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description (not visible, for screen readers etc.): Description for the overflow menu button in the browser toolbar. -->
+ <string name="mozac_browser_toolbar_menu_button">Menû</string>
+ <string name="mozac_clear_button_description">Paqij bike</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection enabled, but none trackers have been blocked or detected. -->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_on_no_trackers_blocked">Parastina ji Şopandinê vekirî ye</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection enabled, and trackers have been blocked or detected.-->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_on_trackers_blocked1">Parastina ji şopandinê şopdar asteng kirin</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection disabled.-->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_off_for_a_site1">Parastina ji şopadinê, ji bo vê malperê girtî ye</string>
+ <!-- Content description: For the site security information icon (the site security icon).-->
+ <string name="mozac_browser_toolbar_content_description_site_info">Agahiyên malperê</string>
+ <!-- Announcement made by the screen reader when the progress bar is shown and a page is loading -->
+ <string name="mozac_browser_toolbar_progress_loading">Tê barkirin</string>
+ <!-- Content description: For the autoplay toolbar icon, it is set when the auto play permission is blocking content playing.-->
+ <string name="mozac_browser_toolbar_content_description_autoplay_blocked">Hin naverok ji aliyê eyara lêdana-otomatîk ve hatin astengkirin</string>
+</resources>
diff --git a/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-kn/strings.xml b/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-kn/strings.xml
new file mode 100644
index 0000000000..ec07a646a6
--- /dev/null
+++ b/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-kn/strings.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description (not visible, for screen readers etc.): Description for the overflow menu button in the browser toolbar. -->
+ <string name="mozac_browser_toolbar_menu_button">ಪರಿವಿಡಿ</string>
+ <string name="mozac_clear_button_description">ಅಳಿಸು</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection enabled, but none trackers have been blocked or detected. -->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_on_no_trackers_blocked">ಜಾಡು ಇರಿಸುವಿಕೆ ಇಂದ ರಕ್ಷಣೆ ಶುರುವಾಗಿದೆ</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection enabled, and trackers have been blocked or detected.-->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_on_trackers_blocked1">ಟ್ರ್ಯಾಕಿಂಗ್ ಪ್ರೊಟೆಕ್ಷನ್ ಟ್ರ್ಯಾಕರ್‌ಗಳನ್ನು ನಿರ್ಬಂಧಿಸಿದೆ</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection disabled.-->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_off_for_a_site1">ಈ ಸೈಟ್‌ಗಾಗಿ ಟ್ರ್ಯಾಕಿಂಗ್ ಪ್ರೊಟೆಕ್ಷನ್ ಆಫ್ ಆಗಿದೆ</string>
+ <!-- Content description: For the site security information icon (the site security icon).-->
+ <string name="mozac_browser_toolbar_content_description_site_info">ತಾಣದ ಮಾಹಿತಿ</string>
+ <!-- Announcement made by the screen reader when the progress bar is shown and a page is loading -->
+ <string name="mozac_browser_toolbar_progress_loading">ಲೋಡ್ ಆಗುತ್ತಿದೆ</string>
+ </resources>
diff --git a/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-ko/strings.xml b/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-ko/strings.xml
new file mode 100644
index 0000000000..ff3fcf3bcc
--- /dev/null
+++ b/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-ko/strings.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description (not visible, for screen readers etc.): Description for the overflow menu button in the browser toolbar. -->
+ <string name="mozac_browser_toolbar_menu_button">메뉴</string>
+ <!-- Content description: For the clear URL text button. -->
+ <string name="mozac_clear_button_description">지우기</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection enabled, but none trackers have been blocked or detected. -->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_on_no_trackers_blocked">추적 방지 기능이 켜져 있음</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection enabled, and trackers have been blocked or detected.-->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_on_trackers_blocked1">추적 방지 기능이 추적기를 차단함</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection disabled.-->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_off_for_a_site1">이 사이트에 추적 방지 기능이 꺼져 있음</string>
+ <!-- Content description: For the site security information icon (the site security icon).-->
+ <string name="mozac_browser_toolbar_content_description_site_info">사이트 정보</string>
+ <!-- Announcement made by the screen reader when the progress bar is shown and a page is loading -->
+ <string name="mozac_browser_toolbar_progress_loading">로드 중</string>
+ <!-- Content description: For the autoplay toolbar icon, it is set when the auto play permission is blocking content playing.-->
+ <string name="mozac_browser_toolbar_content_description_autoplay_blocked">자동 재생 설정에 의해 일부 콘텐츠가 차단되었습니다.</string>
+</resources>
diff --git a/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-ldrtl/dimens.xml b/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-ldrtl/dimens.xml
new file mode 100644
index 0000000000..a36c7c4366
--- /dev/null
+++ b/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-ldrtl/dimens.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- This Source Code Form is subject to the terms of the Mozilla Public
+ - License, v. 2.0. If a copy of the MPL was not distributed with this
+ - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
+<resources>
+ <!-- DisplayToolbar -->
+ <dimen name="mozac_browser_toolbar_origin_padding_end">16dp</dimen>
+</resources>
diff --git a/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-lij/strings.xml b/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-lij/strings.xml
new file mode 100644
index 0000000000..31fd025526
--- /dev/null
+++ b/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-lij/strings.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description (not visible, for screen readers etc.): Description for the overflow menu button in the browser toolbar. -->
+ <string name="mozac_browser_toolbar_menu_button">Menû</string>
+ <string name="mozac_clear_button_description">Scancella</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection enabled, but none trackers have been blocked or detected. -->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_on_no_trackers_blocked">Proteçion anti-traciamento açeiza</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection enabled, and trackers have been blocked or detected.-->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_on_trackers_blocked1">A proteçion anti-traciamento a l\'à blocou di traciatoî</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection disabled.-->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_off_for_a_site1">A proteçion anti-traciamento a l\'é asmortâ pe sto scito</string>
+ <!-- Content description: For the site security information icon (the site security icon).-->
+ <string name="mozac_browser_toolbar_content_description_site_info">Informaçioin do scito</string>
+ <!-- Announcement made by the screen reader when the progress bar is shown and a page is loading -->
+ <string name="mozac_browser_toolbar_progress_loading">Carego</string>
+ </resources>
diff --git a/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-lo/strings.xml b/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-lo/strings.xml
new file mode 100644
index 0000000000..d9327a731d
--- /dev/null
+++ b/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-lo/strings.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description (not visible, for screen readers etc.): Description for the overflow menu button in the browser toolbar. -->
+ <string name="mozac_browser_toolbar_menu_button">ເມນູ</string>
+ <string name="mozac_clear_button_description">ລົບລ້າງ</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection enabled, but none trackers have been blocked or detected. -->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_on_no_trackers_blocked">ການປ້ອງກັນການຕິດຕາມກຳລັງເປີດຢູ່</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection enabled, and trackers have been blocked or detected.-->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_on_trackers_blocked1">ການປ້ອງກັນການຕິດຕາມໄດ້ບັອກຕົວຕິດຕາມ</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection disabled.-->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_off_for_a_site1">ການປ້ອງກັນການຕິດຕາມໄດ້ປິດສຳລັບເວັບໄຊທນີ້</string>
+ <!-- Content description: For the site security information icon (the site security icon).-->
+ <string name="mozac_browser_toolbar_content_description_site_info">ຂໍ້ມູນເວັບໄຊ</string>
+ <!-- Announcement made by the screen reader when the progress bar is shown and a page is loading -->
+ <string name="mozac_browser_toolbar_progress_loading">ກຳລັງໂຫລດ</string>
+ <!-- Content description: For the autoplay toolbar icon, it is set when the auto play permission is blocking content playing.-->
+ <string name="mozac_browser_toolbar_content_description_autoplay_blocked">ເນື້ອຫາບາງອັນຖືກບລັອກໂດຍການຕັ້ງຄ່າການຫຼີ້ນອັດຕະໂນມັດ</string>
+</resources>
diff --git a/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-lt/strings.xml b/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-lt/strings.xml
new file mode 100644
index 0000000000..433b57f18e
--- /dev/null
+++ b/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-lt/strings.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description (not visible, for screen readers etc.): Description for the overflow menu button in the browser toolbar. -->
+ <string name="mozac_browser_toolbar_menu_button">Meniu</string>
+ <string name="mozac_clear_button_description">Išvalyti</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection enabled, but none trackers have been blocked or detected. -->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_on_no_trackers_blocked">Apsauga nuo stebėjimo įjungta</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection enabled, and trackers have been blocked or detected.-->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_on_trackers_blocked1">Apsaugo nuo stebėjimo užblokavo stebėjimo elementus</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection disabled.-->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_off_for_a_site1">Apsauga nuo stebėjimo šioje svetainėje išjungta</string>
+ <!-- Content description: For the site security information icon (the site security icon).-->
+ <string name="mozac_browser_toolbar_content_description_site_info">Svetainės informacija</string>
+ <!-- Announcement made by the screen reader when the progress bar is shown and a page is loading -->
+ <string name="mozac_browser_toolbar_progress_loading">Įkeliama</string>
+ <!-- Content description: For the autoplay toolbar icon, it is set when the auto play permission is blocking content playing.-->
+ <string name="mozac_browser_toolbar_content_description_autoplay_blocked">Dalį turinio užblokavo automatinio grojimo nuostatos</string>
+</resources>
diff --git a/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-mix/strings.xml b/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-mix/strings.xml
new file mode 100644
index 0000000000..1636f653d5
--- /dev/null
+++ b/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-mix/strings.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description (not visible, for screen readers etc.): Description for the overflow menu button in the browser toolbar. -->
+ <string name="mozac_browser_toolbar_menu_button">Katsi</string>
+ <string name="mozac_clear_button_description">Ku^un</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection enabled, but none trackers have been blocked or detected. -->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_on_no_trackers_blocked">Chika va^a ña sau</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection enabled, and trackers have been blocked or detected.-->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_on_trackers_blocked1">Chika va^a ña sau</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection disabled.-->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_off_for_a_site1">Chika va^a ña sau nu pagina yo^o </string>
+ <!-- Content description: For the site security information icon (the site security icon).-->
+ <string name="mozac_browser_toolbar_content_description_site_info">Tu^tu sitio yo^o</string>
+ <!-- Announcement made by the screen reader when the progress bar is shown and a page is loading -->
+ <string name="mozac_browser_toolbar_progress_loading">Sachuin</string>
+ <!-- Content description: For the autoplay toolbar icon, it is set when the auto play permission is blocking content playing.-->
+ <string name="mozac_browser_toolbar_content_description_autoplay_blocked">Ma ku kunu ña ku reproducción automática</string>
+</resources>
diff --git a/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-ml/strings.xml b/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-ml/strings.xml
new file mode 100644
index 0000000000..9f376452a4
--- /dev/null
+++ b/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-ml/strings.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description (not visible, for screen readers etc.): Description for the overflow menu button in the browser toolbar. -->
+ <string name="mozac_browser_toolbar_menu_button">മെനു</string>
+ <string name="mozac_clear_button_description">മായ്ക്കുക</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection enabled, but none trackers have been blocked or detected. -->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_on_no_trackers_blocked">ട്രാക്കിങ്ങ് സംരക്ഷണം ഓൺ ആണ്</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection enabled, and trackers have been blocked or detected.-->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_on_trackers_blocked1">ട്രാക്കിംഗ് സംരക്ഷണം ട്രാക്കറുകളെ തടഞ്ഞു</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection disabled.-->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_off_for_a_site1">ഈ സൈറ്റിന് ട്രാക്കിംഗ് പരിരക്ഷ ഇപ്പോൾ ഓഫാണ്</string>
+ <!-- Content description: For the site security information icon (the site security icon).-->
+ <string name="mozac_browser_toolbar_content_description_site_info">സൈറ്റ് വിവരങ്ങള്‍</string>
+ <!-- Announcement made by the screen reader when the progress bar is shown and a page is loading -->
+ <string name="mozac_browser_toolbar_progress_loading">ലഭ്യമാക്കുന്നു</string>
+ </resources>
diff --git a/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-mr/strings.xml b/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-mr/strings.xml
new file mode 100644
index 0000000000..5430ce7327
--- /dev/null
+++ b/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-mr/strings.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description (not visible, for screen readers etc.): Description for the overflow menu button in the browser toolbar. -->
+ <string name="mozac_browser_toolbar_menu_button">मेनू</string>
+ <string name="mozac_clear_button_description">साफ करा</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection enabled, but none trackers have been blocked or detected. -->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_on_no_trackers_blocked">ट्रॅकिंग संरक्षण चालू आहे</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection enabled, and trackers have been blocked or detected.-->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_on_trackers_blocked1">ट्रॅकिंग संरक्षणने ट्रॅकर्स अवरोधित केले आहेत</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection disabled.-->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_off_for_a_site1">या साइटसाठी ट्रॅकिंग संरक्षण बंद आहे</string>
+ <!-- Content description: For the site security information icon (the site security icon).-->
+ <string name="mozac_browser_toolbar_content_description_site_info">साईट माहिती</string>
+ <!-- Announcement made by the screen reader when the progress bar is shown and a page is loading -->
+ <string name="mozac_browser_toolbar_progress_loading">लोड होत आहे</string>
+ </resources>
diff --git a/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-my/strings.xml b/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-my/strings.xml
new file mode 100644
index 0000000000..006be61ee2
--- /dev/null
+++ b/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-my/strings.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description (not visible, for screen readers etc.): Description for the overflow menu button in the browser toolbar. -->
+ <string name="mozac_browser_toolbar_menu_button">စာရင်း</string>
+ <string name="mozac_clear_button_description">ရှင်းလင်းပါ</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection enabled, but none trackers have been blocked or detected. -->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_on_no_trackers_blocked">ခြေရာခံကာကွယ်မှုကို ဖွင့်ထားသည်</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection enabled, and trackers have been blocked or detected.-->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_on_trackers_blocked1">ခြေရာခံကာကွယ်မှုသည် ခြေရာခံသူများကိုပိတ်ဆို့ထားသည်။</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection disabled.-->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_off_for_a_site1">ဒီ site အတွက်အကာအကွယ်ပေးမှုကိုပိတ်ထားသည်</string>
+ <!-- Content description: For the site security information icon (the site security icon).-->
+ <string name="mozac_browser_toolbar_content_description_site_info">ဆိုက်အချက်အလက်</string>
+ <!-- Announcement made by the screen reader when the progress bar is shown and a page is loading -->
+ <string name="mozac_browser_toolbar_progress_loading">အလုပ်လုပ်နေတယ်</string>
+ <!-- Content description: For the autoplay toolbar icon, it is set when the auto play permission is blocking content playing.-->
+ <string name="mozac_browser_toolbar_content_description_autoplay_blocked">အလိုအလျောက်ဖွင့်ခြင်း ဆက်တင်မှ အကြောင်းအရာအချို့အား ပိတ်ထားသည်။</string>
+</resources>
diff --git a/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-nb-rNO/strings.xml b/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-nb-rNO/strings.xml
new file mode 100644
index 0000000000..9d9bcbfc13
--- /dev/null
+++ b/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-nb-rNO/strings.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description (not visible, for screen readers etc.): Description for the overflow menu button in the browser toolbar. -->
+ <string name="mozac_browser_toolbar_menu_button">Meny</string>
+ <!-- Content description: For the clear URL text button. -->
+ <string name="mozac_clear_button_description">Tøm</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection enabled, but none trackers have been blocked or detected. -->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_on_no_trackers_blocked">Sporingsbeskyttelse er på</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection enabled, and trackers have been blocked or detected.-->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_on_trackers_blocked1">Sporingsbeskyttelse har blokkert sporere</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection disabled.-->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_off_for_a_site1">Sporingsbeskyttelse er slått av for dette nettstedet</string>
+ <!-- Content description: For the site security information icon (the site security icon).-->
+ <string name="mozac_browser_toolbar_content_description_site_info">Informasjon om nettstedet</string>
+ <!-- Announcement made by the screen reader when the progress bar is shown and a page is loading -->
+ <string name="mozac_browser_toolbar_progress_loading">Laster</string>
+ <!-- Content description: For the autoplay toolbar icon, it is set when the auto play permission is blocking content playing.-->
+ <string name="mozac_browser_toolbar_content_description_autoplay_blocked">Noe av innholdet er blokkert av autoavspillings-innstillingene</string>
+</resources>
diff --git a/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-ne-rNP/strings.xml b/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-ne-rNP/strings.xml
new file mode 100644
index 0000000000..6a4341aafd
--- /dev/null
+++ b/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-ne-rNP/strings.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description (not visible, for screen readers etc.): Description for the overflow menu button in the browser toolbar. -->
+ <string name="mozac_browser_toolbar_menu_button">मेनु</string>
+ <string name="mozac_clear_button_description">खाली गर्नुहोस्</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection enabled, but none trackers have been blocked or detected. -->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_on_no_trackers_blocked">ट्र्याकिंग संरक्षण सक्रिय छ</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection enabled, and trackers have been blocked or detected.-->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_on_trackers_blocked1">ट्र्याकिङ्ग सुरक्षाले ट्रयाकरहरुलाई रोकेको छ</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection disabled.-->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_off_for_a_site1">हाल यस साइटको लागी ट्रयाकिङ् सुरक्षा बन्द गरिएको छ।</string>
+ <!-- Content description: For the site security information icon (the site security icon).-->
+ <string name="mozac_browser_toolbar_content_description_site_info">साइट जानकारी</string>
+ <!-- Announcement made by the screen reader when the progress bar is shown and a page is loading -->
+ <string name="mozac_browser_toolbar_progress_loading">लोड हुँदैछ</string>
+ <!-- Content description: For the autoplay toolbar icon, it is set when the auto play permission is blocking content playing.-->
+ <string name="mozac_browser_toolbar_content_description_autoplay_blocked">केहि सामग्री स्वतः प्ले सेटिङ्ग द्वारा रोकिएको छ</string>
+</resources>
diff --git a/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-nl/strings.xml b/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-nl/strings.xml
new file mode 100644
index 0000000000..fee481b12f
--- /dev/null
+++ b/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-nl/strings.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description (not visible, for screen readers etc.): Description for the overflow menu button in the browser toolbar. -->
+ <string name="mozac_browser_toolbar_menu_button">Menu</string>
+ <!-- Content description: For the clear URL text button. -->
+ <string name="mozac_clear_button_description">Wissen</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection enabled, but none trackers have been blocked or detected. -->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_on_no_trackers_blocked">Bescherming tegen volgen is ingeschakeld</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection enabled, and trackers have been blocked or detected.-->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_on_trackers_blocked1">Bescherming tegen volgen heeft trackers geblokkeerd</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection disabled.-->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_off_for_a_site1">Bescherming tegen volgen is uit voor deze website</string>
+ <!-- Content description: For the site security information icon (the site security icon).-->
+ <string name="mozac_browser_toolbar_content_description_site_info">Website-informatie</string>
+ <!-- Announcement made by the screen reader when the progress bar is shown and a page is loading -->
+ <string name="mozac_browser_toolbar_progress_loading">Laden</string>
+ <!-- Content description: For the autoplay toolbar icon, it is set when the auto play permission is blocking content playing.-->
+ <string name="mozac_browser_toolbar_content_description_autoplay_blocked">Sommige inhoud is geblokkeerd door de instelling voor automatisch afspelen</string>
+</resources>
diff --git a/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-nn-rNO/strings.xml b/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-nn-rNO/strings.xml
new file mode 100644
index 0000000000..c77b3373d0
--- /dev/null
+++ b/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-nn-rNO/strings.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description (not visible, for screen readers etc.): Description for the overflow menu button in the browser toolbar. -->
+ <string name="mozac_browser_toolbar_menu_button">Meny</string>
+ <!-- Content description: For the clear URL text button. -->
+ <string name="mozac_clear_button_description">Tøm</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection enabled, but none trackers have been blocked or detected. -->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_on_no_trackers_blocked">Sporingsvern er på</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection enabled, and trackers have been blocked or detected.-->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_on_trackers_blocked1">Sporingsvern har blokkert sporarar</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection disabled.-->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_off_for_a_site1">Sporingsvern er slått av for denne nettstaden</string>
+ <!-- Content description: For the site security information icon (the site security icon).-->
+ <string name="mozac_browser_toolbar_content_description_site_info">Informasjon om nettstaden</string>
+ <!-- Announcement made by the screen reader when the progress bar is shown and a page is loading -->
+ <string name="mozac_browser_toolbar_progress_loading">Lastar</string>
+ <!-- Content description: For the autoplay toolbar icon, it is set when the auto play permission is blocking content playing.-->
+ <string name="mozac_browser_toolbar_content_description_autoplay_blocked">Noko innhald har vorte blokkert av autoavspelings-innstillingane</string>
+</resources>
diff --git a/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-oc/strings.xml b/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-oc/strings.xml
new file mode 100644
index 0000000000..d2a72f26c1
--- /dev/null
+++ b/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-oc/strings.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description (not visible, for screen readers etc.): Description for the overflow menu button in the browser toolbar. -->
+ <string name="mozac_browser_toolbar_menu_button">Menú</string>
+ <!-- Content description: For the clear URL text button. -->
+ <string name="mozac_clear_button_description">Escafar</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection enabled, but none trackers have been blocked or detected. -->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_on_no_trackers_blocked">La proteccion contra lo seguiment es activada</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection enabled, and trackers have been blocked or detected.-->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_on_trackers_blocked1">La proteccion contra lo seguiment a blocat de traçadors</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection disabled.-->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_off_for_a_site1">La proteccion contra lo seguiment es desactivada per aqueste site</string>
+ <!-- Content description: For the site security information icon (the site security icon).-->
+ <string name="mozac_browser_toolbar_content_description_site_info">Informacions del site</string>
+ <!-- Announcement made by the screen reader when the progress bar is shown and a page is loading -->
+ <string name="mozac_browser_toolbar_progress_loading">Cargament</string>
+ <!-- Content description: For the autoplay toolbar icon, it is set when the auto play permission is blocking content playing.-->
+ <string name="mozac_browser_toolbar_content_description_autoplay_blocked">Una part del contengut es estada blocada per la configuracion de la lectura automatica</string>
+</resources>
diff --git a/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-or/strings.xml b/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-or/strings.xml
new file mode 100644
index 0000000000..9ca67e8959
--- /dev/null
+++ b/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-or/strings.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description (not visible, for screen readers etc.): Description for the overflow menu button in the browser toolbar. -->
+ <string name="mozac_browser_toolbar_menu_button">ମେନୁ</string>
+ <string name="mozac_clear_button_description">ଖାଲି କରନ୍ତୁ</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection enabled, but none trackers have been blocked or detected. -->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_on_no_trackers_blocked">ଟ୍ରାକିଂ ସୁରକ୍ଷା ଚାଲୁଛି</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection enabled, and trackers have been blocked or detected.-->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_on_trackers_blocked1">ଟ୍ରାକିଂ ସୁରକ୍ଷା ଟ୍ରାକରଗୁଡ଼ିକୁ ରୋକି ଦେଇଛି</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection disabled.-->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_off_for_a_site1">ଟ୍ରାକିଂ ସୁରକ୍ଷା ଏହି ସାଇଟ ପାଇଁ ବନ୍ଦ ଅଛି</string>
+ <!-- Content description: For the site security information icon (the site security icon).-->
+ <string name="mozac_browser_toolbar_content_description_site_info">ସାଇଟ ସୂଚନା</string>
+ <!-- Announcement made by the screen reader when the progress bar is shown and a page is loading -->
+ <string name="mozac_browser_toolbar_progress_loading">ଧାରଣ କରୁଅଛି</string>
+ </resources>
diff --git a/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-pa-rIN/strings.xml b/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-pa-rIN/strings.xml
new file mode 100644
index 0000000000..10a68745b3
--- /dev/null
+++ b/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-pa-rIN/strings.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description (not visible, for screen readers etc.): Description for the overflow menu button in the browser toolbar. -->
+ <string name="mozac_browser_toolbar_menu_button">ਮੇਨੂ</string>
+ <!-- Content description: For the clear URL text button. -->
+ <string name="mozac_clear_button_description">ਸਾਫ਼ ਕਰੋ</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection enabled, but none trackers have been blocked or detected. -->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_on_no_trackers_blocked">ਟਰੈਕ ਕਰਨ ਤੋਂ ਸੁਰੱਖਿਆ ਚਾਲੂ ਹੈ</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection enabled, and trackers have been blocked or detected.-->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_on_trackers_blocked1">ਟਰੈਕਿੰਗ ਸੁਰੱਖਿਆ ਟਰੈਕਾਂ ਉੱਤੇ ਪਾਬੰਦੀ ਲਗਾਉਂਦੀ ਹੈ</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection disabled.-->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_off_for_a_site1">ਇਸ ਸਾਈਟ ਲਈ ਟਰੈਕਿੰਗ ਸੁਰੱਖਿਆ ਬੰਦ ਹੈ</string>
+ <!-- Content description: For the site security information icon (the site security icon).-->
+ <string name="mozac_browser_toolbar_content_description_site_info">ਸਾਈਟ ਜਾਣਕਾਰੀ</string>
+ <!-- Announcement made by the screen reader when the progress bar is shown and a page is loading -->
+ <string name="mozac_browser_toolbar_progress_loading">ਲੋਡ ਹੋ ਰਿਹਾ ਹੈ</string>
+ <!-- Content description: For the autoplay toolbar icon, it is set when the auto play permission is blocking content playing.-->
+ <string name="mozac_browser_toolbar_content_description_autoplay_blocked">ਕੁਝ ਸਮੱਗਰੀ ਨੂੰ ਆਪੇ-ਪਲੇਅ ਦੀ ਸੈਟਿੰਗ ਰਾਹੀਂ ਪਾਬੰਦੀ ਲਾਈ ਹੈ</string>
+</resources>
diff --git a/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-pa-rPK/strings.xml b/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-pa-rPK/strings.xml
new file mode 100644
index 0000000000..f48af403b2
--- /dev/null
+++ b/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-pa-rPK/strings.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description (not visible, for screen readers etc.): Description for the overflow menu button in the browser toolbar. -->
+ <string name="mozac_browser_toolbar_menu_button">مینو</string>
+ <string name="mozac_clear_button_description">صاف کرو</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection enabled, but none trackers have been blocked or detected. -->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_on_no_trackers_blocked">ٹوہ لاوݨ توں سرکھیا چالو اے</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection enabled, and trackers have been blocked or detected.-->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_on_trackers_blocked1">ٹوہ لاوݨ توں کجھ روک لاۓ گئے ہن</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection disabled.-->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_off_for_a_site1">ٹوہ لاوݨ توں سرکھیا بند ہو گیا</string>
+ <!-- Content description: For the site security information icon (the site security icon).-->
+ <string name="mozac_browser_toolbar_content_description_site_info">سائٹ جاݨکاری</string>
+ <!-- Announcement made by the screen reader when the progress bar is shown and a page is loading -->
+ <string name="mozac_browser_toolbar_progress_loading">لوڈ کیتا جا رہا اے</string>
+ <!-- Content description: For the autoplay toolbar icon, it is set when the auto play permission is blocking content playing.-->
+ <string name="mozac_browser_toolbar_content_description_autoplay_blocked">خود بخود چلݨ نال کجھ وستوآں روکے گئے</string>
+</resources>
diff --git a/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-pl/strings.xml b/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-pl/strings.xml
new file mode 100644
index 0000000000..083dfd9aa9
--- /dev/null
+++ b/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-pl/strings.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description (not visible, for screen readers etc.): Description for the overflow menu button in the browser toolbar. -->
+ <string name="mozac_browser_toolbar_menu_button">Menu</string>
+ <!-- Content description: For the clear URL text button. -->
+ <string name="mozac_clear_button_description">Wyczyść</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection enabled, but none trackers have been blocked or detected. -->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_on_no_trackers_blocked">Ochrona przed śledzeniem jest włączona</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection enabled, and trackers have been blocked or detected.-->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_on_trackers_blocked1">Ochrona przed śledzeniem zablokowała elementy śledzące</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection disabled.-->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_off_for_a_site1">Ochrona przed śledzeniem jest wyłączona na tej witrynie</string>
+ <!-- Content description: For the site security information icon (the site security icon).-->
+ <string name="mozac_browser_toolbar_content_description_site_info">Informacje o witrynie</string>
+ <!-- Announcement made by the screen reader when the progress bar is shown and a page is loading -->
+ <string name="mozac_browser_toolbar_progress_loading">Wczytywanie</string>
+ <!-- Content description: For the autoplay toolbar icon, it is set when the auto play permission is blocking content playing.-->
+ <string name="mozac_browser_toolbar_content_description_autoplay_blocked">Część treści została zablokowana przez ustawienie automatycznego odtwarzania</string>
+</resources>
diff --git a/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-pt-rBR/strings.xml b/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-pt-rBR/strings.xml
new file mode 100644
index 0000000000..135bacdc26
--- /dev/null
+++ b/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-pt-rBR/strings.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description (not visible, for screen readers etc.): Description for the overflow menu button in the browser toolbar. -->
+ <string name="mozac_browser_toolbar_menu_button">Menu</string>
+ <!-- Content description: For the clear URL text button. -->
+ <string name="mozac_clear_button_description">Limpar</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection enabled, but none trackers have been blocked or detected. -->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_on_no_trackers_blocked">Proteção contra rastreamento ativada</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection enabled, and trackers have been blocked or detected.-->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_on_trackers_blocked1">A proteção contra rastreamento bloqueou rastreadores</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection disabled.-->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_off_for_a_site1">A proteção contra rastreamento está desativada neste site</string>
+ <!-- Content description: For the site security information icon (the site security icon).-->
+ <string name="mozac_browser_toolbar_content_description_site_info">Informações do site</string>
+ <!-- Announcement made by the screen reader when the progress bar is shown and a page is loading -->
+ <string name="mozac_browser_toolbar_progress_loading">Carregando</string>
+ <!-- Content description: For the autoplay toolbar icon, it is set when the auto play permission is blocking content playing.-->
+ <string name="mozac_browser_toolbar_content_description_autoplay_blocked">Algum conteúdo foi bloqueado pela configuração de reprodução automática</string>
+</resources>
diff --git a/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-pt-rPT/strings.xml b/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-pt-rPT/strings.xml
new file mode 100644
index 0000000000..bcd168a481
--- /dev/null
+++ b/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-pt-rPT/strings.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description (not visible, for screen readers etc.): Description for the overflow menu button in the browser toolbar. -->
+ <string name="mozac_browser_toolbar_menu_button">Menu</string>
+ <!-- Content description: For the clear URL text button. -->
+ <string name="mozac_clear_button_description">Limpar</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection enabled, but none trackers have been blocked or detected. -->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_on_no_trackers_blocked">Proteção contra monitorização está ativada</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection enabled, and trackers have been blocked or detected.-->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_on_trackers_blocked1">A proteção contra a monitorização bloqueou rastreadores</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection disabled.-->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_off_for_a_site1">A proteção contra monitorização está desativada para este site</string>
+ <!-- Content description: For the site security information icon (the site security icon).-->
+ <string name="mozac_browser_toolbar_content_description_site_info">Informação do site</string>
+ <!-- Announcement made by the screen reader when the progress bar is shown and a page is loading -->
+ <string name="mozac_browser_toolbar_progress_loading">A carregar</string>
+ <!-- Content description: For the autoplay toolbar icon, it is set when the auto play permission is blocking content playing.-->
+ <string name="mozac_browser_toolbar_content_description_autoplay_blocked">Algum conteúdo foi bloqueado pela configuração de reprodução automática</string>
+</resources>
diff --git a/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-rm/strings.xml b/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-rm/strings.xml
new file mode 100644
index 0000000000..d583fd3c77
--- /dev/null
+++ b/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-rm/strings.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description (not visible, for screen readers etc.): Description for the overflow menu button in the browser toolbar. -->
+ <string name="mozac_browser_toolbar_menu_button">Menu</string>
+ <!-- Content description: For the clear URL text button. -->
+ <string name="mozac_clear_button_description">Stizzar</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection enabled, but none trackers have been blocked or detected. -->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_on_no_trackers_blocked">La protecziun cunter il fastizar è activa</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection enabled, and trackers have been blocked or detected.-->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_on_trackers_blocked1">La protecziun cunter il fastizar ha bloccà fastizaders</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection disabled.-->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_off_for_a_site1">La protecziun cunter il fastizar è deactivada per questa website</string>
+ <!-- Content description: For the site security information icon (the site security icon).-->
+ <string name="mozac_browser_toolbar_content_description_site_info">Infurmaziuns davart la website</string>
+ <!-- Announcement made by the screen reader when the progress bar is shown and a page is loading -->
+ <string name="mozac_browser_toolbar_progress_loading">Chargiar</string>
+ <!-- Content description: For the autoplay toolbar icon, it is set when the auto play permission is blocking content playing.-->
+ <string name="mozac_browser_toolbar_content_description_autoplay_blocked">Tschert cuntegn è vegnì bloccà dal parameter da la reproducziun automatica</string>
+</resources>
diff --git a/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-ro/strings.xml b/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-ro/strings.xml
new file mode 100644
index 0000000000..72dee0c902
--- /dev/null
+++ b/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-ro/strings.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description (not visible, for screen readers etc.): Description for the overflow menu button in the browser toolbar. -->
+ <string name="mozac_browser_toolbar_menu_button">Meniu</string>
+ <string name="mozac_clear_button_description">Șterge</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection enabled, but none trackers have been blocked or detected. -->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_on_no_trackers_blocked">Protecția împotriva urmăririi este activată</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection enabled, and trackers have been blocked or detected.-->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_on_trackers_blocked1">Protecția împotriva urmăririi a blocat elementele de urmărire</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection disabled.-->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_off_for_a_site1">Protecția împotriva urmăririi este dezactivată pentru acest site</string>
+ <!-- Content description: For the site security information icon (the site security icon).-->
+ <string name="mozac_browser_toolbar_content_description_site_info">Informații despre site</string>
+ <!-- Announcement made by the screen reader when the progress bar is shown and a page is loading -->
+ <string name="mozac_browser_toolbar_progress_loading">Se încarcă</string>
+ </resources>
diff --git a/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-ru/strings.xml b/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-ru/strings.xml
new file mode 100644
index 0000000000..f722325b3a
--- /dev/null
+++ b/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-ru/strings.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description (not visible, for screen readers etc.): Description for the overflow menu button in the browser toolbar. -->
+ <string name="mozac_browser_toolbar_menu_button">Меню</string>
+ <!-- Content description: For the clear URL text button. -->
+ <string name="mozac_clear_button_description">Очистить</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection enabled, but none trackers have been blocked or detected. -->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_on_no_trackers_blocked">Защита от отслеживания включена</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection enabled, and trackers have been blocked or detected.-->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_on_trackers_blocked1">Защита от отслеживания заблокировала трекеры</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection disabled.-->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_off_for_a_site1">Защита от отслеживания отключена для этого сайта</string>
+ <!-- Content description: For the site security information icon (the site security icon).-->
+ <string name="mozac_browser_toolbar_content_description_site_info">Сведения о сайте</string>
+ <!-- Announcement made by the screen reader when the progress bar is shown and a page is loading -->
+ <string name="mozac_browser_toolbar_progress_loading">Загрузка</string>
+ <!-- Content description: For the autoplay toolbar icon, it is set when the auto play permission is blocking content playing.-->
+ <string name="mozac_browser_toolbar_content_description_autoplay_blocked">Некоторое содержимое было заблокировано настройками автовоспроизведения</string>
+</resources>
diff --git a/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-sat/strings.xml b/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-sat/strings.xml
new file mode 100644
index 0000000000..f363d29490
--- /dev/null
+++ b/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-sat/strings.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description (not visible, for screen readers etc.): Description for the overflow menu button in the browser toolbar. -->
+ <string name="mozac_browser_toolbar_menu_button">ᱢᱮᱱᱩ</string>
+ <!-- Content description: For the clear URL text button. -->
+ <string name="mozac_clear_button_description">ᱯᱷᱟᱨᱪᱟ</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection enabled, but none trackers have been blocked or detected. -->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_on_no_trackers_blocked">ᱯᱟᱸᱡᱟ ᱟᱰ ᱪᱟᱹᱞᱩ ᱢᱮᱱᱟᱜ-ᱟ</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection enabled, and trackers have been blocked or detected.-->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_on_trackers_blocked1">ᱯᱟᱸᱡᱟ ᱨᱚᱯᱷᱟ ᱯᱟᱧᱡᱟ ᱫᱟᱱᱟᱲ ᱠᱚ ᱟᱠᱚᱴ ᱠᱮᱜᱼᱟᱭ</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection disabled.-->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_off_for_a_site1">ᱯᱟᱸᱡᱟ ᱨᱚᱯᱷᱟ ᱵᱚᱸᱫᱚ ᱢᱮᱱᱟᱜ-ᱟ</string>
+ <!-- Content description: For the site security information icon (the site security icon).-->
+ <string name="mozac_browser_toolbar_content_description_site_info">ᱥᱟᱭᱤᱴ ᱨᱮᱭᱟᱜ ᱠᱷᱚᱵᱚᱨ</string>
+ <!-- Announcement made by the screen reader when the progress bar is shown and a page is loading -->
+ <string name="mozac_browser_toolbar_progress_loading">ᱞᱟᱫᱮᱜ ᱠᱟᱱᱟ</string>
+ <!-- Content description: For the autoplay toolbar icon, it is set when the auto play permission is blocking content playing.-->
+ <string name="mozac_browser_toolbar_content_description_autoplay_blocked">ᱟᱡ ᱛᱮ ᱮᱛᱦᱚᱵ ᱥᱟᱡᱟᱣ ᱠᱚ ᱠᱷᱟᱹᱛᱤᱨ ᱛᱮ ᱠᱤᱪᱷᱤ ᱡᱤᱱᱤᱥ ᱠᱚ ᱵᱞᱚᱠ ᱠᱟᱱᱟ</string>
+</resources>
diff --git a/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-sc/strings.xml b/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-sc/strings.xml
new file mode 100644
index 0000000000..f0b375f172
--- /dev/null
+++ b/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-sc/strings.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description (not visible, for screen readers etc.): Description for the overflow menu button in the browser toolbar. -->
+ <string name="mozac_browser_toolbar_menu_button">Menù</string>
+ <!-- Content description: For the clear URL text button. -->
+ <string name="mozac_clear_button_description">Isbòida</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection enabled, but none trackers have been blocked or detected. -->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_on_no_trackers_blocked">S’amparu contra sa sighidura est ativu</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection enabled, and trackers have been blocked or detected.-->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_on_trackers_blocked1">S’amparu contra sa sighidura at blocadu sighidores</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection disabled.-->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_off_for_a_site1">Sa protetzione contra sa sighidura est disativada pro custu situ</string>
+ <!-- Content description: For the site security information icon (the site security icon).-->
+ <string name="mozac_browser_toolbar_content_description_site_info">Informatziones de su situ</string>
+ <!-- Announcement made by the screen reader when the progress bar is shown and a page is loading -->
+ <string name="mozac_browser_toolbar_progress_loading">Carrighende</string>
+ <!-- Content description: For the autoplay toolbar icon, it is set when the auto play permission is blocking content playing.-->
+ <string name="mozac_browser_toolbar_content_description_autoplay_blocked">Sa funtzionalidade de riprodutzione automàtica at blocadu cuntenutos</string>
+</resources>
diff --git a/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-si/strings.xml b/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-si/strings.xml
new file mode 100644
index 0000000000..52a9db1744
--- /dev/null
+++ b/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-si/strings.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description (not visible, for screen readers etc.): Description for the overflow menu button in the browser toolbar. -->
+ <string name="mozac_browser_toolbar_menu_button">වට්ටෝරුව</string>
+ <!-- Content description: For the clear URL text button. -->
+ <string name="mozac_clear_button_description">මකන්න</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection enabled, but none trackers have been blocked or detected. -->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_on_no_trackers_blocked">ලුහුබැඳීමේ රැකවරණය සක්‍රියයි</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection enabled, and trackers have been blocked or detected.-->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_on_trackers_blocked1">ලුහුබැඳීමේ රැකවරණයෙන් අවහිරයි</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection disabled.-->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_off_for_a_site1">අඩවිය සඳහා ලුහුබැඳීමේ රැකවරණය අබලයි</string>
+ <!-- Content description: For the site security information icon (the site security icon).-->
+ <string name="mozac_browser_toolbar_content_description_site_info">අඩවියේ තොරතුරු</string>
+ <!-- Announcement made by the screen reader when the progress bar is shown and a page is loading -->
+ <string name="mozac_browser_toolbar_progress_loading">පූරණය වෙමින්</string>
+ <!-- Content description: For the autoplay toolbar icon, it is set when the auto play permission is blocking content playing.-->
+ <string name="mozac_browser_toolbar_content_description_autoplay_blocked">ස්වයං වාදන සැකසුම මගින් ඇතැම් අන්තර්ගත අවහිර වී ඇත</string>
+</resources>
diff --git a/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-sk/strings.xml b/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-sk/strings.xml
new file mode 100644
index 0000000000..d60ecd8152
--- /dev/null
+++ b/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-sk/strings.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description (not visible, for screen readers etc.): Description for the overflow menu button in the browser toolbar. -->
+ <string name="mozac_browser_toolbar_menu_button">Ponuka</string>
+ <!-- Content description: For the clear URL text button. -->
+ <string name="mozac_clear_button_description">Vymazať</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection enabled, but none trackers have been blocked or detected. -->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_on_no_trackers_blocked">Ochrana pred sledovaním je zapnutá</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection enabled, and trackers have been blocked or detected.-->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_on_trackers_blocked1">Ochrana pred sledovaním zablokovala sledovacie prvky</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection disabled.-->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_off_for_a_site1">Ochrana pred sledovaním je na tejto stránke vypnutá</string>
+ <!-- Content description: For the site security information icon (the site security icon).-->
+ <string name="mozac_browser_toolbar_content_description_site_info">Informácie o stránke</string>
+ <!-- Announcement made by the screen reader when the progress bar is shown and a page is loading -->
+ <string name="mozac_browser_toolbar_progress_loading">Načítava sa</string>
+ <!-- Content description: For the autoplay toolbar icon, it is set when the auto play permission is blocking content playing.-->
+ <string name="mozac_browser_toolbar_content_description_autoplay_blocked">Niektorý obsah bol zablokovaný nastavením automatického prehrávania</string>
+</resources>
diff --git a/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-skr/strings.xml b/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-skr/strings.xml
new file mode 100644
index 0000000000..ccf404cabd
--- /dev/null
+++ b/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-skr/strings.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description (not visible, for screen readers etc.): Description for the overflow menu button in the browser toolbar. -->
+ <string name="mozac_browser_toolbar_menu_button">مینیو</string>
+ <!-- Content description: For the clear URL text button. -->
+ <string name="mozac_clear_button_description">صاف کرو</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection enabled, but none trackers have been blocked or detected. -->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_on_no_trackers_blocked">سراغ کاری تحفظ چالو ہے</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection enabled, and trackers have been blocked or detected.-->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_on_trackers_blocked1">سراغ کاری تحفظ نے سُراغ رساں کوں بلاک کر ݙتا ہے</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection disabled.-->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_off_for_a_site1">سراغ کاری تحفظ ایں سائٹ کیتے بند ہے</string>
+ <!-- Content description: For the site security information icon (the site security icon).-->
+ <string name="mozac_browser_toolbar_content_description_site_info">سائٹ ڄاݨکاری</string>
+ <!-- Announcement made by the screen reader when the progress bar is shown and a page is loading -->
+ <string name="mozac_browser_toolbar_progress_loading">لوڈ تھیندا پئے</string>
+ <!-- Content description: For the autoplay toolbar icon, it is set when the auto play permission is blocking content playing.-->
+ <string name="mozac_browser_toolbar_content_description_autoplay_blocked">کجھ مواد کوں آٹو پلے ترتیباں نال بلاک کر ݙتا ڳئے</string>
+</resources>
diff --git a/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-sl/strings.xml b/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-sl/strings.xml
new file mode 100644
index 0000000000..0d7a545930
--- /dev/null
+++ b/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-sl/strings.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description (not visible, for screen readers etc.): Description for the overflow menu button in the browser toolbar. -->
+ <string name="mozac_browser_toolbar_menu_button">Meni</string>
+ <!-- Content description: For the clear URL text button. -->
+ <string name="mozac_clear_button_description">Počisti</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection enabled, but none trackers have been blocked or detected. -->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_on_no_trackers_blocked">Zaščita pred sledenjem je vključena</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection enabled, and trackers have been blocked or detected.-->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_on_trackers_blocked1">Zaščita pred sledenjem je zavrnila sledilce</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection disabled.-->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_off_for_a_site1">Zaščita pred sledenjem je za to spletno mesto izključena</string>
+ <!-- Content description: For the site security information icon (the site security icon).-->
+ <string name="mozac_browser_toolbar_content_description_site_info">Podatki o strani</string>
+ <!-- Announcement made by the screen reader when the progress bar is shown and a page is loading -->
+ <string name="mozac_browser_toolbar_progress_loading">Nalaganje</string>
+ <!-- Content description: For the autoplay toolbar icon, it is set when the auto play permission is blocking content playing.-->
+ <string name="mozac_browser_toolbar_content_description_autoplay_blocked">Nastavitev samodejnega predvajanja je zavrnila nekaj vsebine</string>
+</resources>
diff --git a/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-sq/strings.xml b/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-sq/strings.xml
new file mode 100644
index 0000000000..33b69257a5
--- /dev/null
+++ b/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-sq/strings.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description (not visible, for screen readers etc.): Description for the overflow menu button in the browser toolbar. -->
+ <string name="mozac_browser_toolbar_menu_button">Menu</string>
+ <!-- Content description: For the clear URL text button. -->
+ <string name="mozac_clear_button_description">Spastroje</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection enabled, but none trackers have been blocked or detected. -->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_on_no_trackers_blocked">Mbrojtje Nga Gjurmimet është aktive</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection enabled, and trackers have been blocked or detected.-->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_on_trackers_blocked1">Mbrojtja Nga Gjurmimet ka bllokuar gjurmues</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection disabled.-->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_off_for_a_site1">Mbrojtja Nga Gjurmimet është e çaktivizuar për këtë sajt</string>
+ <!-- Content description: For the site security information icon (the site security icon).-->
+ <string name="mozac_browser_toolbar_content_description_site_info">Hollësi sajti</string>
+ <!-- Announcement made by the screen reader when the progress bar is shown and a page is loading -->
+ <string name="mozac_browser_toolbar_progress_loading">Po ngarkohet</string>
+ <!-- Content description: For the autoplay toolbar icon, it is set when the auto play permission is blocking content playing.-->
+ <string name="mozac_browser_toolbar_content_description_autoplay_blocked">Është bllokuar lëndë nga rregullimi i vetëluajtjes</string>
+</resources>
diff --git a/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-sr/strings.xml b/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-sr/strings.xml
new file mode 100644
index 0000000000..5e70cab0c1
--- /dev/null
+++ b/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-sr/strings.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description (not visible, for screen readers etc.): Description for the overflow menu button in the browser toolbar. -->
+ <string name="mozac_browser_toolbar_menu_button">Мени</string>
+ <string name="mozac_clear_button_description">Обриши</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection enabled, but none trackers have been blocked or detected. -->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_on_no_trackers_blocked">Заштита од праћења је укључена</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection enabled, and trackers have been blocked or detected.-->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_on_trackers_blocked1">Заштита од праћења је блокирала пратиоце</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection disabled.-->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_off_for_a_site1">Заштита од праћења је искључена за ову страницу</string>
+ <!-- Content description: For the site security information icon (the site security icon).-->
+ <string name="mozac_browser_toolbar_content_description_site_info">Информације о страници</string>
+ <!-- Announcement made by the screen reader when the progress bar is shown and a page is loading -->
+ <string name="mozac_browser_toolbar_progress_loading">Учитавање</string>
+ <!-- Content description: For the autoplay toolbar icon, it is set when the auto play permission is blocking content playing.-->
+ <string name="mozac_browser_toolbar_content_description_autoplay_blocked">Неки садржај је блокиран због подешавања аутоматске репродукције</string>
+</resources>
diff --git a/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-su/strings.xml b/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-su/strings.xml
new file mode 100644
index 0000000000..af9bfdc6b0
--- /dev/null
+++ b/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-su/strings.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description (not visible, for screen readers etc.): Description for the overflow menu button in the browser toolbar. -->
+ <string name="mozac_browser_toolbar_menu_button">Menu</string>
+ <!-- Content description: For the clear URL text button. -->
+ <string name="mozac_clear_button_description">Beresihan</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection enabled, but none trackers have been blocked or detected. -->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_on_no_trackers_blocked">Kilung Palacakan keur hurung</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection enabled, and trackers have been blocked or detected.-->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_on_trackers_blocked1">Kilung Palacakan geus meungpeuk palacak</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection disabled.-->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_off_for_a_site1">Kilung Palacakan pareum pikeun ieu loka</string>
+ <!-- Content description: For the site security information icon (the site security icon).-->
+ <string name="mozac_browser_toolbar_content_description_site_info">Émbaran loka</string>
+ <!-- Announcement made by the screen reader when the progress bar is shown and a page is loading -->
+ <string name="mozac_browser_toolbar_progress_loading">Ngamuat</string>
+ <!-- Content description: For the autoplay toolbar icon, it is set when the auto play permission is blocking content playing.-->
+ <string name="mozac_browser_toolbar_content_description_autoplay_blocked">Sababaraha kontén dipeungpeuk ku setélan otoplay</string>
+</resources>
diff --git a/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-sv-rSE/strings.xml b/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-sv-rSE/strings.xml
new file mode 100644
index 0000000000..8922e20f5e
--- /dev/null
+++ b/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-sv-rSE/strings.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description (not visible, for screen readers etc.): Description for the overflow menu button in the browser toolbar. -->
+ <string name="mozac_browser_toolbar_menu_button">Meny</string>
+ <!-- Content description: For the clear URL text button. -->
+ <string name="mozac_clear_button_description">Rensa</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection enabled, but none trackers have been blocked or detected. -->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_on_no_trackers_blocked">Spårningsskydd är på</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection enabled, and trackers have been blocked or detected.-->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_on_trackers_blocked1">Spårningsskydd har blockerat spårare</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection disabled.-->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_off_for_a_site1">Spårningsskydd är avstängt för den här webbplatsen</string>
+ <!-- Content description: For the site security information icon (the site security icon).-->
+ <string name="mozac_browser_toolbar_content_description_site_info">Webbplatsinformation</string>
+ <!-- Announcement made by the screen reader when the progress bar is shown and a page is loading -->
+ <string name="mozac_browser_toolbar_progress_loading">Laddar</string>
+ <!-- Content description: For the autoplay toolbar icon, it is set when the auto play permission is blocking content playing.-->
+ <string name="mozac_browser_toolbar_content_description_autoplay_blocked">En del innehåll har blockerats av inställningen för automatisk uppspelning</string>
+</resources>
diff --git a/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-szl/strings.xml b/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-szl/strings.xml
new file mode 100644
index 0000000000..e6537d32b1
--- /dev/null
+++ b/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-szl/strings.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description (not visible, for screen readers etc.): Description for the overflow menu button in the browser toolbar. -->
+ <string name="mozac_browser_toolbar_menu_button">Myni</string>
+ <string name="mozac_clear_button_description">Wypucuj</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection enabled, but none trackers have been blocked or detected. -->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_on_no_trackers_blocked">Ôchrōna ôd śledzynio je załōnczōno</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection enabled, and trackers have been blocked or detected.-->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_on_trackers_blocked1">Ôchrōna ôd śledzynio szperuje śledzōnce elymynty</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection disabled.-->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_off_for_a_site1">Na tyj strōnie ôchrōna ôd śledzynio je wyłōnczōno</string>
+ <!-- Content description: For the site security information icon (the site security icon).-->
+ <string name="mozac_browser_toolbar_content_description_site_info">Informacyje ô strōnie</string>
+ <!-- Announcement made by the screen reader when the progress bar is shown and a page is loading -->
+ <string name="mozac_browser_toolbar_progress_loading">Ladowanie</string>
+ <!-- Content description: For the autoplay toolbar icon, it is set when the auto play permission is blocking content playing.-->
+ <string name="mozac_browser_toolbar_content_description_autoplay_blocked">Nasztalowanie autōmatycznego puszczanio zaszperowało kōnsek zawartości</string>
+</resources>
diff --git a/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-ta/strings.xml b/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-ta/strings.xml
new file mode 100644
index 0000000000..9b6e317f6c
--- /dev/null
+++ b/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-ta/strings.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description (not visible, for screen readers etc.): Description for the overflow menu button in the browser toolbar. -->
+ <string name="mozac_browser_toolbar_menu_button">பட்டி</string>
+ <string name="mozac_clear_button_description">துடை</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection enabled, but none trackers have been blocked or detected. -->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_on_no_trackers_blocked">தடமறியல் பாதுகாப்பு இயக்கத்தில்</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection enabled, and trackers have been blocked or detected.-->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_on_trackers_blocked1">தடமறியல் பாதுகாப்பு தடமறிவான்களை முடக்கியது</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection disabled.-->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_off_for_a_site1">தடமறியல் பாதுகாப்பு இத்தளத்தில் அணைக்கப்பட்டுள்ளது</string>
+ <!-- Content description: For the site security information icon (the site security icon).-->
+ <string name="mozac_browser_toolbar_content_description_site_info">தளத்தகவல்கள்</string>
+ <!-- Announcement made by the screen reader when the progress bar is shown and a page is loading -->
+ <string name="mozac_browser_toolbar_progress_loading">ஏற்றுகிறது</string>
+ <!-- Content description: For the autoplay toolbar icon, it is set when the auto play permission is blocking content playing.-->
+ <string name="mozac_browser_toolbar_content_description_autoplay_blocked">தன்னியக்க அமைப்பால் சில உள்ளடக்கம் தடுக்கப்பட்டுள்ளது</string>
+</resources>
diff --git a/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-te/strings.xml b/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-te/strings.xml
new file mode 100644
index 0000000000..504c84b58d
--- /dev/null
+++ b/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-te/strings.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description (not visible, for screen readers etc.): Description for the overflow menu button in the browser toolbar. -->
+ <string name="mozac_browser_toolbar_menu_button">మెనూ</string>
+ <string name="mozac_clear_button_description">తుడిచివేయి</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection enabled, but none trackers have been blocked or detected. -->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_on_no_trackers_blocked">ట్రాకింగ్ సంరక్షణ చేతనంగా ఉంది</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection enabled, and trackers have been blocked or detected.-->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_on_trackers_blocked1">ట్రాకింగ్ సంరక్షణ ట్రాకర్లను నిరోధించింది</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection disabled.-->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_off_for_a_site1">ఈ సైటుకి ట్రాకింగ్ సంరక్షణ ఆపివేయబడింది</string>
+ <!-- Content description: For the site security information icon (the site security icon).-->
+ <string name="mozac_browser_toolbar_content_description_site_info">సైటు సమాచారం</string>
+ <!-- Announcement made by the screen reader when the progress bar is shown and a page is loading -->
+ <string name="mozac_browser_toolbar_progress_loading">వస్తోంది</string>
+ <!-- Content description: For the autoplay toolbar icon, it is set when the auto play permission is blocking content playing.-->
+ <string name="mozac_browser_toolbar_content_description_autoplay_blocked">ఆటోప్లే అమరిక ద్వారా కొంత కంటెంట్ నిరోధించబడింది</string>
+</resources>
diff --git a/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-tg/strings.xml b/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-tg/strings.xml
new file mode 100644
index 0000000000..0fed273e55
--- /dev/null
+++ b/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-tg/strings.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description (not visible, for screen readers etc.): Description for the overflow menu button in the browser toolbar. -->
+ <string name="mozac_browser_toolbar_menu_button">Меню</string>
+ <!-- Content description: For the clear URL text button. -->
+ <string name="mozac_clear_button_description">Пок кардан</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection enabled, but none trackers have been blocked or detected. -->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_on_no_trackers_blocked">Муҳофизат аз пайгирӣ фаъол аст</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection enabled, and trackers have been blocked or detected.-->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_on_trackers_blocked1">Муҳофизат аз пайгирӣ васоити пайгириро манъ кард</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection disabled.-->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_off_for_a_site1">Муҳофизат аз пайгирӣ барои ин сомона хомӯш аст</string>
+ <!-- Content description: For the site security information icon (the site security icon).-->
+ <string name="mozac_browser_toolbar_content_description_site_info">Маълумот дар бораи сомона</string>
+ <!-- Announcement made by the screen reader when the progress bar is shown and a page is loading -->
+ <string name="mozac_browser_toolbar_progress_loading">Бор шуда истодааст</string>
+ <!-- Content description: For the autoplay toolbar icon, it is set when the auto play permission is blocking content playing.-->
+ <string name="mozac_browser_toolbar_content_description_autoplay_blocked">Баъзеи муҳтаво тавассути танзими пахши худкор манъ карда шуд</string>
+</resources>
diff --git a/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-th/strings.xml b/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-th/strings.xml
new file mode 100644
index 0000000000..55f06924fa
--- /dev/null
+++ b/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-th/strings.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description (not visible, for screen readers etc.): Description for the overflow menu button in the browser toolbar. -->
+ <string name="mozac_browser_toolbar_menu_button">เมนู</string>
+ <string name="mozac_clear_button_description">ล้าง</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection enabled, but none trackers have been blocked or detected. -->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_on_no_trackers_blocked">การป้องกันการติดตามเปิดอยู่</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection enabled, and trackers have been blocked or detected.-->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_on_trackers_blocked1">การป้องกันการติดตามได้ปิดกั้นตัวติดตาม</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection disabled.-->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_off_for_a_site1">การป้องกันการติดตามปิดอยู่สำหรับไซต์นี้</string>
+ <!-- Content description: For the site security information icon (the site security icon).-->
+ <string name="mozac_browser_toolbar_content_description_site_info">ข้อมูลไซต์</string>
+ <!-- Announcement made by the screen reader when the progress bar is shown and a page is loading -->
+ <string name="mozac_browser_toolbar_progress_loading">กำลังโหลด</string>
+ <!-- Content description: For the autoplay toolbar icon, it is set when the auto play permission is blocking content playing.-->
+ <string name="mozac_browser_toolbar_content_description_autoplay_blocked">เนื้อหาบางส่วนถูกปิดกั้นด้วยการตั้งค่าเล่นอัตโนมัติ</string>
+</resources>
diff --git a/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-tl/strings.xml b/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-tl/strings.xml
new file mode 100644
index 0000000000..4e5e6b3300
--- /dev/null
+++ b/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-tl/strings.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description (not visible, for screen readers etc.): Description for the overflow menu button in the browser toolbar. -->
+ <string name="mozac_browser_toolbar_menu_button">Menu</string>
+ <string name="mozac_clear_button_description">Burahin</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection enabled, but none trackers have been blocked or detected. -->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_on_no_trackers_blocked">Nakabukas ang Tracking Protection</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection enabled, and trackers have been blocked or detected.-->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_on_trackers_blocked1">May naharang na mga tracker ang Tracking Protection</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection disabled.-->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_off_for_a_site1">Nakasara ang Tracking Protection sa site na ito</string>
+ <!-- Content description: For the site security information icon (the site security icon).-->
+ <string name="mozac_browser_toolbar_content_description_site_info">Impormasyon sa site</string>
+ <!-- Announcement made by the screen reader when the progress bar is shown and a page is loading -->
+ <string name="mozac_browser_toolbar_progress_loading">Naglo-load</string>
+ <!-- Content description: For the autoplay toolbar icon, it is set when the auto play permission is blocking content playing.-->
+ <string name="mozac_browser_toolbar_content_description_autoplay_blocked">May ilang content na naharang dahil sa autoplay setting</string>
+</resources>
diff --git a/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-tok/strings.xml b/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-tok/strings.xml
new file mode 100644
index 0000000000..d9f3149d1b
--- /dev/null
+++ b/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-tok/strings.xml
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <string name="mozac_clear_button_description">o weka ale</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection enabled, but none trackers have been blocked or detected. -->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_on_no_trackers_blocked">lipu li ken ala lukin e sona sina</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection enabled, and trackers have been blocked or detected.-->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_on_trackers_blocked1">lipu li weka e lipu lukin</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection disabled.-->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_off_for_a_site1">lipu ni la weka pi lipu lukin li lon ala</string>
+ <!-- Content description: For the site security information icon (the site security icon).-->
+ <string name="mozac_browser_toolbar_content_description_site_info">sona lipu</string>
+ <!-- Announcement made by the screen reader when the progress bar is shown and a page is loading -->
+ <string name="mozac_browser_toolbar_progress_loading">o awen</string>
+ </resources>
diff --git a/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-tr/strings.xml b/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-tr/strings.xml
new file mode 100644
index 0000000000..904675f6e9
--- /dev/null
+++ b/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-tr/strings.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description (not visible, for screen readers etc.): Description for the overflow menu button in the browser toolbar. -->
+ <string name="mozac_browser_toolbar_menu_button">Menü</string>
+ <!-- Content description: For the clear URL text button. -->
+ <string name="mozac_clear_button_description">Temizle</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection enabled, but none trackers have been blocked or detected. -->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_on_no_trackers_blocked">İzlenme koruması açık</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection enabled, and trackers have been blocked or detected.-->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_on_trackers_blocked1">İzlenme koruması, takip kodlarını engelledi</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection disabled.-->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_off_for_a_site1">Bu sitede izlenme koruması kapalı</string>
+ <!-- Content description: For the site security information icon (the site security icon).-->
+ <string name="mozac_browser_toolbar_content_description_site_info">Site bilgileri</string>
+ <!-- Announcement made by the screen reader when the progress bar is shown and a page is loading -->
+ <string name="mozac_browser_toolbar_progress_loading">Yükleniyor</string>
+ <!-- Content description: For the autoplay toolbar icon, it is set when the auto play permission is blocking content playing.-->
+ <string name="mozac_browser_toolbar_content_description_autoplay_blocked">Otomatik oynatma ayarınız bazı içerikleri engelledi</string>
+</resources>
diff --git a/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-trs/strings.xml b/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-trs/strings.xml
new file mode 100644
index 0000000000..ef86e00be9
--- /dev/null
+++ b/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-trs/strings.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description (not visible, for screen readers etc.): Description for the overflow menu button in the browser toolbar. -->
+ <string name="mozac_browser_toolbar_menu_button">Menû</string>
+ <string name="mozac_clear_button_description">Nā\'nïn\'</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection enabled, but none trackers have been blocked or detected. -->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_on_no_trackers_blocked">Sa narrán riña sa naga\'nāj a</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection enabled, and trackers have been blocked or detected.-->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_on_trackers_blocked1">Narrán sa dugumî ñù\' riña nej sa naga\'nāj a</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection disabled.-->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_off_for_a_site1">Nitāj si \'iaj sun sa narán riña sa naga\'nāj a riña sitiô nan</string>
+ <!-- Content description: For the site security information icon (the site security icon).-->
+ <string name="mozac_browser_toolbar_content_description_site_info">Nuguan\' huā rayi\'î sitiô nan</string>
+ <!-- Announcement made by the screen reader when the progress bar is shown and a page is loading -->
+ <string name="mozac_browser_toolbar_progress_loading">Hìaj ayì\'ij</string>
+ <!-- Content description: For the autoplay toolbar icon, it is set when the auto play permission is blocking content playing.-->
+ <string name="mozac_browser_toolbar_content_description_autoplay_blocked">Huā da’āj nej sa mà riñaj narán gi’iaj guendâ nù sa duguachín man’an sa ni’io’</string>
+</resources>
diff --git a/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-tt/strings.xml b/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-tt/strings.xml
new file mode 100644
index 0000000000..3a463ee5cf
--- /dev/null
+++ b/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-tt/strings.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description (not visible, for screen readers etc.): Description for the overflow menu button in the browser toolbar. -->
+ <string name="mozac_browser_toolbar_menu_button">Меню</string>
+ <string name="mozac_clear_button_description">Чистарту</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection enabled, but none trackers have been blocked or detected. -->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_on_no_trackers_blocked">Күзәтелүдән Саклау кабызылган</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection enabled, and trackers have been blocked or detected.-->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_on_trackers_blocked1">Күзәтүдән саклау күзәтеп торучыларны блоклады</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection disabled.-->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_off_for_a_site1">Бу сайт өчен Күзәтелүдән Саклау сүндерелгән</string>
+ <!-- Content description: For the site security information icon (the site security icon).-->
+ <string name="mozac_browser_toolbar_content_description_site_info">Сайт турында мәгълүмат</string>
+ <!-- Announcement made by the screen reader when the progress bar is shown and a page is loading -->
+ <string name="mozac_browser_toolbar_progress_loading">Йөкләү</string>
+ <!-- Content description: For the autoplay toolbar icon, it is set when the auto play permission is blocking content playing.-->
+ <string name="mozac_browser_toolbar_content_description_autoplay_blocked">Автоуйнату көйләүләре аркасында кайбер эчтәлекләр блокланды</string>
+</resources>
diff --git a/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-tzm/strings.xml b/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-tzm/strings.xml
new file mode 100644
index 0000000000..d451c5972c
--- /dev/null
+++ b/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-tzm/strings.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description (not visible, for screen readers etc.): Description for the overflow menu button in the browser toolbar. -->
+ <string name="mozac_browser_toolbar_menu_button">Umuɣ</string>
+ <string name="mozac_clear_button_description">Sfeḍ</string>
+ <!-- Content description: For the site security information icon (the site security icon).-->
+ <string name="mozac_browser_toolbar_content_description_site_info">Asmel n wasit</string>
+ <!-- Announcement made by the screen reader when the progress bar is shown and a page is loading -->
+ <string name="mozac_browser_toolbar_progress_loading">Asali</string>
+ </resources>
diff --git a/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-ug/strings.xml b/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-ug/strings.xml
new file mode 100644
index 0000000000..89e5173df3
--- /dev/null
+++ b/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-ug/strings.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description (not visible, for screen readers etc.): Description for the overflow menu button in the browser toolbar. -->
+ <string name="mozac_browser_toolbar_menu_button">تىزىملىك</string>
+ <!-- Content description: For the clear URL text button. -->
+ <string name="mozac_clear_button_description">تازىلا</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection enabled, but none trackers have been blocked or detected. -->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_on_no_trackers_blocked">ئىزلاشتىن توسۇش ئىقتىدارى ئوچۇق</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection enabled, and trackers have been blocked or detected.-->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_on_trackers_blocked1">ئىز قوغلاش قوغدىغۇچىسى ئىز قوغلىغۇچىلارنى توستى</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection disabled.-->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_off_for_a_site1">بۇ توربېكەتكە نىسبەتەن ئىزلاشتىن قوغداش تاقاق</string>
+ <!-- Content description: For the site security information icon (the site security icon).-->
+ <string name="mozac_browser_toolbar_content_description_site_info">بېكەت ئۇچۇرى</string>
+ <!-- Announcement made by the screen reader when the progress bar is shown and a page is loading -->
+ <string name="mozac_browser_toolbar_progress_loading">يۈكلەۋاتىدۇ</string>
+ <!-- Content description: For the autoplay toolbar icon, it is set when the auto play permission is blocking content playing.-->
+ <string name="mozac_browser_toolbar_content_description_autoplay_blocked">بەزى مەزمۇنلارنى ئاپتوماتىك قويۇش تەڭشىكى توستى</string>
+</resources>
diff --git a/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-uk/strings.xml b/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-uk/strings.xml
new file mode 100644
index 0000000000..1460d015dd
--- /dev/null
+++ b/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-uk/strings.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description (not visible, for screen readers etc.): Description for the overflow menu button in the browser toolbar. -->
+ <string name="mozac_browser_toolbar_menu_button">Меню</string>
+ <!-- Content description: For the clear URL text button. -->
+ <string name="mozac_clear_button_description">Очистити</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection enabled, but none trackers have been blocked or detected. -->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_on_no_trackers_blocked">Захист від стеження увімкнено</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection enabled, and trackers have been blocked or detected.-->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_on_trackers_blocked1">Захист від стеження заблокував стеження</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection disabled.-->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_off_for_a_site1">Захист від стеження вимкнено для цього сайту</string>
+ <!-- Content description: For the site security information icon (the site security icon).-->
+ <string name="mozac_browser_toolbar_content_description_site_info">Інформація про сайт</string>
+ <!-- Announcement made by the screen reader when the progress bar is shown and a page is loading -->
+ <string name="mozac_browser_toolbar_progress_loading">Завантаження</string>
+ <!-- Content description: For the autoplay toolbar icon, it is set when the auto play permission is blocking content playing.-->
+ <string name="mozac_browser_toolbar_content_description_autoplay_blocked">Деякий вміст заблоковано налаштуванням автовідтворення</string>
+</resources>
diff --git a/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-ur/strings.xml b/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-ur/strings.xml
new file mode 100644
index 0000000000..78470d254c
--- /dev/null
+++ b/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-ur/strings.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description (not visible, for screen readers etc.): Description for the overflow menu button in the browser toolbar. -->
+ <string name="mozac_browser_toolbar_menu_button">مینیو</string>
+ <string name="mozac_clear_button_description">صاف کریں</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection enabled, but none trackers have been blocked or detected. -->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_on_no_trackers_blocked">سراغ کاری تحفظ چالو ہے</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection enabled, and trackers have been blocked or detected.-->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_on_trackers_blocked1">سراغ کاری تحفظ نے سُراغ رساں کو مسدود کردیا ہے</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection disabled.-->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_off_for_a_site1">سراغ کاری تحفظ اس سائٹ کے لیئے بند ہے</string>
+ <!-- Content description: For the site security information icon (the site security icon).-->
+ <string name="mozac_browser_toolbar_content_description_site_info">سائٹ کی معلومات</string>
+ <!-- Announcement made by the screen reader when the progress bar is shown and a page is loading -->
+ <string name="mozac_browser_toolbar_progress_loading">لوڈ کر رہا ہے</string>
+ <!-- Content description: For the autoplay toolbar icon, it is set when the auto play permission is blocking content playing.-->
+ <string name="mozac_browser_toolbar_content_description_autoplay_blocked">کچھ مشمولات کو آٹو پلے سیٹنگ سے مسدود کردیا گیا ہے</string>
+</resources>
diff --git a/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-uz/strings.xml b/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-uz/strings.xml
new file mode 100644
index 0000000000..ec69af71f6
--- /dev/null
+++ b/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-uz/strings.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description (not visible, for screen readers etc.): Description for the overflow menu button in the browser toolbar. -->
+ <string name="mozac_browser_toolbar_menu_button">Menyu</string>
+ <string name="mozac_clear_button_description">Tozalash</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection enabled, but none trackers have been blocked or detected. -->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_on_no_trackers_blocked">Kuzatuvdan himoya yoniq</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection enabled, and trackers have been blocked or detected.-->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_on_trackers_blocked1">Kuzatuvdan himoya funksiyasi kuzatuvchilarni blokladi</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection disabled.-->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_off_for_a_site1">Bu sayt uchun kuzatuvdan himoya funksiyasi oʻchirilgan</string>
+ <!-- Content description: For the site security information icon (the site security icon).-->
+ <string name="mozac_browser_toolbar_content_description_site_info">Sayt maʼlumoti</string>
+ <!-- Announcement made by the screen reader when the progress bar is shown and a page is loading -->
+ <string name="mozac_browser_toolbar_progress_loading">Yuklanmoqda</string>
+ <!-- Content description: For the autoplay toolbar icon, it is set when the auto play permission is blocking content playing.-->
+ <string name="mozac_browser_toolbar_content_description_autoplay_blocked">Avtomatik ishga tushirish sozlamasi tufayli ayrim kontentlar bloklandi</string>
+</resources>
diff --git a/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-vec/strings.xml b/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-vec/strings.xml
new file mode 100644
index 0000000000..15a625bcbc
--- /dev/null
+++ b/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-vec/strings.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description (not visible, for screen readers etc.): Description for the overflow menu button in the browser toolbar. -->
+ <string name="mozac_browser_toolbar_menu_button">Menu</string>
+ <string name="mozac_clear_button_description">Pulisi</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection enabled, but none trackers have been blocked or detected. -->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_on_no_trackers_blocked">Ƚa protesion antitraciamento ƚa xe ativa</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection enabled, and trackers have been blocked or detected.-->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_on_trackers_blocked1">Ƚa protesion antitraciamento ƚa ga blocà contenudi tracianti</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection disabled.-->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_off_for_a_site1">Ƚa protesion antitraciamento ƚa xe disativà par sto sito</string>
+ <!-- Content description: For the site security information icon (the site security icon).-->
+ <string name="mozac_browser_toolbar_content_description_site_info">Informasioni sito</string>
+ <!-- Announcement made by the screen reader when the progress bar is shown and a page is loading -->
+ <string name="mozac_browser_toolbar_progress_loading">Cargamento</string>
+ </resources>
diff --git a/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-vi/strings.xml b/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-vi/strings.xml
new file mode 100644
index 0000000000..c3c54456ed
--- /dev/null
+++ b/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-vi/strings.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description (not visible, for screen readers etc.): Description for the overflow menu button in the browser toolbar. -->
+ <string name="mozac_browser_toolbar_menu_button">Menu</string>
+ <!-- Content description: For the clear URL text button. -->
+ <string name="mozac_clear_button_description">Xóa</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection enabled, but none trackers have been blocked or detected. -->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_on_no_trackers_blocked">Trình chống theo dõi đang bật</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection enabled, and trackers have been blocked or detected.-->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_on_trackers_blocked1">Trình chống theo dõi đã chặn trình theo dõi</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection disabled.-->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_off_for_a_site1">Đã tắt Trình chống theo dõi cho trang web này</string>
+ <!-- Content description: For the site security information icon (the site security icon).-->
+ <string name="mozac_browser_toolbar_content_description_site_info">Thông tin về trang web</string>
+ <!-- Announcement made by the screen reader when the progress bar is shown and a page is loading -->
+ <string name="mozac_browser_toolbar_progress_loading">Đang tải</string>
+ <!-- Content description: For the autoplay toolbar icon, it is set when the auto play permission is blocking content playing.-->
+ <string name="mozac_browser_toolbar_content_description_autoplay_blocked">Một số nội dung đã bị chặn bởi cài đặt tự động phát</string>
+</resources>
diff --git a/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-yo/strings.xml b/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-yo/strings.xml
new file mode 100644
index 0000000000..6f46be1286
--- /dev/null
+++ b/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-yo/strings.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description (not visible, for screen readers etc.): Description for the overflow menu button in the browser toolbar. -->
+ <string name="mozac_browser_toolbar_menu_button">Mẹ́nù</string>
+ <string name="mozac_clear_button_description">Paárẹ́</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection enabled, but none trackers have been blocked or detected. -->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_on_no_trackers_blocked">Ìtọpinpin Ìdàábòbò wà ní títàn </string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection enabled, and trackers have been blocked or detected.-->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_on_trackers_blocked1">Ìtọpinpin ìdàábòbò ti dènà atọpinpin</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection disabled.-->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_off_for_a_site1">Ìtọpinpin ìdàábòbò ti di pípa fún ìkànnì yìí</string>
+ <!-- Content description: For the site security information icon (the site security icon).-->
+ <string name="mozac_browser_toolbar_content_description_site_info">Ìfitóniléti ìkànnì</string>
+ <!-- Announcement made by the screen reader when the progress bar is shown and a page is loading -->
+ <string name="mozac_browser_toolbar_progress_loading">Ó ń gbáradì</string>
+ <!-- Content description: For the autoplay toolbar icon, it is set when the auto play permission is blocking content playing.-->
+ <string name="mozac_browser_toolbar_content_description_autoplay_blocked">Àwọn àkòónú kan ti di dídénà ààtò ìfi-ara-ẹni-ṣisẹ́</string>
+</resources>
diff --git a/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-zh-rCN/strings.xml b/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-zh-rCN/strings.xml
new file mode 100644
index 0000000000..3cb765dc23
--- /dev/null
+++ b/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-zh-rCN/strings.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description (not visible, for screen readers etc.): Description for the overflow menu button in the browser toolbar. -->
+ <string name="mozac_browser_toolbar_menu_button">菜单</string>
+ <!-- Content description: For the clear URL text button. -->
+ <string name="mozac_clear_button_description">清除</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection enabled, but none trackers have been blocked or detected. -->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_on_no_trackers_blocked">已开启跟踪保护</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection enabled, and trackers have been blocked or detected.-->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_on_trackers_blocked1">跟踪保护已拦截跟踪器</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection disabled.-->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_off_for_a_site1">已关闭对此网站的跟踪保护</string>
+ <!-- Content description: For the site security information icon (the site security icon).-->
+ <string name="mozac_browser_toolbar_content_description_site_info">网站信息</string>
+ <!-- Announcement made by the screen reader when the progress bar is shown and a page is loading -->
+ <string name="mozac_browser_toolbar_progress_loading">正在加载</string>
+ <!-- Content description: For the autoplay toolbar icon, it is set when the auto play permission is blocking content playing.-->
+ <string name="mozac_browser_toolbar_content_description_autoplay_blocked">某些内容已被自动播放设置阻止</string>
+</resources>
diff --git a/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-zh-rTW/strings.xml b/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-zh-rTW/strings.xml
new file mode 100644
index 0000000000..d1d023f3db
--- /dev/null
+++ b/mobile/android/android-components/components/browser/toolbar2/src/main/res/values-zh-rTW/strings.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Content description (not visible, for screen readers etc.): Description for the overflow menu button in the browser toolbar. -->
+ <string name="mozac_browser_toolbar_menu_button">選單</string>
+ <!-- Content description: For the clear URL text button. -->
+ <string name="mozac_clear_button_description">清除</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection enabled, but none trackers have been blocked or detected. -->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_on_no_trackers_blocked">追蹤保護功能已開啟</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection enabled, and trackers have been blocked or detected.-->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_on_trackers_blocked1">追蹤保護功能已封鎖追蹤器</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection disabled.-->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_off_for_a_site1">已關閉針對此網站的追蹤保護功能</string>
+ <!-- Content description: For the site security information icon (the site security icon).-->
+ <string name="mozac_browser_toolbar_content_description_site_info">網站資訊</string>
+ <!-- Announcement made by the screen reader when the progress bar is shown and a page is loading -->
+ <string name="mozac_browser_toolbar_progress_loading">載入中</string>
+ <!-- Content description: For the autoplay toolbar icon, it is set when the auto play permission is blocking content playing.-->
+ <string name="mozac_browser_toolbar_content_description_autoplay_blocked">某些內容已由自動播放設定封鎖</string>
+</resources>
diff --git a/mobile/android/android-components/components/browser/toolbar2/src/main/res/values/attrs_browser_toolbar.xml b/mobile/android/android-components/components/browser/toolbar2/src/main/res/values/attrs_browser_toolbar.xml
new file mode 100644
index 0000000000..431bb6b080
--- /dev/null
+++ b/mobile/android/android-components/components/browser/toolbar2/src/main/res/values/attrs_browser_toolbar.xml
@@ -0,0 +1,33 @@
+<?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>
+ <declare-styleable name="BrowserToolbar">
+ <attr name="browserToolbarHintColor" format="color"/>
+ <attr name="browserToolbarTextColor" format="color"/>
+ <attr name="browserToolbarTextSize" format="dimension"/>
+ <attr name="browserToolbarSecurityIcon" format="reference"/>
+ <attr name="browserToolbarInsecureColor" format="color"/>
+ <attr name="browserToolbarSecureColor" format="color"/>
+ <attr name="browserToolbarMenuColor" format="color"/>
+ <attr name="browserToolbarSuggestionBackgroundColor" format="color" />
+ <attr name="browserToolbarSuggestionForegroundColor" format="color" />
+ <attr name="browserToolbarClearColor" format="color"/>
+ <attr name="browserToolbarTrackingProtectionAndSecurityIndicatorSeparatorColor" format="color"/>
+ <attr name="browserToolbarFadingEdgeSize" format="dimension" />
+ <attr name="browserToolbarProgressBarGravity">
+ <enum name="bottom" value="0" />
+ <enum name="top" value="1" />
+ </attr>
+ </declare-styleable>
+
+ <declare-styleable name="BrowserToolbarSiteSecurityState">
+ <attr name="state_site_secure" format="boolean"/>
+ </declare-styleable>
+
+ <declare-styleable name="ActionContainer">
+ <attr name="actionContainerItemSize" format="dimension" />
+ </declare-styleable>
+</resources>
diff --git a/mobile/android/android-components/components/browser/toolbar2/src/main/res/values/dimens.xml b/mobile/android/android-components/components/browser/toolbar2/src/main/res/values/dimens.xml
new file mode 100644
index 0000000000..23fd755686
--- /dev/null
+++ b/mobile/android/android-components/components/browser/toolbar2/src/main/res/values/dimens.xml
@@ -0,0 +1,31 @@
+<?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_browser_toolbar_default_toolbar_height">56dp</dimen>
+
+ <!-- DisplayToolbar -->
+ <dimen name="mozac_browser_toolbar_progress_bar_height">3dp</dimen>
+ <dimen name="mozac_browser_toolbar_icons_separator_height">24dp</dimen>
+ <dimen name="mozac_browser_toolbar_icons_separator_width">1dp</dimen>
+ <dimen name="mozac_browser_toolbar_page_action_separator_width">4dp</dimen>
+ <dimen name="mozac_browser_toolbar_url_fading_edge_size">24dp</dimen>
+ <dimen name="mozac_browser_toolbar_icon_padding">12dp</dimen>
+ <dimen name="mozac_browser_toolbar_icon_size">24dp</dimen>
+ <dimen name="mozac_browser_toolbar_menu_padding">16dp</dimen>
+ <dimen name="mozac_browser_toolbar_origin_padding_end">0dp</dimen>
+
+ <!-- EditToolbar -->
+ <dimen name="mozac_browser_toolbar_url_horizontal_padding">8dp</dimen>
+ <dimen name="mozac_browser_toolbar_url_vertical_padding">0dp</dimen>
+ <dimen name="mozac_browser_toolbar_url_gone_margin_end">8dp</dimen>
+ <dimen name="mozac_browser_toolbar_cancel_padding">16dp</dimen>
+
+ <dimen name="mozac_browser_toolbar_url_textsize">15sp</dimen>
+ <dimen name="mozac_browser_toolbar_title_textsize">15sp</dimen>
+ <dimen name="mozac_browser_toolbar_url_with_title_textsize">12sp</dimen>
+
+ <dimen name="mozac_browser_toolbar_pageaction_size">48dp</dimen>
+ <dimen name="mozac_browser_toolbar_browseraction_size">48dp</dimen>
+</resources>
diff --git a/mobile/android/android-components/components/browser/toolbar2/src/main/res/values/ids.xml b/mobile/android/android-components/components/browser/toolbar2/src/main/res/values/ids.xml
new file mode 100644
index 0000000000..20e28a0c58
--- /dev/null
+++ b/mobile/android/android-components/components/browser/toolbar2/src/main/res/values/ids.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- This Source Code Form is subject to the terms of the Mozilla Public
+ - License, v. 2.0. If a copy of the MPL was not distributed with this
+ - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
+<resources>
+ <item name="mozac_browser_toolbar_title_view" type="id"/>
+ <item name="mozac_browser_toolbar_url_view" type="id"/>
+</resources>
diff --git a/mobile/android/android-components/components/browser/toolbar2/src/main/res/values/strings.xml b/mobile/android/android-components/components/browser/toolbar2/src/main/res/values/strings.xml
new file mode 100644
index 0000000000..c845e189e7
--- /dev/null
+++ b/mobile/android/android-components/components/browser/toolbar2/src/main/res/values/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- This Source Code Form is subject to the terms of the Mozilla Public
+ - License, v. 2.0. If a copy of the MPL was not distributed with this
+ - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
+<resources>
+ <!-- Content description (not visible, for screen readers etc.): Description for the overflow menu button in the browser toolbar. -->
+ <string name="mozac_browser_toolbar_menu_button">Menu</string>
+ <!-- Content description: For the clear URL text button. -->
+ <string name="mozac_clear_button_description">Clear</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection enabled, but none trackers have been blocked or detected. -->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_on_no_trackers_blocked">Tracking Protection is on</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection enabled, and trackers have been blocked or detected.-->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_on_trackers_blocked1">Tracking Protection has blocked trackers</string>
+ <!-- Content description: For the tracking protection toolbar icon, it is set when the site has tracking protection disabled.-->
+ <string name="mozac_browser_toolbar_content_description_tracking_protection_off_for_a_site1">Tracking Protection is off for this site</string>
+ <!-- Content description: For the site security information icon (the site security icon).-->
+ <string name="mozac_browser_toolbar_content_description_site_info">Site information</string>
+ <!-- Announcement made by the screen reader when the progress bar is shown and a page is loading -->
+ <string name="mozac_browser_toolbar_progress_loading">Loading</string>
+ <!-- Content description: For the autoplay toolbar icon, it is set when the auto play permission is blocking content playing.-->
+ <string name="mozac_browser_toolbar_content_description_autoplay_blocked">Some content has been blocked by the autoplay setting</string>
+</resources>
diff --git a/mobile/android/android-components/components/browser/toolbar2/src/test/java/mozilla/components/browser/toolbar2/AsyncFilterListenerTest.kt b/mobile/android/android-components/components/browser/toolbar2/src/test/java/mozilla/components/browser/toolbar2/AsyncFilterListenerTest.kt
new file mode 100644
index 0000000000..6c95c8f243
--- /dev/null
+++ b/mobile/android/android-components/components/browser/toolbar2/src/test/java/mozilla/components/browser/toolbar2/AsyncFilterListenerTest.kt
@@ -0,0 +1,350 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.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.browser.toolbar2
+
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.asCoroutineDispatcher
+import kotlinx.coroutines.async
+import kotlinx.coroutines.cancelChildren
+import kotlinx.coroutines.isActive
+import kotlinx.coroutines.test.runTest
+import mozilla.components.concept.toolbar.AutocompleteDelegate
+import mozilla.components.concept.toolbar.AutocompleteResult
+import mozilla.components.support.test.mock
+import mozilla.components.ui.autocomplete.AutocompleteView
+import mozilla.components.ui.autocomplete.InlineAutocompleteEditText
+import org.junit.Assert.assertEquals
+import org.junit.Assert.fail
+import org.junit.Test
+import org.mockito.Mockito.atLeast
+import org.mockito.Mockito.atLeastOnce
+import org.mockito.Mockito.never
+import org.mockito.Mockito.spy
+import org.mockito.Mockito.verify
+import java.util.concurrent.Executor
+
+@ExperimentalCoroutinesApi // for runTest
+class AsyncFilterListenerTest {
+ @Test
+ fun `filter listener cancels prior filter executions`() = runTest {
+ val urlView: AutocompleteView = mock()
+ val filter: suspend (String, AutocompleteDelegate) -> Unit = mock()
+
+ val dispatcher = spy(
+ Executor {
+ it.run()
+ }.asCoroutineDispatcher(),
+ )
+
+ val listener = AsyncFilterListener(urlView, dispatcher, filter)
+
+ verify(dispatcher, never()).cancelChildren()
+
+ listener("test")
+
+ verify(dispatcher, atLeastOnce()).cancelChildren()
+ }
+
+ @Test
+ fun `filter delegate checks for cancellations before it runs, passes results to autocomplete view`() = runTest {
+ var filter: suspend (String, AutocompleteDelegate) -> Unit = { query, delegate ->
+ assertEquals("test", query)
+ delegate.applyAutocompleteResult(
+ AutocompleteResult(
+ input = "test",
+ text = "testing.com",
+ url = "http://www.testing.com",
+ source = "asyncTest",
+ totalItems = 1,
+ ),
+ )
+ }
+
+ val dispatcher = spy(
+ Executor {
+ it.run()
+ }.asCoroutineDispatcher(),
+ )
+
+ var didCallApply = 0
+
+ var listener = AsyncFilterListener(
+ object : AutocompleteView {
+ override val originalText: String = "test"
+
+ override fun applyAutocompleteResult(result: InlineAutocompleteEditText.AutocompleteResult) {
+ assertEquals("asyncTest", result.source)
+ assertEquals("testing.com", result.text)
+ assertEquals(1, result.totalItems)
+ didCallApply += 1
+ }
+
+ override fun noAutocompleteResult() {
+ fail()
+ }
+ },
+ dispatcher,
+ filter,
+ this.coroutineContext,
+ )
+
+ verify(dispatcher, never()).isActive
+
+ async { listener("test") }.await()
+
+ // Checked if parent scope is still active. Somehow, each access to 'isActive' registers as 4?
+ verify(dispatcher, atLeast(4)).isActive
+ // Passed the result to the view's apply method exactly once.
+ assertEquals(1, didCallApply)
+
+ filter = { query, delegate ->
+ assertEquals("moz", query)
+ delegate.applyAutocompleteResult(
+ AutocompleteResult(
+ input = "moz",
+ text = "mozilla.com",
+ url = "http://www.mozilla.com",
+ source = "asyncTestTwo",
+ totalItems = 2,
+ ),
+ )
+ }
+ listener = AsyncFilterListener(
+ object : AutocompleteView {
+ override val originalText: String = "moz"
+
+ override fun applyAutocompleteResult(result: InlineAutocompleteEditText.AutocompleteResult) {
+ assertEquals("asyncTestTwo", result.source)
+ assertEquals("mozilla.com", result.text)
+ assertEquals(2, result.totalItems)
+ didCallApply += 1
+ }
+
+ override fun noAutocompleteResult() {
+ fail()
+ }
+ },
+ dispatcher,
+ filter,
+ this.coroutineContext,
+ )
+
+ async { listener("moz") }.await()
+
+ verify(dispatcher, atLeast(8)).isActive
+ assertEquals(2, didCallApply)
+ }
+
+ @Test
+ fun `delegate discards stale results`() = runTest {
+ val filter: suspend (String, AutocompleteDelegate) -> Unit = { query, delegate ->
+ assertEquals("test", query)
+ delegate.applyAutocompleteResult(
+ AutocompleteResult(
+ input = "test",
+ text = "testing.com",
+ url = "http://www.testing.com",
+ source = "asyncTest",
+ totalItems = 1,
+ ),
+ )
+ }
+
+ val dispatcher = Executor {
+ it.run()
+ }.asCoroutineDispatcher()
+
+ val listener = AsyncFilterListener(
+ object : AutocompleteView {
+ override val originalText: String = "nolongertest"
+
+ override fun applyAutocompleteResult(result: InlineAutocompleteEditText.AutocompleteResult) {
+ fail()
+ }
+
+ override fun noAutocompleteResult() {
+ fail()
+ }
+ },
+ dispatcher,
+ filter,
+ this.coroutineContext,
+ )
+
+ listener("test")
+ }
+
+ @Test
+ fun `delegate discards stale lack of results`() = runTest {
+ val filter: suspend (String, AutocompleteDelegate) -> Unit = { query, delegate ->
+ assertEquals("test", query)
+ delegate.noAutocompleteResult("test")
+ }
+
+ val dispatcher = Executor {
+ it.run()
+ }.asCoroutineDispatcher()
+
+ val listener = AsyncFilterListener(
+ object : AutocompleteView {
+ override val originalText: String = "nolongertest"
+
+ override fun applyAutocompleteResult(result: InlineAutocompleteEditText.AutocompleteResult) {
+ fail()
+ }
+
+ override fun noAutocompleteResult() {
+ fail()
+ }
+ },
+ dispatcher,
+ filter,
+ this.coroutineContext,
+ )
+
+ listener("test")
+ }
+
+ @Test
+ fun `delegate passes through non-stale lack of results`() = runTest {
+ val filter: suspend (String, AutocompleteDelegate) -> Unit = { query, delegate ->
+ assertEquals("test", query)
+ delegate.noAutocompleteResult("test")
+ }
+
+ val dispatcher = Executor {
+ it.run()
+ }.asCoroutineDispatcher()
+
+ var calledNoResults = 0
+ val listener = AsyncFilterListener(
+ object : AutocompleteView {
+ override val originalText: String = "test"
+
+ override fun applyAutocompleteResult(result: InlineAutocompleteEditText.AutocompleteResult) {
+ fail()
+ }
+
+ override fun noAutocompleteResult() {
+ calledNoResults += 1
+ }
+ },
+ dispatcher,
+ filter,
+ this.coroutineContext,
+ )
+
+ async { listener("test") }.await()
+
+ assertEquals(1, calledNoResults)
+ }
+
+ @Test
+ fun `delegate discards results if parent scope was cancelled`() = runTest {
+ var preservedDelegate: AutocompleteDelegate? = null
+
+ val filter: suspend (String, AutocompleteDelegate) -> Unit = { query, delegate ->
+ preservedDelegate = delegate
+ assertEquals("test", query)
+ delegate.applyAutocompleteResult(
+ AutocompleteResult(
+ input = "test",
+ text = "testing.com",
+ url = "http://www.testing.com",
+ source = "asyncTest",
+ totalItems = 1,
+ ),
+ )
+ }
+
+ val dispatcher = Executor {
+ it.run()
+ }.asCoroutineDispatcher()
+
+ var calledResults = 0
+ val listener = AsyncFilterListener(
+ object : AutocompleteView {
+ override val originalText: String = "test"
+
+ override fun applyAutocompleteResult(result: InlineAutocompleteEditText.AutocompleteResult) {
+ assertEquals("asyncTest", result.source)
+ assertEquals("testing.com", result.text)
+ assertEquals(1, result.totalItems)
+ calledResults += 1
+ }
+
+ override fun noAutocompleteResult() {
+ fail()
+ }
+ },
+ dispatcher,
+ filter,
+ this.coroutineContext,
+ )
+
+ async {
+ listener("test")
+ listener("test")
+ }.await()
+
+ // This result application should be discarded, because scope has been cancelled by the second
+ // 'listener' call above.
+ preservedDelegate!!.applyAutocompleteResult(
+ AutocompleteResult(
+ input = "test",
+ text = "testing.com",
+ url = "http://www.testing.com",
+ source = "asyncCancelled",
+ totalItems = 1,
+ ),
+ )
+
+ assertEquals(2, calledResults)
+ }
+
+ @Test
+ fun `delegate discards lack of results if parent scope was cancelled`() = runTest {
+ var preservedDelegate: AutocompleteDelegate? = null
+
+ val filter: suspend (String, AutocompleteDelegate) -> Unit = { query, delegate ->
+ preservedDelegate = delegate
+ assertEquals("test", query)
+ delegate.noAutocompleteResult("test")
+ }
+
+ val dispatcher = Executor {
+ it.run()
+ }.asCoroutineDispatcher()
+
+ var calledResults = 0
+ val listener = AsyncFilterListener(
+ object : AutocompleteView {
+ override val originalText: String = "test"
+
+ override fun applyAutocompleteResult(result: InlineAutocompleteEditText.AutocompleteResult) {
+ fail()
+ }
+
+ override fun noAutocompleteResult() {
+ calledResults += 1
+ }
+ },
+ dispatcher,
+ filter,
+ this.coroutineContext,
+ )
+
+ async {
+ listener("test")
+ listener("test")
+ }.await()
+
+ // This "no results" call should be discarded, because scope has been cancelled by the second
+ // 'listener' call above.
+ preservedDelegate!!.noAutocompleteResult("test")
+
+ assertEquals(2, calledResults)
+ }
+}
diff --git a/mobile/android/android-components/components/browser/toolbar2/src/test/java/mozilla/components/browser/toolbar2/BrowserToolbarTest.kt b/mobile/android/android-components/components/browser/toolbar2/src/test/java/mozilla/components/browser/toolbar2/BrowserToolbarTest.kt
new file mode 100644
index 0000000000..d1a499e30c
--- /dev/null
+++ b/mobile/android/android-components/components/browser/toolbar2/src/test/java/mozilla/components/browser/toolbar2/BrowserToolbarTest.kt
@@ -0,0 +1,1044 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.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.browser.toolbar2
+
+import android.content.Context
+import android.graphics.drawable.Drawable
+import android.util.AttributeSet
+import android.view.View
+import android.view.ViewParent
+import android.view.accessibility.AccessibilityEvent
+import android.view.accessibility.AccessibilityManager
+import android.widget.ImageButton
+import androidx.coordinatorlayout.widget.CoordinatorLayout
+import androidx.core.view.inputmethod.EditorInfoCompat
+import androidx.core.view.isGone
+import androidx.core.view.isVisible
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import mozilla.components.browser.toolbar2.display.DisplayToolbar
+import mozilla.components.browser.toolbar2.display.DisplayToolbarViews
+import mozilla.components.browser.toolbar2.display.MenuButton
+import mozilla.components.browser.toolbar2.edit.EditToolbar
+import mozilla.components.concept.toolbar.AutocompleteDelegate
+import mozilla.components.concept.toolbar.Toolbar
+import mozilla.components.concept.toolbar.Toolbar.SiteSecurity
+import mozilla.components.concept.toolbar.Toolbar.SiteTrackingProtection
+import mozilla.components.support.ktx.kotlin.MAX_URI_LENGTH
+import mozilla.components.support.test.argumentCaptor
+import mozilla.components.support.test.mock
+import mozilla.components.support.test.robolectric.testContext
+import mozilla.components.support.test.whenever
+import mozilla.components.ui.widgets.behavior.EngineViewScrollingBehavior
+import mozilla.components.ui.widgets.behavior.ViewPosition
+import org.junit.Assert.assertEquals
+import org.junit.Assert.assertFalse
+import org.junit.Assert.assertNotEquals
+import org.junit.Assert.assertNotNull
+import org.junit.Assert.assertNull
+import org.junit.Assert.assertTrue
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.ArgumentCaptor
+import org.mockito.ArgumentMatchers
+import org.mockito.Mockito.any
+import org.mockito.Mockito.mock
+import org.mockito.Mockito.never
+import org.mockito.Mockito.spy
+import org.mockito.Mockito.times
+import org.mockito.Mockito.verify
+import org.mockito.Mockito.verifyNoMoreInteractions
+import org.mockito.Mockito.`when`
+import org.robolectric.Robolectric
+import org.robolectric.Shadows.shadowOf
+
+@RunWith(AndroidJUnit4::class)
+class BrowserToolbarTest {
+
+ @Test
+ fun `display toolbar is visible by default`() {
+ val toolbar = BrowserToolbar(testContext)
+ assertTrue(toolbar.display.rootView.visibility == View.VISIBLE)
+ assertTrue(toolbar.edit.rootView.visibility == View.GONE)
+ }
+
+ @Test
+ fun `calling editMode() makes edit toolbar visible`() {
+ val toolbar = BrowserToolbar(testContext)
+ assertTrue(toolbar.display.rootView.visibility == View.VISIBLE)
+ assertTrue(toolbar.edit.rootView.visibility == View.GONE)
+
+ toolbar.editMode()
+
+ assertTrue(toolbar.display.rootView.visibility == View.GONE)
+ assertTrue(toolbar.edit.rootView.visibility == View.VISIBLE)
+ }
+
+ @Test
+ fun `calling displayMode() makes display toolbar visible`() {
+ val toolbar = BrowserToolbar(testContext)
+ toolbar.editMode()
+
+ assertTrue(toolbar.display.rootView.visibility == View.GONE)
+ assertTrue(toolbar.edit.rootView.visibility == View.VISIBLE)
+
+ toolbar.displayMode()
+
+ assertTrue(toolbar.display.rootView.visibility == View.VISIBLE)
+ assertTrue(toolbar.edit.rootView.visibility == View.GONE)
+ }
+
+ @Test
+ fun `back presses will not be handled in display mode`() {
+ val toolbar = BrowserToolbar(testContext)
+ toolbar.displayMode()
+
+ assertFalse(toolbar.onBackPressed())
+
+ assertTrue(toolbar.display.rootView.visibility == View.VISIBLE)
+ assertTrue(toolbar.edit.rootView.visibility == View.GONE)
+ }
+
+ @Test
+ fun `back presses will switch from edit mode to display mode`() {
+ val toolbar = BrowserToolbar(testContext)
+ toolbar.editMode()
+
+ assertTrue(toolbar.display.rootView.visibility == View.GONE)
+ assertTrue(toolbar.edit.rootView.visibility == View.VISIBLE)
+
+ assertTrue(toolbar.onBackPressed())
+
+ assertTrue(toolbar.display.rootView.visibility == View.VISIBLE)
+ assertTrue(toolbar.edit.rootView.visibility == View.GONE)
+ }
+
+ @Test
+ fun `displayUrl will be forwarded to display toolbar immediately`() {
+ val toolbar = BrowserToolbar(testContext)
+ val display: DisplayToolbar = mock()
+ val edit: EditToolbar = mock()
+
+ toolbar.display = display
+ toolbar.edit = edit
+
+ toolbar.url = "https://www.mozilla.org"
+
+ verify(display).url = "https://www.mozilla.org"
+ verify(edit, never()).updateUrl(ArgumentMatchers.anyString(), ArgumentMatchers.anyBoolean(), ArgumentMatchers.anyBoolean(), ArgumentMatchers.anyBoolean())
+ }
+
+ @Test
+ fun `displayUrl is truncated to prevent extreme cases from slowing down the UI`() {
+ val toolbar = BrowserToolbar(testContext)
+ val display: DisplayToolbar = mock()
+ val edit: EditToolbar = mock()
+
+ toolbar.display = display
+ toolbar.edit = edit
+
+ toolbar.url = "a".repeat(MAX_URI_LENGTH + 1)
+ toolbar.url = "b".repeat(MAX_URI_LENGTH)
+ toolbar.url = "c".repeat(MAX_URI_LENGTH - 1)
+
+ val urlCaptor = argumentCaptor<String>()
+ verify(display, times(3)).url = urlCaptor.capture()
+
+ val capturedValues = urlCaptor.allValues
+ // Value was too long and should've been truncated
+ assertEquals("a".repeat(MAX_URI_LENGTH), capturedValues[0])
+ // Values should be the same as before
+ assertEquals("b".repeat(MAX_URI_LENGTH), capturedValues[1])
+ assertEquals("c".repeat(MAX_URI_LENGTH - 1), capturedValues[2])
+ }
+
+ @Test
+ fun `searchTerms is truncated in case it is greater than MAX_URI_LENGTH`() {
+ val toolbar = BrowserToolbar(testContext)
+ toolbar.edit = spy(toolbar.edit)
+ toolbar.editMode()
+
+ toolbar.setSearchTerms("a".repeat(MAX_URI_LENGTH + 1))
+
+ // Value was too long and should've been truncated
+ assertEquals(toolbar.searchTerms.length, MAX_URI_LENGTH)
+ verify(toolbar.edit).editSuggestion("a".repeat(MAX_URI_LENGTH))
+ }
+
+ @Test
+ fun `searchTerms is not truncated in case it is equal or less than MAX_URI_LENGTH`() {
+ val toolbar = BrowserToolbar(testContext)
+ toolbar.edit = spy(toolbar.edit)
+ toolbar.editMode()
+
+ toolbar.setSearchTerms("b".repeat(MAX_URI_LENGTH))
+
+ // Value should be the same as before
+ assertEquals(toolbar.searchTerms.length, MAX_URI_LENGTH)
+ verify(toolbar.edit).editSuggestion("b".repeat(MAX_URI_LENGTH))
+
+ toolbar.setSearchTerms("c".repeat(MAX_URI_LENGTH - 1))
+
+ // Value should be the same as before
+ assertEquals(toolbar.searchTerms.length, MAX_URI_LENGTH - 1)
+ verify(toolbar.edit).editSuggestion("c".repeat(MAX_URI_LENGTH - 1))
+ }
+
+ @Test
+ fun `last URL will be forwarded to edit toolbar when switching mode`() {
+ val toolbar = BrowserToolbar(testContext)
+ toolbar.edit = spy(toolbar.edit)
+
+ toolbar.url = "https://www.mozilla.org"
+ verify(toolbar.edit, never()).updateUrl("https://www.mozilla.org", false)
+
+ toolbar.editMode()
+
+ verify(toolbar.edit).updateUrl("https://www.mozilla.org", false)
+ }
+
+ @Test
+ fun `displayProgress will send accessibility events`() {
+ val toolbar = BrowserToolbar(testContext)
+ val root = mock(ViewParent::class.java)
+ shadowOf(toolbar).setMyParent(root)
+ `when`(root.requestSendAccessibilityEvent(any(), any())).thenReturn(false)
+
+ val shadowAccessibilityManager = shadowOf(testContext.getSystemService(Context.ACCESSIBILITY_SERVICE) as AccessibilityManager)
+ shadowAccessibilityManager.setEnabled(true)
+ shadowAccessibilityManager.setTouchExplorationEnabled(true)
+
+ toolbar.displayProgress(10)
+ toolbar.displayProgress(50)
+ toolbar.displayProgress(100)
+
+ // make sure multiple calls to 100% does not trigger "loading" announcement
+ toolbar.displayProgress(100)
+
+ val captor = ArgumentCaptor.forClass(AccessibilityEvent::class.java)
+
+ verify(root, times(5)).requestSendAccessibilityEvent(any(), captor.capture())
+
+ assertEquals(AccessibilityEvent.TYPE_ANNOUNCEMENT, captor.allValues[0].eventType)
+ assertEquals(testContext.getString(R.string.mozac_browser_toolbar_progress_loading), captor.allValues[0].text[0])
+
+ assertEquals(AccessibilityEvent.TYPE_VIEW_SCROLLED, captor.allValues[1].eventType)
+ assertEquals(10, captor.allValues[1].scrollY)
+ assertEquals(100, captor.allValues[1].maxScrollY)
+
+ assertEquals(AccessibilityEvent.TYPE_VIEW_SCROLLED, captor.allValues[2].eventType)
+ assertEquals(50, captor.allValues[2].scrollY)
+ assertEquals(100, captor.allValues[2].maxScrollY)
+
+ assertEquals(AccessibilityEvent.TYPE_VIEW_SCROLLED, captor.allValues[3].eventType)
+ assertEquals(100, captor.allValues[3].scrollY)
+ assertEquals(100, captor.allValues[3].maxScrollY)
+
+ assertEquals(AccessibilityEvent.TYPE_VIEW_SCROLLED, captor.allValues[4].eventType)
+ assertEquals(100, captor.allValues[3].scrollY)
+ assertEquals(100, captor.allValues[3].maxScrollY)
+ }
+
+ @Test
+ fun `displayProgress will not send send view scrolled accessibility events if touch exploration is disabled`() {
+ val toolbar = BrowserToolbar(testContext)
+ val root = mock(ViewParent::class.java)
+ shadowOf(toolbar).setMyParent(root)
+ `when`(root.requestSendAccessibilityEvent(any(), any())).thenReturn(false)
+
+ val shadowAccessibilityManager = shadowOf(testContext.getSystemService(Context.ACCESSIBILITY_SERVICE) as AccessibilityManager)
+ shadowAccessibilityManager.setEnabled(true)
+ shadowAccessibilityManager.setTouchExplorationEnabled(false)
+
+ toolbar.displayProgress(10)
+ toolbar.displayProgress(50)
+ toolbar.displayProgress(100)
+
+ // make sure multiple calls to 100% does not trigger "loading" announcement
+ toolbar.displayProgress(100)
+
+ val captor = ArgumentCaptor.forClass(AccessibilityEvent::class.java)
+
+ verify(root, times(1)).requestSendAccessibilityEvent(any(), captor.capture())
+
+ assertEquals(AccessibilityEvent.TYPE_ANNOUNCEMENT, captor.allValues[0].eventType)
+ assertEquals(testContext.getString(R.string.mozac_browser_toolbar_progress_loading), captor.allValues[0].text[0])
+ }
+
+ @Test
+ fun `displayProgress will be forwarded to display toolbar`() {
+ val toolbar = BrowserToolbar(testContext)
+ val display: DisplayToolbar = mock()
+
+ toolbar.display = display
+
+ toolbar.displayProgress(10)
+ toolbar.displayProgress(50)
+ toolbar.displayProgress(75)
+ toolbar.displayProgress(100)
+
+ verify(display).updateProgress(10)
+ verify(display).updateProgress(50)
+ verify(display).updateProgress(75)
+ verify(display).updateProgress(100)
+
+ verifyNoMoreInteractions(display)
+ }
+
+ @Test
+ fun `internal onUrlEntered callback will be forwarded to urlChangeListener`() {
+ val toolbar = BrowserToolbar(testContext)
+
+ val mockedListener = object {
+ var called = false
+ var url: String? = null
+
+ fun invoke(url: String): Boolean {
+ this.called = true
+ this.url = url
+ return true
+ }
+ }
+
+ toolbar.setOnUrlCommitListener(mockedListener::invoke)
+ toolbar.onUrlEntered("https://www.mozilla.org")
+
+ assertTrue(mockedListener.called)
+ assertEquals("https://www.mozilla.org", mockedListener.url)
+ }
+
+ /*
+ @Test
+ fun `internal onEditCancelled callback will be forwarded to editListener`() {
+ val toolbar = BrowserToolbar(testContext)
+ val listener: Toolbar.OnEditListener = mock()
+ toolbar.setOnEditListener(listener)
+ assertEquals(toolbar.edit.editListener, listener)
+
+ toolbar.edit.views.url.onKeyPreIme(
+ KeyEvent.KEYCODE_BACK,
+ KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_BACK)
+ )
+ verify(listener, times(1)).onCancelEditing()
+ }*/
+
+ @Test
+ fun `toolbar measure will use full width and fixed 56dp height`() {
+ val toolbar = BrowserToolbar(testContext)
+
+ val widthSpec = View.MeasureSpec.makeMeasureSpec(1024, View.MeasureSpec.AT_MOST)
+ val heightSpec = View.MeasureSpec.makeMeasureSpec(800, View.MeasureSpec.AT_MOST)
+
+ toolbar.measure(widthSpec, heightSpec)
+
+ assertEquals(1024, toolbar.measuredWidth)
+ assertEquals(56, toolbar.measuredHeight)
+ }
+
+ @Test
+ fun `toolbar will use provided height with EXACTLY measure spec`() {
+ val toolbar = BrowserToolbar(testContext)
+
+ val widthSpec = View.MeasureSpec.makeMeasureSpec(1024, View.MeasureSpec.AT_MOST)
+ val heightSpec = View.MeasureSpec.makeMeasureSpec(800, View.MeasureSpec.EXACTLY)
+
+ toolbar.measure(widthSpec, heightSpec)
+
+ assertEquals(1024, toolbar.measuredWidth)
+ assertEquals(800, toolbar.measuredHeight)
+ }
+
+ @Test
+ fun `display and edit toolbar will use full size of browser toolbar`() {
+ val toolbar = BrowserToolbar(testContext)
+
+ assertEquals(0, toolbar.display.rootView.measuredWidth)
+ assertEquals(0, toolbar.display.rootView.measuredHeight)
+ assertEquals(0, toolbar.edit.rootView.measuredWidth)
+ assertEquals(0, toolbar.edit.rootView.measuredHeight)
+
+ val widthSpec = View.MeasureSpec.makeMeasureSpec(1024, View.MeasureSpec.AT_MOST)
+ val heightSpec = View.MeasureSpec.makeMeasureSpec(800, View.MeasureSpec.AT_MOST)
+
+ toolbar.measure(widthSpec, heightSpec)
+
+ assertEquals(1024, toolbar.display.rootView.measuredWidth)
+ assertEquals(56, toolbar.display.rootView.measuredHeight)
+ assertEquals(1024, toolbar.edit.rootView.measuredWidth)
+ assertEquals(56, toolbar.edit.rootView.measuredHeight)
+ }
+
+ @Test
+ fun `toolbar will switch back to display mode after an URL has been entered`() {
+ val toolbar = BrowserToolbar(testContext)
+ toolbar.editMode()
+
+ assertTrue(toolbar.display.rootView.visibility == View.GONE)
+ assertTrue(toolbar.edit.rootView.visibility == View.VISIBLE)
+
+ toolbar.onUrlEntered("https://www.mozilla.org")
+
+ assertTrue(toolbar.display.rootView.visibility == View.VISIBLE)
+ assertTrue(toolbar.edit.rootView.visibility == View.GONE)
+ }
+
+ @Test
+ fun `toolbar will switch back to display mode if URL commit listener returns true`() {
+ val toolbar = BrowserToolbar(testContext)
+ toolbar.setOnUrlCommitListener { true }
+ toolbar.editMode()
+
+ assertTrue(toolbar.display.rootView.isGone)
+ assertTrue(toolbar.edit.rootView.isVisible)
+
+ toolbar.onUrlEntered("https://www.mozilla.org")
+
+ assertTrue(toolbar.display.rootView.isVisible)
+ assertTrue(toolbar.edit.rootView.isGone)
+ }
+
+ @Test
+ fun `toolbar will stay in edit mode if URL commit listener returns false`() {
+ val toolbar = BrowserToolbar(testContext)
+ toolbar.setOnUrlCommitListener { false }
+ toolbar.editMode()
+
+ assertTrue(toolbar.display.rootView.isGone)
+ assertTrue(toolbar.edit.rootView.isVisible)
+
+ toolbar.onUrlEntered("https://www.mozilla.org")
+
+ assertTrue(toolbar.display.rootView.isGone)
+ assertTrue(toolbar.edit.rootView.isVisible)
+ }
+
+ @Test
+ fun `add browser action will be forwarded to display toolbar`() {
+ val toolbar = BrowserToolbar(testContext)
+ val display: DisplayToolbar = mock()
+
+ toolbar.display = display
+
+ val action = BrowserToolbar.Button(mock(), "Hello") {
+ // Do nothing
+ }
+
+ toolbar.addBrowserAction(action)
+
+ verify(display).addBrowserAction(action)
+ }
+
+ @Test
+ fun `remove browser action will be forwarded to display toolbar`() {
+ val toolbar = BrowserToolbar(testContext)
+ val display: DisplayToolbar = mock()
+
+ toolbar.display = display
+
+ val action = BrowserToolbar.Button(mock(), "Hello") {
+ // Do nothing
+ }
+
+ toolbar.removeBrowserAction(action)
+
+ verify(display).removeBrowserAction(action)
+ }
+
+ @Test
+ fun `remove navigation action will be forwarded to display toolbar`() {
+ val toolbar = BrowserToolbar(testContext)
+ val display: DisplayToolbar = mock()
+
+ toolbar.display = display
+
+ val action = BrowserToolbar.Button(mock(), "Hello") {
+ // Do nothing
+ }
+
+ toolbar.removeNavigationAction(action)
+
+ verify(display).removeNavigationAction(action)
+ }
+
+ @Test
+ fun `remove page action will be forwarded to display toolbar`() {
+ val toolbar = BrowserToolbar(testContext)
+ val display: DisplayToolbar = mock()
+
+ toolbar.display = display
+
+ val action = BrowserToolbar.Button(mock(), "Hello") {
+ // Do nothing
+ }
+
+ toolbar.removePageAction(action)
+
+ verify(display).removePageAction(action)
+ }
+
+ @Test
+ fun `add page action will be forwarded to display toolbar`() {
+ val toolbar = BrowserToolbar(testContext)
+
+ val display: DisplayToolbar = mock()
+
+ toolbar.display = display
+
+ val action = BrowserToolbar.Button(mock(), "World") {
+ // Do nothing
+ }
+
+ toolbar.addPageAction(action)
+
+ verify(display).addPageAction(action)
+ }
+
+ @Test
+ fun `add edit action start will be forwarded to edit toolbar`() {
+ val toolbar = BrowserToolbar(testContext)
+
+ val edit: EditToolbar = mock()
+ toolbar.edit = edit
+
+ val action = BrowserToolbar.Button(mock(), "QR code scanner") {
+ // Do nothing
+ }
+
+ toolbar.addEditActionStart(action)
+
+ verify(edit).addEditActionStart(action)
+ }
+
+ @Test
+ fun `add edit action end will be forwarded to edit toolbar`() {
+ val toolbar = BrowserToolbar(testContext)
+
+ val edit: EditToolbar = mock()
+ toolbar.edit = edit
+
+ val action = BrowserToolbar.Button(mock(), "QR code scanner") {
+ // Do nothing
+ }
+
+ toolbar.addEditActionEnd(action)
+
+ verify(edit).addEditActionEnd(action)
+ }
+
+ @Test
+ fun `WHEN removing action end THEN it will be forwarded to the edit toolbar`() {
+ val toolbar = BrowserToolbar(testContext)
+
+ val edit: EditToolbar = mock()
+ toolbar.edit = edit
+
+ val action = BrowserToolbar.Button(mock(), "QR code scanner") {
+ // Do nothing
+ }
+
+ toolbar.removeEditActionEnd(action)
+
+ verify(edit).removeEditActionEnd(action)
+ }
+
+ @Test
+ fun `WHEN hideMenuButton is sent to BrowserToolbar THEN it will be forwarded to the DisplayToolbar`() {
+ val toolbar = BrowserToolbar(testContext)
+
+ val display: DisplayToolbar = mock()
+ toolbar.display = display
+
+ toolbar.hideMenuButton()
+
+ verify(display).hideMenuButton()
+ }
+
+ @Test
+ fun `WHEN showMenuButton is sent to BrowserToolbar THEN it will be forwarded to the DisplayToolbar`() {
+ val toolbar = BrowserToolbar(testContext)
+
+ val display: DisplayToolbar = mock()
+ toolbar.display = display
+
+ toolbar.showMenuButton()
+
+ verify(display).showMenuButton()
+ }
+
+ @Test
+ fun `WHEN showPageActionSeparator is sent to BrowserToolbar THEN it will be forwarded to the DisplayToolbar and EditToolbar`() {
+ val toolbar = BrowserToolbar(testContext)
+
+ val display: DisplayToolbar = mock()
+ val edit: EditToolbar = mock()
+ toolbar.display = display
+ toolbar.edit = edit
+
+ toolbar.showPageActionSeparator()
+
+ verify(display).showPageActionSeparator()
+ verify(edit).showPageActionSeparator()
+ }
+
+ @Test
+ fun `WHEN hidePageActionSeparator is sent to BrowserToolbar THEN it will be forwarded to the DisplayToolbar and EditToolbar`() {
+ val toolbar = BrowserToolbar(testContext)
+
+ val display: DisplayToolbar = mock()
+ val edit: EditToolbar = mock()
+ toolbar.display = display
+ toolbar.edit = edit
+
+ toolbar.hidePageActionSeparator()
+
+ verify(display).hidePageActionSeparator()
+ verify(edit).hidePageActionSeparator()
+ }
+
+ @Test
+ fun `WHEN setDisplayHorizontalPadding is sent to BrowserToolbar THEN it will be forwarded to the DisplayToolbar`() {
+ val toolbar = BrowserToolbar(testContext)
+
+ val display: DisplayToolbar = mock()
+ toolbar.display = display
+ toolbar.edit = mock()
+
+ toolbar.setDisplayHorizontalPadding(123)
+ verify(display).setHorizontalPadding(123)
+
+ toolbar.setDisplayHorizontalPadding(0)
+ verify(display).setHorizontalPadding(0)
+ }
+
+ @Test
+ fun `cast to view`() {
+ // Given
+ val toolbar = BrowserToolbar(testContext)
+
+ // When
+ val view = toolbar.asView()
+
+ // Then
+ assertNotNull(view)
+ }
+
+ @Test
+ fun `URL update does not override search terms in edit mode`() {
+ val toolbar = BrowserToolbar(testContext)
+
+ toolbar.display = spy(toolbar.display)
+ toolbar.edit = spy(toolbar.edit)
+
+ toolbar.setSearchTerms("mozilla android")
+ toolbar.url = "https://www.mozilla.com"
+ toolbar.editMode()
+ verify(toolbar.display).url = "https://www.mozilla.com"
+ verify(toolbar.edit).updateUrl("mozilla android", false)
+
+ toolbar.setSearchTerms("")
+ verify(toolbar.edit).updateUrl("", false)
+
+ toolbar.url = "https://www.mozilla.org"
+ toolbar.editMode()
+ verify(toolbar.display).url = "https://www.mozilla.org"
+ verify(toolbar.edit).updateUrl("https://www.mozilla.org", false)
+ }
+
+ @Test
+ fun `add navigation action will be forwarded to display toolbar`() {
+ val toolbar = BrowserToolbar(testContext)
+ val display: DisplayToolbar = mock()
+ toolbar.display = display
+
+ val action = BrowserToolbar.Button(mock(), "Back") {
+ // Do nothing
+ }
+
+ toolbar.addNavigationAction(action)
+
+ verify(display).addNavigationAction(action)
+ }
+
+ @Test
+ fun `invalidate actions is forwarded to display toolbar`() {
+ val toolbar = BrowserToolbar(testContext)
+ val display: DisplayToolbar = mock()
+ toolbar.display = display
+
+ verify(display, never()).invalidateActions()
+
+ toolbar.invalidateActions()
+
+ verify(display).invalidateActions()
+ }
+
+ @Test
+ fun `invalidate actions is forwarded to edit toolbar`() {
+ val toolbar = BrowserToolbar(testContext)
+ val edit: EditToolbar = mock()
+ toolbar.edit = edit
+
+ verify(edit, never()).invalidateActions()
+
+ toolbar.invalidateActions()
+
+ verify(edit).invalidateActions()
+ }
+
+ @Test
+ fun `search terms (if set) are forwarded to edit toolbar instead of URL`() {
+ val toolbar = BrowserToolbar(testContext)
+
+ toolbar.edit = spy(toolbar.edit)
+
+ toolbar.url = "https://www.mozilla.org"
+ toolbar.setSearchTerms("Mozilla Firefox")
+
+ verify(toolbar.edit, never()).updateUrl("https://www.mozilla.org")
+ verify(toolbar.edit, never()).updateUrl("Mozilla Firefox")
+
+ toolbar.editMode()
+
+ verify(toolbar.edit, never()).updateUrl("https://www.mozilla.org")
+ verify(toolbar.edit).updateUrl("Mozilla Firefox")
+ }
+
+ @Test
+ fun `search terms are forwarded to edit toolbar when it is active`() {
+ val toolbar = BrowserToolbar(testContext)
+
+ toolbar.edit = spy(toolbar.edit)
+
+ toolbar.editMode()
+
+ toolbar.setSearchTerms("Mozilla Firefox")
+
+ verify(toolbar.edit).editSuggestion("Mozilla Firefox")
+ }
+
+ @Test
+ fun `editListener is set on edit`() {
+ val toolbar = BrowserToolbar(testContext)
+ assertNull(toolbar.edit.editListener)
+
+ val listener: Toolbar.OnEditListener = mock()
+ toolbar.setOnEditListener(listener)
+
+ assertEquals(listener, toolbar.edit.editListener)
+ }
+
+ @Test
+ fun `editListener is invoked when switching between modes`() {
+ val toolbar = BrowserToolbar(testContext)
+
+ val listener: Toolbar.OnEditListener = mock()
+ toolbar.setOnEditListener(listener)
+
+ toolbar.editMode()
+
+ verify(listener).onStartEditing()
+ verifyNoMoreInteractions(listener)
+
+ toolbar.displayMode()
+
+ verify(listener).onStopEditing()
+ verifyNoMoreInteractions(listener)
+ }
+
+ @Test
+ fun `editListener is invoked when text changes`() {
+ val toolbar = BrowserToolbar(testContext)
+
+ val listener: Toolbar.OnEditListener = mock()
+ toolbar.setOnEditListener(listener)
+
+ toolbar.edit.views.url.onAttachedToWindow()
+
+ toolbar.editMode()
+
+ toolbar.edit.views.url.setText("Hello")
+ toolbar.edit.views.url.setText("Hello World")
+
+ verify(listener).onStartEditing()
+ verify(listener).onTextChanged("Hello")
+ verify(listener).onTextChanged("Hello World")
+ }
+
+ @Test
+ fun `titleView visibility is based on being set`() {
+ val toolbar = BrowserToolbar(testContext)
+
+ assertEquals(toolbar.display.views.origin.titleView.visibility, View.GONE)
+ toolbar.title = "Mozilla"
+ assertEquals(toolbar.display.views.origin.titleView.visibility, View.VISIBLE)
+ toolbar.title = ""
+ assertEquals(toolbar.display.views.origin.titleView.visibility, View.GONE)
+ }
+
+ @Test
+ fun `titleView text is set properly`() {
+ val toolbar = BrowserToolbar(testContext)
+
+ toolbar.title = "Mozilla"
+ assertEquals("Mozilla", toolbar.display.views.origin.titleView.text)
+ assertEquals("Mozilla", toolbar.title)
+ }
+
+ @Test
+ fun `titleView fading is set properly with non-null attrs`() {
+ val attributeSet: AttributeSet = Robolectric.buildAttributeSet().build()
+
+ val toolbar = BrowserToolbar(testContext, attributeSet)
+ val titleView = toolbar.display.views.origin.titleView
+ val edgeLength = testContext.resources.getDimensionPixelSize(R.dimen.mozac_browser_toolbar_url_fading_edge_size)
+
+ assertTrue(titleView.isHorizontalFadingEdgeEnabled)
+ assertEquals(edgeLength, titleView.horizontalFadingEdgeLength)
+ }
+
+ @Test
+ fun `Button constructor with drawable`() {
+ val buttonDefault = BrowserToolbar.Button(mock(), "imageDrawable") {}
+
+ assertEquals(true, buttonDefault.visible())
+ assertEquals(BrowserToolbar.DEFAULT_PADDING, buttonDefault.padding)
+ assertEquals("imageDrawable", buttonDefault.contentDescription)
+
+ val button = BrowserToolbar.Button(mock(), "imageDrawable", visible = { false }) {}
+
+ assertEquals(false, button.visible())
+ }
+
+ @Test
+ fun `ToggleButton constructor with drawable`() {
+ val buttonDefault =
+ BrowserToolbar.ToggleButton(mock(), mock(), "imageDrawable", "imageSelectedDrawable") {}
+
+ assertEquals(true, buttonDefault.visible())
+ assertEquals(BrowserToolbar.DEFAULT_PADDING, buttonDefault.padding)
+
+ val button = BrowserToolbar.ToggleButton(
+ mock(),
+ mock(),
+ "imageDrawable",
+ "imageSelectedDrawable",
+ visible = { false },
+ ) {}
+
+ assertEquals(false, button.visible())
+ }
+
+ @Test
+ fun `ReloadPageAction visibility changes update image`() {
+ val reloadImage: Drawable = mock()
+ val stopImage: Drawable = mock()
+ val view: ImageButton = mock()
+ var reloadPageAction = BrowserToolbar.TwoStateButton(reloadImage, "reload", stopImage, "stop") {}
+ assertFalse(reloadPageAction.enabled)
+ reloadPageAction.bind(view)
+ verify(view).setImageDrawable(reloadImage)
+ verify(view).contentDescription = "reload"
+
+ reloadPageAction = BrowserToolbar.TwoStateButton(reloadImage, "reload", stopImage, "stop", { false }) {}
+ reloadPageAction.bind(view)
+ verify(view).setImageDrawable(stopImage)
+ verify(view).contentDescription = "stop"
+ }
+
+ @Test
+ fun `siteSecure updates the display`() {
+ val toolbar = BrowserToolbar(testContext)
+ toolbar.display = spy(toolbar.display)
+ assertEquals(SiteSecurity.INSECURE, toolbar.siteSecure)
+
+ toolbar.siteSecure = SiteSecurity.SECURE
+
+ verify(toolbar.display).siteSecurity = SiteSecurity.SECURE
+ }
+
+ @Test
+ fun `siteTrackingProtection updates the display`() {
+ val toolbar = BrowserToolbar(testContext)
+ toolbar.display = spy(toolbar.display)
+ assertEquals(SiteTrackingProtection.OFF_GLOBALLY, toolbar.siteTrackingProtection)
+
+ toolbar.siteTrackingProtection = SiteTrackingProtection.ON_NO_TRACKERS_BLOCKED
+
+ verify(toolbar.display).setTrackingProtectionState(SiteTrackingProtection.ON_NO_TRACKERS_BLOCKED)
+
+ toolbar.siteTrackingProtection = SiteTrackingProtection.ON_NO_TRACKERS_BLOCKED
+ verifyNoMoreInteractions(toolbar.display)
+ }
+
+ @Test
+ fun `private flag sets IME_FLAG_NO_PERSONALIZED_LEARNING on url edit view`() {
+ val toolbar = BrowserToolbar(testContext)
+ val edit = toolbar.edit
+
+ // By default "private mode" is off.
+ assertEquals(
+ 0,
+ edit.views.url.imeOptions and
+ EditorInfoCompat.IME_FLAG_NO_PERSONALIZED_LEARNING,
+ )
+ assertEquals(false, toolbar.private)
+
+ // Turning on private mode sets flag
+ toolbar.private = true
+ assertNotEquals(
+ 0,
+ edit.views.url.imeOptions and
+ EditorInfoCompat.IME_FLAG_NO_PERSONALIZED_LEARNING,
+ )
+ assertTrue(toolbar.private)
+
+ // Turning private mode off again - should remove flag
+ toolbar.private = false
+ assertEquals(
+ 0,
+ edit.views.url.imeOptions and
+ EditorInfoCompat.IME_FLAG_NO_PERSONALIZED_LEARNING,
+ )
+ assertEquals(false, toolbar.private)
+ }
+
+ @Test
+ fun `setAutocompleteListener is forwarded to edit toolbar`() {
+ val toolbar = BrowserToolbar(testContext)
+ toolbar.edit = mock()
+
+ val filter: suspend (String, AutocompleteDelegate) -> Unit = { _, _ ->
+ // Do nothing
+ }
+
+ toolbar.setAutocompleteListener(filter)
+
+ verify(toolbar.edit).setAutocompleteListener(filter)
+ }
+
+ @Test
+ fun `WHEN an attempt to refresh autocomplete suggestions is made THEN forward the call to edit toolbar`() {
+ val toolbar = BrowserToolbar(testContext)
+ toolbar.edit = mock()
+ toolbar.setAutocompleteListener { _, _ -> }
+
+ toolbar.refreshAutocomplete()
+
+ verify(toolbar.edit).refreshAutocompleteSuggestion()
+ }
+
+ @Test
+ fun `onStop is forwarded to display toolbar`() {
+ val toolbar = BrowserToolbar(testContext)
+ toolbar.display = mock()
+
+ toolbar.onStop()
+
+ verify(toolbar.display).onStop()
+ }
+
+ @Test
+ fun `dismiss menu is forwarded to display toolbar`() {
+ val toolbar = BrowserToolbar(testContext)
+ toolbar.display = mock()
+ val displayToolbarViews: DisplayToolbarViews = mock()
+ val menuButton: MenuButton = mock()
+
+ whenever(toolbar.display.views).thenReturn(displayToolbarViews)
+ whenever(displayToolbarViews.menu).thenReturn(menuButton)
+
+ toolbar.dismissMenu()
+ verify(menuButton).dismissMenu()
+ }
+
+ @Test
+ fun `enable scrolling is forwarded to the toolbar behavior`() {
+ // Seems like real instances are needed for things to be set properly
+ val toolbar = BrowserToolbar(testContext)
+ val behavior = spy(EngineViewScrollingBehavior(testContext, null, ViewPosition.BOTTOM))
+ val params = CoordinatorLayout.LayoutParams(10, 10).apply {
+ this.behavior = behavior
+ }
+ toolbar.layoutParams = params
+
+ toolbar.enableScrolling()
+
+ verify(behavior).enableScrolling()
+ }
+
+ @Test
+ fun `disable scrolling is forwarded to the toolbar behavior`() {
+ // Seems like real instances are needed for things to be set properly
+ val toolbar = BrowserToolbar(testContext)
+ val behavior = spy(EngineViewScrollingBehavior(testContext, null, ViewPosition.BOTTOM))
+ val params = CoordinatorLayout.LayoutParams(10, 10).apply {
+ this.behavior = behavior
+ }
+ toolbar.layoutParams = params
+
+ toolbar.disableScrolling()
+
+ verify(behavior).disableScrolling()
+ }
+
+ @Test
+ fun `expand is forwarded to the toolbar behavior`() {
+ // Seems like real instances are needed for things to be set properly
+ val toolbar = BrowserToolbar(testContext)
+ val behavior = spy(EngineViewScrollingBehavior(testContext, null, ViewPosition.BOTTOM))
+ val params = CoordinatorLayout.LayoutParams(10, 10).apply {
+ this.behavior = behavior
+ }
+ toolbar.layoutParams = params
+
+ toolbar.expand()
+
+ verify(behavior).forceExpand(toolbar)
+ }
+
+ @Test
+ fun `collapse is forwarded to the toolbar behavior`() {
+ // Seems like real instances are needed for things to be set properly
+ val toolbar = BrowserToolbar(testContext)
+ val behavior = spy(EngineViewScrollingBehavior(testContext, null, ViewPosition.BOTTOM))
+ val params = CoordinatorLayout.LayoutParams(10, 10).apply {
+ this.behavior = behavior
+ }
+ toolbar.layoutParams = params
+
+ toolbar.collapse()
+
+ verify(behavior).forceCollapse(toolbar)
+ }
+
+ @Test
+ fun `WHEN search terms changes THEN edit listener is notified`() {
+ val toolbar = BrowserToolbar(testContext)
+ toolbar.edit = spy(toolbar.edit)
+ toolbar.edit.editListener = mock()
+
+ toolbar.setSearchTerms("")
+ toolbar.editMode()
+
+ toolbar.setSearchTerms("test")
+ verify(toolbar.edit.editListener)?.onTextChanged("test")
+
+ toolbar.setSearchTerms("")
+ verify(toolbar.edit.editListener)?.onTextChanged("")
+ }
+
+ @Test
+ fun `WHEN switching to edit mode AND the cursor placement parameter is specified THEN call the correct method to place the cursor`() {
+ val toolbar = BrowserToolbar(testContext)
+ toolbar.edit = spy(toolbar.edit)
+
+ toolbar.editMode(Toolbar.CursorPlacement.ALL)
+
+ verify(toolbar.edit).selectAll()
+
+ toolbar.editMode(Toolbar.CursorPlacement.END)
+
+ verify(toolbar.edit).selectEnd()
+ }
+}
diff --git a/mobile/android/android-components/components/browser/toolbar2/src/test/java/mozilla/components/browser/toolbar2/display/DisplayToolbarTest.kt b/mobile/android/android-components/components/browser/toolbar2/src/test/java/mozilla/components/browser/toolbar2/display/DisplayToolbarTest.kt
new file mode 100644
index 0000000000..6a8ba9e478
--- /dev/null
+++ b/mobile/android/android-components/components/browser/toolbar2/src/test/java/mozilla/components/browser/toolbar2/display/DisplayToolbarTest.kt
@@ -0,0 +1,824 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.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.browser.toolbar2.display
+
+import android.graphics.Color
+import android.os.Build
+import android.view.View
+import androidx.core.content.ContextCompat
+import androidx.core.view.isGone
+import androidx.core.view.isVisible
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import mozilla.components.browser.menu.BrowserMenu
+import mozilla.components.browser.menu.BrowserMenuBuilder
+import mozilla.components.browser.menu.item.SimpleBrowserMenuItem
+import mozilla.components.browser.toolbar2.BrowserToolbar
+import mozilla.components.browser.toolbar2.R
+import mozilla.components.concept.menu.MenuButton
+import mozilla.components.concept.toolbar.Toolbar
+import mozilla.components.concept.toolbar.Toolbar.SiteSecurity
+import mozilla.components.concept.toolbar.Toolbar.SiteTrackingProtection
+import mozilla.components.support.base.Component
+import mozilla.components.support.base.facts.Action
+import mozilla.components.support.base.facts.processor.CollectionProcessor
+import mozilla.components.support.test.any
+import mozilla.components.support.test.eq
+import mozilla.components.support.test.mock
+import mozilla.components.support.test.robolectric.testContext
+import org.junit.Assert.assertEquals
+import org.junit.Assert.assertFalse
+import org.junit.Assert.assertNotEquals
+import org.junit.Assert.assertNotNull
+import org.junit.Assert.assertNull
+import org.junit.Assert.assertTrue
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.ArgumentMatchers.anyBoolean
+import org.mockito.Mockito.doReturn
+import org.mockito.Mockito.mock
+import org.mockito.Mockito.never
+import org.mockito.Mockito.reset
+import org.mockito.Mockito.spy
+import org.mockito.Mockito.verify
+import org.robolectric.util.ReflectionHelpers
+import mozilla.components.ui.icons.R as iconsR
+
+@RunWith(AndroidJUnit4::class)
+class DisplayToolbarTest {
+ private fun createDisplayToolbar(): Pair<BrowserToolbar, DisplayToolbar> {
+ val toolbar: BrowserToolbar = mock()
+ val displayToolbar = DisplayToolbar(
+ testContext,
+ toolbar,
+ View.inflate(testContext, R.layout.mozac_browser_toolbar_displaytoolbar, null),
+ )
+ return Pair(toolbar, displayToolbar)
+ }
+
+ @Test
+ fun `clicking on the URL switches the toolbar to editing mode`() {
+ val (toolbar, displayToolbar) = createDisplayToolbar()
+
+ val urlView = displayToolbar.views.origin.urlView
+ assertTrue(urlView.performClick())
+
+ verify(toolbar).editMode()
+ }
+
+ @Test
+ fun `progress is forwarded to progress bar`() {
+ val (_, displayToolbar) = createDisplayToolbar()
+
+ val progressView = displayToolbar.views.progress
+
+ displayToolbar.updateProgress(0)
+ assertEquals(0, progressView.progress)
+ assertEquals(View.GONE, progressView.visibility)
+
+ displayToolbar.updateProgress(10)
+ assertEquals(10, progressView.progress)
+ assertEquals(View.VISIBLE, progressView.visibility)
+
+ displayToolbar.updateProgress(50)
+ assertEquals(50, progressView.progress)
+ assertEquals(View.VISIBLE, progressView.visibility)
+
+ displayToolbar.updateProgress(75)
+ assertEquals(75, progressView.progress)
+ assertEquals(View.VISIBLE, progressView.visibility)
+
+ displayToolbar.updateProgress(100)
+ assertEquals(100, progressView.progress)
+ assertEquals(View.GONE, progressView.visibility)
+ }
+
+ @Test
+ fun `trackingProtectionViewColor will change the color of the trackingProtectionIconView`() {
+ val (_, displayToolbar) = createDisplayToolbar()
+
+ assertNull(displayToolbar.views.trackingProtectionIndicator.colorFilter)
+
+ displayToolbar.colors = displayToolbar.colors.copy(
+ trackingProtection = Color.BLUE,
+ )
+
+ assertNotNull(displayToolbar.views.trackingProtectionIndicator.colorFilter)
+ assertNotNull(displayToolbar.views.trackingProtectionIndicator.trackingProtectionTint)
+ }
+
+ @Test
+ fun `highlightView will change the color of the dot`() {
+ val (_, displayToolbar) = createDisplayToolbar()
+
+ assertNull(displayToolbar.views.highlight.colorFilter)
+
+ displayToolbar.colors = displayToolbar.colors.copy(highlight = Color.BLUE)
+
+ assertNotNull(displayToolbar.views.highlight.colorFilter)
+ assertNotNull(displayToolbar.views.highlight.highlightTint)
+ }
+
+ @Test
+ fun `tracking protection and separator views become visible when states ON OR ACTIVE are set to siteTrackingProtection`() {
+ val (_, displayToolbar) = createDisplayToolbar()
+
+ val trackingView = displayToolbar.views.trackingProtectionIndicator
+ val separatorView = displayToolbar.views.separator
+
+ assertTrue(trackingView.visibility == View.GONE)
+ assertTrue(separatorView.visibility == View.GONE)
+
+ displayToolbar.indicators = listOf(
+ DisplayToolbar.Indicators.SECURITY,
+ DisplayToolbar.Indicators.TRACKING_PROTECTION,
+ )
+ displayToolbar.url = "https://www.mozilla.org"
+ displayToolbar.displayIndicatorSeparator = true
+ displayToolbar.setTrackingProtectionState(SiteTrackingProtection.ON_NO_TRACKERS_BLOCKED)
+
+ assertTrue(trackingView.isVisible)
+ assertTrue(separatorView.isVisible)
+
+ displayToolbar.setTrackingProtectionState(SiteTrackingProtection.OFF_GLOBALLY)
+
+ assertTrue(trackingView.visibility == View.GONE)
+ assertTrue(separatorView.visibility == View.GONE)
+
+ displayToolbar.setTrackingProtectionState(SiteTrackingProtection.ON_TRACKERS_BLOCKED)
+
+ assertTrue(trackingView.isVisible)
+ assertTrue(separatorView.isVisible)
+ }
+
+ @Test
+ fun `setTrackingProtectionIcons will forward to TrackingProtectionIconView`() {
+ val (_, displayToolbar) = createDisplayToolbar()
+
+ displayToolbar.indicators = listOf(DisplayToolbar.Indicators.TRACKING_PROTECTION)
+ displayToolbar.setTrackingProtectionState(SiteTrackingProtection.ON_NO_TRACKERS_BLOCKED)
+
+ val oldTrackingProtectionIcon = displayToolbar.views.trackingProtectionIndicator.drawable
+ assertNotNull(oldTrackingProtectionIcon)
+
+ val drawable1 =
+ testContext.getDrawable(TrackingProtectionIconView.DEFAULT_ICON_ON_NO_TRACKERS_BLOCKED)!!
+ val drawable2 =
+ testContext.getDrawable(TrackingProtectionIconView.DEFAULT_ICON_ON_TRACKERS_BLOCKED)!!
+ val drawable3 =
+ testContext.getDrawable(TrackingProtectionIconView.DEFAULT_ICON_OFF_FOR_A_SITE)!!
+
+ displayToolbar.icons = displayToolbar.icons.copy(
+ trackingProtectionTrackersBlocked = drawable1,
+ trackingProtectionNothingBlocked = drawable2,
+ trackingProtectionException = drawable3,
+ )
+
+ assertNotEquals(
+ oldTrackingProtectionIcon,
+ displayToolbar.views.trackingProtectionIndicator.drawable,
+ )
+
+ assertEquals(drawable2, displayToolbar.views.trackingProtectionIndicator.drawable)
+
+ displayToolbar.setTrackingProtectionState(SiteTrackingProtection.ON_TRACKERS_BLOCKED)
+
+ assertNotEquals(
+ oldTrackingProtectionIcon,
+ displayToolbar.views.trackingProtectionIndicator.drawable,
+ )
+
+ assertEquals(
+ drawable1,
+ displayToolbar.views.trackingProtectionIndicator.drawable,
+ )
+ }
+
+ @Test
+ fun `setHighlight will forward to HighlightView`() {
+ val (_, displayToolbar) = createDisplayToolbar()
+
+ val oldPermissionIcon = displayToolbar.views.highlight.drawable
+ assertNotNull(oldPermissionIcon)
+
+ val drawable1 = testContext.getDrawable(HighlightView.DEFAULT_ICON)!!
+
+ displayToolbar.indicators = listOf(DisplayToolbar.Indicators.HIGHLIGHT)
+ displayToolbar.icons = displayToolbar.icons.copy(
+ highlight = drawable1,
+ )
+
+ assertNotEquals(
+ oldPermissionIcon,
+ displayToolbar.views.highlight.drawable,
+ )
+
+ displayToolbar.setHighlight(Toolbar.Highlight.PERMISSIONS_CHANGED)
+
+ assertNotEquals(
+ oldPermissionIcon,
+ displayToolbar.views.highlight.drawable,
+ )
+ }
+
+ @Test
+ fun `menu view is gone by default`() {
+ val (_, displayToolbar) = createDisplayToolbar()
+
+ val menuView = displayToolbar.views.menu
+
+ assertNotNull(menuView)
+ assertEquals(View.GONE, menuView.impl.visibility)
+ }
+
+ @Test
+ fun `menu view becomes visible once a menu builder is set`() {
+ val (_, displayToolbar) = createDisplayToolbar()
+
+ val menuView = displayToolbar.views.menu
+
+ assertNotNull(menuView)
+
+ assertEquals(View.GONE, menuView.impl.visibility)
+
+ displayToolbar.menuBuilder = BrowserMenuBuilder(emptyList())
+
+ assertEquals(View.VISIBLE, menuView.impl.visibility)
+
+ displayToolbar.menuBuilder = null
+
+ assertEquals(View.GONE, menuView.impl.visibility)
+ }
+
+ @Test
+ fun `no menu builder is set by default`() {
+ val (_, displayToolbar) = createDisplayToolbar()
+
+ assertNull(displayToolbar.menuBuilder)
+ }
+
+ @Test
+ fun `menu builder will be used to create and show menu when button is clicked`() {
+ val (_, displayToolbar) = createDisplayToolbar()
+ val menuView = displayToolbar.views.menu
+
+ val menuBuilder = mock(BrowserMenuBuilder::class.java)
+ val menu = mock(BrowserMenu::class.java)
+ doReturn(menu).`when`(menuBuilder).build(testContext)
+
+ displayToolbar.menuBuilder = menuBuilder
+
+ verify(menuBuilder, never()).build(testContext)
+ verify(menu, never()).show(menuView.impl)
+
+ menuView.impl.performClick()
+
+ verify(menuBuilder).build(testContext)
+ verify(menu).show(eq(menuView.impl), any(), any(), anyBoolean(), any())
+ verify(menu, never()).invalidate()
+
+ displayToolbar.invalidateActions()
+
+ verify(menu).invalidate()
+ }
+
+ @Test
+ fun `browser action gets added as view to toolbar`() {
+ val contentDescription = "Mozilla"
+
+ val (_, displayToolbar) = createDisplayToolbar()
+
+ assertEquals(0, displayToolbar.views.browserActions.childCount)
+
+ val action = BrowserToolbar.Button(mock(), contentDescription) {}
+ displayToolbar.addBrowserAction(action)
+
+ assertEquals(1, displayToolbar.views.browserActions.childCount)
+
+ val view = displayToolbar.views.browserActions.getChildAt(0)
+ assertEquals(contentDescription, view.contentDescription)
+ }
+
+ @Test
+ fun `clicking browser action view triggers listener of action`() {
+ var callbackExecuted = false
+
+ val action = BrowserToolbar.Button(mock(), "Button") {
+ callbackExecuted = true
+ }
+
+ val (_, displayToolbar) = createDisplayToolbar()
+ displayToolbar.addBrowserAction(action)
+
+ assertEquals(1, displayToolbar.views.browserActions.childCount)
+ val view = displayToolbar.views.browserActions.getChildAt(0)
+
+ assertNotNull(view)
+
+ assertFalse(callbackExecuted)
+
+ view?.performClick()
+
+ assertTrue(callbackExecuted)
+ }
+
+ @Test
+ fun `browser action can be removed`() {
+ val contentDescription = "to-be-removed"
+
+ val (_, displayToolbar) = createDisplayToolbar()
+
+ val action = BrowserToolbar.Button(mock(), contentDescription) {}
+ // Removing action which was never added has no effect
+ displayToolbar.removeBrowserAction(action)
+
+ displayToolbar.addBrowserAction(action)
+ assertEquals(1, displayToolbar.views.browserActions.childCount)
+
+ displayToolbar.removeBrowserAction(action)
+ assertEquals(0, displayToolbar.views.browserActions.childCount)
+ }
+
+ @Test
+ fun `navigation action can be removed`() {
+ val contentDescription = "to-be-removed"
+
+ val (_, displayToolbar) = createDisplayToolbar()
+
+ val action = BrowserToolbar.Button(mock(), contentDescription) {}
+ // Removing action which was never added has no effect
+ displayToolbar.removeNavigationAction(action)
+
+ displayToolbar.addNavigationAction(action)
+ assertEquals(1, displayToolbar.views.navigationActions.childCount)
+
+ displayToolbar.removeNavigationAction(action)
+ assertEquals(0, displayToolbar.views.navigationActions.childCount)
+ }
+
+ @Test
+ fun `page action can be removed`() {
+ val contentDescription = "to-be-removed"
+
+ val (_, displayToolbar) = createDisplayToolbar()
+
+ val action = BrowserToolbar.Button(mock(), contentDescription) {}
+ // Removing action which was never added has no effect
+ displayToolbar.removePageAction(action)
+
+ displayToolbar.addPageAction(action)
+ assertEquals(1, displayToolbar.views.pageActions.childCount)
+
+ displayToolbar.removePageAction(action)
+ assertEquals(0, displayToolbar.views.pageActions.childCount)
+ }
+
+ @Test
+ fun `page actions will be added as view to the toolbar`() {
+ val (_, displayToolbar) = createDisplayToolbar()
+
+ assertEquals(0, displayToolbar.views.pageActions.childCount)
+
+ val action = BrowserToolbar.Button(mock(), "Reader Mode") {}
+ displayToolbar.addPageAction(action)
+
+ assertEquals(1, displayToolbar.views.pageActions.childCount)
+ val view = displayToolbar.views.pageActions.getChildAt(0)
+ assertEquals("Reader Mode", view.contentDescription)
+ }
+
+ @Test
+ fun `clicking a page action view will execute the listener of the action`() {
+ var listenerExecuted = false
+
+ val action = BrowserToolbar.Button(mock(), "Reload") {
+ listenerExecuted = true
+ }
+
+ val (_, displayToolbar) = createDisplayToolbar()
+ displayToolbar.addPageAction(action)
+
+ assertFalse(listenerExecuted)
+
+ assertEquals(1, displayToolbar.views.pageActions.childCount)
+ val view = displayToolbar.views.pageActions.getChildAt(0)
+
+ assertNotNull(view)
+ view!!.performClick()
+
+ assertTrue(listenerExecuted)
+ }
+
+ @Test
+ fun `navigation actions will be added as view to the toolbar`() {
+ val (_, displayToolbar) = createDisplayToolbar()
+
+ assertEquals(0, displayToolbar.views.navigationActions.childCount)
+
+ displayToolbar.addNavigationAction(BrowserToolbar.Button(mock(), "Back") {})
+ displayToolbar.addNavigationAction(BrowserToolbar.Button(mock(), "Forward") {})
+
+ assertEquals(2, displayToolbar.views.navigationActions.childCount)
+ }
+
+ @Test
+ fun `clicking on navigation action will execute listener of the action`() {
+ val (_, displayToolbar) = createDisplayToolbar()
+
+ var listenerExecuted = false
+ val action = BrowserToolbar.Button(mock(), "Back") {
+ listenerExecuted = true
+ }
+
+ displayToolbar.addNavigationAction(action)
+
+ assertFalse(listenerExecuted)
+
+ assertEquals(1, displayToolbar.views.navigationActions.childCount)
+ val view = displayToolbar.views.navigationActions.getChildAt(0)
+ view.performClick()
+
+ assertTrue(listenerExecuted)
+ }
+
+ @Test
+ fun `view of not visible navigation action gets removed after invalidating`() {
+ val (_, displayToolbar) = createDisplayToolbar()
+
+ var shouldActionBeDisplayed = true
+
+ val action = BrowserToolbar.Button(
+ mock(),
+ "Back",
+ visible = { shouldActionBeDisplayed },
+ ) { /* Do nothing */ }
+
+ displayToolbar.addNavigationAction(action)
+
+ assertEquals(1, displayToolbar.views.navigationActions.childCount)
+
+ shouldActionBeDisplayed = false
+ displayToolbar.invalidateActions()
+
+ assertEquals(0, displayToolbar.views.navigationActions.childCount)
+
+ shouldActionBeDisplayed = true
+ displayToolbar.invalidateActions()
+
+ assertEquals(1, displayToolbar.views.navigationActions.childCount)
+ }
+
+ @Test
+ fun `toolbar should call bind with view argument on action after invalidating`() {
+ val (_, displayToolbar) = createDisplayToolbar()
+
+ val action = spy(BrowserToolbar.Button(mock(), "Reload") {})
+
+ displayToolbar.addPageAction(action)
+
+ assertEquals(1, displayToolbar.views.pageActions.childCount)
+ val view = displayToolbar.views.pageActions.getChildAt(0)
+
+ verify(action, never()).bind(view!!)
+
+ displayToolbar.invalidateActions()
+
+ verify(action).bind(view)
+ }
+
+ @Test
+ fun `page action will not be added if visible lambda of action returns false`() {
+ val (_, displayToolbar) = createDisplayToolbar()
+
+ val visibleAction = BrowserToolbar.Button(mock(), "Reload") {}
+ val invisibleAction = BrowserToolbar.Button(
+ mock(),
+ "Reader Mode",
+ visible = { false },
+ ) {}
+
+ displayToolbar.addPageAction(visibleAction)
+ displayToolbar.addPageAction(invisibleAction)
+
+ assertEquals(1, displayToolbar.views.pageActions.childCount)
+
+ val view = displayToolbar.views.pageActions.getChildAt(0)
+ assertEquals("Reload", view.contentDescription)
+ }
+
+ @Test
+ fun `browser action will not be added if visible lambda of action returns false`() {
+ val (_, displayToolbar) = createDisplayToolbar()
+
+ val visibleAction = BrowserToolbar.Button(mock(), "Tabs") {}
+ val invisibleAction = BrowserToolbar.Button(
+ mock(),
+ "Settings",
+ visible = { false },
+ ) {}
+
+ displayToolbar.addBrowserAction(visibleAction)
+ displayToolbar.addBrowserAction(invisibleAction)
+
+ assertEquals(1, displayToolbar.views.browserActions.childCount)
+
+ val view = displayToolbar.views.browserActions.getChildAt(0)
+ assertEquals("Tabs", view.contentDescription)
+ }
+
+ @Test
+ fun `navigation action will not be added if visible lambda of action returns false`() {
+ val (_, displayToolbar) = createDisplayToolbar()
+
+ val visibleAction = BrowserToolbar.Button(mock(), "Forward") {}
+ val invisibleAction = BrowserToolbar.Button(
+ mock(),
+ "Back",
+ visible = { false },
+ ) {}
+
+ displayToolbar.addNavigationAction(visibleAction)
+ displayToolbar.addNavigationAction(invisibleAction)
+
+ assertEquals(1, displayToolbar.views.navigationActions.childCount)
+
+ val view = displayToolbar.views.navigationActions.getChildAt(0)
+ assertEquals("Forward", view.contentDescription)
+ }
+
+ @Test
+ fun `url background will be added and removed from display layout`() {
+ val (_, displayToolbar) = createDisplayToolbar()
+
+ assertNull(displayToolbar.views.background.drawable)
+
+ displayToolbar.setUrlBackground(
+ ContextCompat.getDrawable(
+ testContext,
+ iconsR.drawable.mozac_ic_broken_lock,
+ ),
+ )
+
+ assertNotNull(displayToolbar.views.background.drawable)
+
+ displayToolbar.setUrlBackground(null)
+
+ assertNull(displayToolbar.views.background.drawable)
+ }
+
+ @Test
+ fun `titleView does not display when there is no title text`() {
+ val (_, displayToolbar) = createDisplayToolbar()
+
+ assertTrue(displayToolbar.views.origin.titleView.isGone)
+
+ displayToolbar.title = "Hello World"
+
+ assertTrue(displayToolbar.views.origin.titleView.isVisible)
+ }
+
+ @Test
+ fun `toolbar only switches to editing mode if onUrlClicked returns true`() {
+ val (toolbar, displayToolbar) = createDisplayToolbar()
+
+ displayToolbar.views.origin.urlView.performClick()
+
+ verify(toolbar).editMode()
+
+ reset(toolbar)
+ displayToolbar.onUrlClicked = { false }
+ displayToolbar.views.origin.urlView.performClick()
+
+ verify(toolbar, never()).editMode()
+
+ reset(toolbar)
+ displayToolbar.onUrlClicked = { true }
+ displayToolbar.views.origin.urlView.performClick()
+
+ verify(toolbar).editMode()
+ }
+
+ @Test
+ fun `urlView delegates long click when set`() {
+ val (_, displayToolbar) = createDisplayToolbar()
+
+ var longUrlClicked = false
+
+ displayToolbar.setOnUrlLongClickListener {
+ longUrlClicked = true
+ false
+ }
+
+ assertFalse(longUrlClicked)
+ displayToolbar.views.origin.urlView.performLongClick()
+ assertTrue(longUrlClicked)
+ }
+
+ @Test
+ fun `urlView longClickListener can be unset`() {
+ val (_, displayToolbar) = createDisplayToolbar()
+
+ var longClicked = false
+ displayToolbar.setOnUrlLongClickListener {
+ longClicked = true
+ true
+ }
+
+ displayToolbar.views.origin.urlView.performLongClick()
+ assertTrue(longClicked)
+ longClicked = false
+
+ displayToolbar.setOnUrlLongClickListener(null)
+ displayToolbar.views.origin.urlView.performLongClick()
+
+ assertFalse(longClicked)
+ }
+
+ @Test
+ fun `iconView changes site secure state when site security changes`() {
+ val (_, displayToolbar) = createDisplayToolbar()
+ assertEquals(SiteSecurity.INSECURE, displayToolbar.views.securityIndicator.siteSecurity)
+
+ displayToolbar.siteSecurity = SiteSecurity.SECURE
+
+ assertEquals(SiteSecurity.SECURE, displayToolbar.views.securityIndicator.siteSecurity)
+
+ displayToolbar.siteSecurity = SiteSecurity.INSECURE
+
+ assertEquals(SiteSecurity.INSECURE, displayToolbar.views.securityIndicator.siteSecurity)
+ }
+
+ @Test
+ fun `securityIconColor is set when securityIconColor changes`() {
+ val (_, displayToolbar) = createDisplayToolbar()
+
+ assertNull(displayToolbar.views.securityIndicator.colorFilter)
+
+ displayToolbar.colors = displayToolbar.colors.copy(
+ securityIconSecure = Color.BLUE,
+ securityIconInsecure = Color.BLUE,
+ )
+
+ assertNotNull(displayToolbar.views.securityIndicator.colorFilter)
+ }
+
+ @Test
+ fun `color filter is set with transparent when securityIconColor changes to transparent and api version is lower than 23`() {
+ ReflectionHelpers.setStaticField(Build.VERSION::class.java, "SDK_INT", 22)
+ val (_, displayToolbar) = createDisplayToolbar()
+
+ assertNull(displayToolbar.views.securityIndicator.colorFilter)
+
+ displayToolbar.colors = displayToolbar.colors.copy(
+ securityIconSecure = Color.TRANSPARENT,
+ securityIconInsecure = Color.TRANSPARENT,
+ )
+
+ assertNotNull(displayToolbar.views.securityIndicator.colorFilter)
+ }
+
+ @Test
+ fun `color filter is cleared when securityIconColor changes to transparent and api version is bigger than 22`() {
+ ReflectionHelpers.setStaticField(Build.VERSION::class.java, "SDK_INT", 23)
+
+ val (_, displayToolbar) = createDisplayToolbar()
+
+ assertNull(displayToolbar.views.securityIndicator.colorFilter)
+
+ displayToolbar.colors = displayToolbar.colors.copy(
+ securityIconSecure = Color.TRANSPARENT,
+ securityIconInsecure = Color.TRANSPARENT,
+ )
+
+ assertNull(displayToolbar.views.securityIndicator.colorFilter)
+ }
+
+ @Test
+ fun `clicking menu button emits facts with additional extras from builder set`() {
+ CollectionProcessor.withFactCollection { facts ->
+ val (_, displayToolbar) = createDisplayToolbar()
+ val menuView = displayToolbar.views.menu
+
+ val menuBuilder = BrowserMenuBuilder(
+ listOf(SimpleBrowserMenuItem("Mozilla")),
+ mapOf(
+ "customTab" to true,
+ "test" to "23",
+ ),
+ )
+ displayToolbar.menuBuilder = menuBuilder
+
+ assertEquals(0, facts.size)
+
+ menuView.impl.performClick()
+
+ assertEquals(1, facts.size)
+
+ val fact = facts[0]
+
+ assertEquals(Component.BROWSER_TOOLBAR, fact.component)
+ assertEquals(Action.CLICK, fact.action)
+ assertEquals("menu", fact.item)
+ assertNull(fact.value)
+
+ assertNotNull(fact.metadata)
+
+ val metadata = fact.metadata!!
+ assertEquals(2, metadata.size)
+ assertTrue(metadata.containsKey("customTab"))
+ assertTrue(metadata.containsKey("test"))
+ assertEquals(true, metadata["customTab"])
+ assertEquals("23", metadata["test"])
+ }
+ }
+
+ @Test
+ fun `clicking on site security indicator invokes listener`() {
+ var listenerInvoked = false
+
+ val (_, displayToolbar) = createDisplayToolbar()
+
+ assertNull(displayToolbar.views.securityIndicator.background)
+
+ displayToolbar.setOnSiteSecurityClickedListener {
+ listenerInvoked = true
+ }
+
+ assertNotNull(displayToolbar.views.securityIndicator.background)
+
+ displayToolbar.views.securityIndicator.performClick()
+
+ assertTrue(listenerInvoked)
+
+ listenerInvoked = false
+
+ displayToolbar.setOnSiteSecurityClickedListener { }
+
+ assertNotNull(displayToolbar.views.securityIndicator.background)
+
+ displayToolbar.views.securityIndicator.performClick()
+
+ assertFalse(listenerInvoked)
+
+ displayToolbar.setOnSiteSecurityClickedListener(null)
+
+ assertNull(displayToolbar.views.securityIndicator.background)
+ }
+
+ @Test
+ fun `Security icon has proper content description`() {
+ val (_, displayToolbar) = createDisplayToolbar()
+ val siteSecurityIconView = displayToolbar.views.securityIndicator
+
+ assertNotNull(siteSecurityIconView.contentDescription)
+ assertEquals(
+ testContext.getString(R.string.mozac_browser_toolbar_content_description_site_info),
+ siteSecurityIconView.contentDescription,
+ )
+ }
+
+ @Test
+ fun `Backgrounding the app dismisses menu if already open`() {
+ var wasDismissed = false
+ val (_, displayToolbar) = createDisplayToolbar()
+ val menuView = displayToolbar.views.menu
+ menuView.impl.register(
+ object : MenuButton.Observer {
+ override fun onDismiss() {
+ wasDismissed = true
+ }
+ },
+ )
+ menuView.menuBuilder = BrowserMenuBuilder(emptyList())
+ menuView.impl.performClick()
+
+ displayToolbar.onStop()
+
+ assertTrue(wasDismissed)
+ }
+
+ @Test
+ fun `set a dismiss lambda on the menu button`() {
+ var wasDismissed = false
+ val (_, displayToolbar) = createDisplayToolbar()
+ displayToolbar.setMenuDismissAction { wasDismissed = true }
+ val menuView = displayToolbar.views.menu
+ menuView.menuBuilder = BrowserMenuBuilder(emptyList())
+ menuView.impl.performClick()
+
+ menuView.dismissMenu()
+ assertTrue(wasDismissed)
+ }
+
+ @Test
+ fun `url formatter used if provided`() {
+ val (_, displayToolbar) = createDisplayToolbar()
+ displayToolbar.url = "https://mozilla.org"
+ assertEquals(displayToolbar.url, displayToolbar.views.origin.url)
+
+ displayToolbar.urlFormatter = { it.replace("https://".toRegex(), "") }
+ displayToolbar.url = "https://mozilla.org"
+ assertEquals("mozilla.org", displayToolbar.views.origin.url)
+ }
+}
diff --git a/mobile/android/android-components/components/browser/toolbar2/src/test/java/mozilla/components/browser/toolbar2/display/HighlightViewTest.kt b/mobile/android/android-components/components/browser/toolbar2/src/test/java/mozilla/components/browser/toolbar2/display/HighlightViewTest.kt
new file mode 100644
index 0000000000..e339b98538
--- /dev/null
+++ b/mobile/android/android-components/components/browser/toolbar2/src/test/java/mozilla/components/browser/toolbar2/display/HighlightViewTest.kt
@@ -0,0 +1,67 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.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.browser.toolbar2.display
+
+import androidx.core.view.isVisible
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import mozilla.components.browser.toolbar2.R
+import mozilla.components.concept.toolbar.Toolbar.Highlight.NONE
+import mozilla.components.concept.toolbar.Toolbar.Highlight.PERMISSIONS_CHANGED
+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.assertNull
+import org.junit.Assert.assertTrue
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.Mockito.spy
+import org.mockito.Mockito.verify
+
+@RunWith(AndroidJUnit4::class)
+class HighlightViewTest {
+
+ @Test
+ fun `after setting tint, can get trackingProtectionTint`() {
+ val view = HighlightView(testContext)
+ view.setTint(android.R.color.black)
+ assertEquals(android.R.color.black, view.highlightTint)
+ }
+
+ @Test
+ fun `setting status will trigger an icon updated`() {
+ val view = HighlightView(testContext)
+
+ view.state = PERMISSIONS_CHANGED
+
+ assertEquals(PERMISSIONS_CHANGED, view.state)
+ assertTrue(view.isVisible)
+ assertNotNull(view.drawable)
+ assertEquals(
+ view.contentDescription,
+ testContext.getString(R.string.mozac_browser_toolbar_content_description_autoplay_blocked),
+ )
+
+ view.state = NONE
+
+ assertEquals(NONE, view.state)
+ assertNull(view.drawable)
+ assertFalse(view.isVisible)
+ assertNull(view.contentDescription)
+ }
+
+ @Test
+ fun `setIcons will trigger an icon updated`() {
+ val view = spy(HighlightView(testContext))
+
+ view.setIcon(
+ testContext.getDrawable(
+ TrackingProtectionIconView.DEFAULT_ICON_ON_NO_TRACKERS_BLOCKED,
+ )!!,
+ )
+
+ verify(view).updateIcon()
+ }
+}
diff --git a/mobile/android/android-components/components/browser/toolbar2/src/test/java/mozilla/components/browser/toolbar2/display/MenuButtonTest.kt b/mobile/android/android-components/components/browser/toolbar2/src/test/java/mozilla/components/browser/toolbar2/display/MenuButtonTest.kt
new file mode 100644
index 0000000000..ada49fd88b
--- /dev/null
+++ b/mobile/android/android-components/components/browser/toolbar2/src/test/java/mozilla/components/browser/toolbar2/display/MenuButtonTest.kt
@@ -0,0 +1,156 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.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.browser.toolbar2.display
+
+import android.graphics.Color
+import android.view.View
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import mozilla.components.browser.menu.BrowserMenu
+import mozilla.components.browser.menu.BrowserMenuBuilder
+import mozilla.components.browser.menu.BrowserMenuHighlight
+import mozilla.components.browser.menu.ext.getHighlight
+import mozilla.components.browser.menu.item.BrowserMenuHighlightableItem
+import mozilla.components.browser.menu.item.SimpleBrowserMenuItem
+import mozilla.components.concept.menu.MenuController
+import mozilla.components.concept.menu.candidate.DecorativeTextMenuCandidate
+import mozilla.components.concept.menu.candidate.TextMenuCandidate
+import mozilla.components.support.test.any
+import mozilla.components.support.test.mock
+import mozilla.components.support.test.robolectric.testContext
+import org.junit.Assert.assertEquals
+import org.junit.Assert.assertFalse
+import org.junit.Assert.assertTrue
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.Mock
+import org.mockito.Mockito.doReturn
+import org.mockito.Mockito.never
+import org.mockito.Mockito.spy
+import org.mockito.Mockito.verify
+import org.mockito.Mockito.`when`
+import org.mockito.MockitoAnnotations
+
+@RunWith(AndroidJUnit4::class)
+class MenuButtonTest {
+ @Mock private lateinit var menuBuilder: BrowserMenuBuilder
+
+ @Mock private lateinit var menuController: MenuController
+
+ @Mock private lateinit var menu: BrowserMenu
+
+ @Mock private lateinit var menuButtonInternal: mozilla.components.browser.menu.view.MenuButton
+ private lateinit var menuButton: MenuButton
+
+ @Before
+ fun setup() {
+ MockitoAnnotations.openMocks(this)
+ `when`(menuBuilder.build(testContext)).thenReturn(menu)
+ `when`(menuButtonInternal.context).thenReturn(testContext)
+
+ menuButton = MenuButton(menuButtonInternal)
+ }
+
+ @Test
+ fun `menu button is visible only if menu builder attached`() {
+ verify(menuButtonInternal).visibility = View.GONE
+
+ `when`(menuButtonInternal.menuBuilder).thenReturn(mock())
+ assertTrue(menuButton.shouldBeVisible())
+
+ `when`(menuButtonInternal.menuBuilder).thenReturn(null)
+ assertFalse(menuButton.shouldBeVisible())
+ }
+
+ @Suppress("Deprecation")
+ @Test
+ fun `menu button sets onDismiss action`() {
+ val action = {}
+ menuButton.setMenuDismissAction(action)
+
+ verify(menuButtonInternal).onDismiss = action
+ }
+
+ @Test
+ fun `icon displays dot if low highlighted item is present in menu`() {
+ verify(menuButtonInternal, never()).invalidateBrowserMenu()
+ verify(menuButtonInternal, never()).setHighlight(any())
+
+ var isHighlighted = false
+ val highlight = BrowserMenuHighlight.LowPriority(Color.YELLOW)
+ val highlightMenuBuilder = spy(
+ BrowserMenuBuilder(
+ listOf(
+ BrowserMenuHighlightableItem(
+ label = "Test",
+ startImageResource = 0,
+ highlight = highlight,
+ isHighlighted = { isHighlighted },
+ ),
+ ),
+ ),
+ )
+ doReturn(menu).`when`(highlightMenuBuilder).build(testContext)
+
+ menuButton.menuBuilder = highlightMenuBuilder
+ `when`(menuButtonInternal.menuBuilder).thenReturn(highlightMenuBuilder)
+ menuButton.invalidateMenu()
+
+ verify(menuButtonInternal).setHighlight(null)
+
+ isHighlighted = true
+ menuButton.invalidateMenu()
+
+ assertEquals(highlight, highlightMenuBuilder.items.getHighlight())
+ verify(menuButtonInternal).setHighlight(highlight)
+ }
+
+ @Test
+ fun `invalidateMenu should invalidate the internal menu`() {
+ `when`(menuButtonInternal.menuController).thenReturn(null)
+ `when`(menuButtonInternal.menuBuilder).thenReturn(mock())
+ verify(menuButtonInternal, never()).invalidateBrowserMenu()
+
+ menuButton.invalidateMenu()
+
+ verify(menuButtonInternal).invalidateBrowserMenu()
+ }
+
+ @Test
+ fun `invalidateMenu should do nothing if using the menu controller`() {
+ `when`(menuButtonInternal.menuController).thenReturn(menuController)
+ `when`(menuButtonInternal.menuBuilder).thenReturn(null)
+ verify(menuButtonInternal, never()).invalidateBrowserMenu()
+
+ menuButton.invalidateMenu()
+
+ verify(menuButtonInternal, never()).invalidateBrowserMenu()
+ }
+
+ @Test
+ fun `invalidateMenu should automatically upgrade menu items if both builder and controller are present`() {
+ val onClick = {}
+ `when`(menuButtonInternal.menuController).thenReturn(menuController)
+ `when`(menuButtonInternal.menuBuilder).thenReturn(
+ BrowserMenuBuilder(
+ listOf(
+ SimpleBrowserMenuItem("Item 1", listener = onClick),
+ SimpleBrowserMenuItem("Item 2"),
+ ),
+ ),
+ )
+ verify(menuButtonInternal, never()).invalidateBrowserMenu()
+
+ menuButton.invalidateMenu()
+
+ verify(menuButtonInternal, never()).invalidateBrowserMenu()
+ verify(menuController).submitList(
+ listOf(
+ TextMenuCandidate("Item 1", onClick = onClick),
+ DecorativeTextMenuCandidate("Item 2"),
+ ),
+ )
+ }
+}
diff --git a/mobile/android/android-components/components/browser/toolbar2/src/test/java/mozilla/components/browser/toolbar2/display/TrackingProtectionIconViewTest.kt b/mobile/android/android-components/components/browser/toolbar2/src/test/java/mozilla/components/browser/toolbar2/display/TrackingProtectionIconViewTest.kt
new file mode 100644
index 0000000000..1386c17e29
--- /dev/null
+++ b/mobile/android/android-components/components/browser/toolbar2/src/test/java/mozilla/components/browser/toolbar2/display/TrackingProtectionIconViewTest.kt
@@ -0,0 +1,43 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.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.browser.toolbar2.display
+
+import android.graphics.PorterDuff
+import android.graphics.PorterDuffColorFilter
+import android.graphics.drawable.AnimatedVectorDrawable
+import android.graphics.drawable.Drawable
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import mozilla.components.support.test.mock
+import mozilla.components.support.test.robolectric.testContext
+import org.junit.Assert.assertEquals
+import org.junit.Assert.assertNotEquals
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@RunWith(AndroidJUnit4::class)
+class TrackingProtectionIconViewTest {
+
+ @Test
+ fun `After setting tint, can get trackingProtectionTint`() {
+ val view = TrackingProtectionIconView(testContext)
+ view.setTint(android.R.color.black)
+ assertEquals(android.R.color.black, view.trackingProtectionTint)
+ }
+
+ @Test
+ fun `colorFilter is cleared on animatable drawables`() {
+ val view = TrackingProtectionIconView(testContext)
+ view.trackingProtectionTint = android.R.color.black
+
+ val drawable = mock<Drawable>()
+ val animatedDrawable = mock<AnimatedVectorDrawable>()
+
+ view.setOrClearColorFilter(drawable)
+ assertEquals(PorterDuffColorFilter(android.R.color.black, PorterDuff.Mode.SRC_ATOP), view.colorFilter)
+
+ view.setOrClearColorFilter(animatedDrawable)
+ assertNotEquals(PorterDuffColorFilter(android.R.color.black, PorterDuff.Mode.SRC_ATOP), view.colorFilter)
+ }
+}
diff --git a/mobile/android/android-components/components/browser/toolbar2/src/test/java/mozilla/components/browser/toolbar2/edit/EditToolbarTest.kt b/mobile/android/android-components/components/browser/toolbar2/src/test/java/mozilla/components/browser/toolbar2/edit/EditToolbarTest.kt
new file mode 100644
index 0000000000..a371126a16
--- /dev/null
+++ b/mobile/android/android-components/components/browser/toolbar2/src/test/java/mozilla/components/browser/toolbar2/edit/EditToolbarTest.kt
@@ -0,0 +1,290 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.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.browser.toolbar2.edit
+
+import android.view.KeyEvent
+import android.view.View
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.test.runTest
+import mozilla.components.browser.toolbar2.BrowserToolbar
+import mozilla.components.browser.toolbar2.R
+import mozilla.components.concept.toolbar.AutocompleteDelegate
+import mozilla.components.concept.toolbar.Toolbar
+import mozilla.components.support.base.Component
+import mozilla.components.support.base.facts.Action
+import mozilla.components.support.base.facts.processor.CollectionProcessor
+import mozilla.components.support.test.mock
+import mozilla.components.support.test.robolectric.testContext
+import mozilla.components.ui.autocomplete.InlineAutocompleteEditText
+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.Test
+import org.junit.runner.RunWith
+import java.util.concurrent.CountDownLatch
+
+@ExperimentalCoroutinesApi // for runTest
+@RunWith(AndroidJUnit4::class)
+class EditToolbarTest {
+ private fun createEditToolbar(): Pair<BrowserToolbar, EditToolbar> {
+ val toolbar: BrowserToolbar = mock()
+ val displayToolbar = EditToolbar(
+ testContext,
+ toolbar,
+ View.inflate(testContext, R.layout.mozac_browser_toolbar_edittoolbar, null),
+ )
+ return Pair(toolbar, displayToolbar)
+ }
+
+ @Test
+ fun `entered text is forwarded to async autocomplete filter`() = runTest {
+ val toolbar = BrowserToolbar(testContext)
+
+ toolbar.edit.views.url.onAttachedToWindow()
+
+ val latch = CountDownLatch(1)
+ var invokedWithParams: List<Any?>? = null
+ toolbar.setAutocompleteListener { p1, p2 ->
+ invokedWithParams = listOf(p1, p2)
+ latch.countDown()
+ }
+
+ toolbar.edit.views.url.setText("Hello")
+
+ // Autocomplete filter will be invoked on a worker thread.
+ // Serialize here for the sake of tests.
+ latch.await()
+
+ assertEquals("Hello", invokedWithParams!![0])
+ assertTrue(invokedWithParams!![1] is AutocompleteDelegate)
+ }
+
+ @Test
+ fun `GIVEN existing user input WHEN a call to refresh autocomplete suggestions is made THEN retart the autocomplete functionality with the current text`() {
+ val toolbar = BrowserToolbar(testContext)
+ toolbar.edit.views.url.onAttachedToWindow()
+ // Fake existing user input.
+ toolbar.edit.views.url.setText("Test")
+ val latch = CountDownLatch(1)
+ var invokedWithParams: List<Any?>? = null
+ // Only now enable the autocomplete functionality.
+ toolbar.setAutocompleteListener { p1, p2 ->
+ invokedWithParams = listOf(p1, p2)
+ latch.countDown()
+ }
+
+ toolbar.refreshAutocomplete()
+
+ // Autocomplete filter will be invoked on a worker thread.
+ // Serialize here for the sake of tests.
+ latch.await()
+ assertEquals("Test", invokedWithParams!![0])
+ assertTrue(invokedWithParams!![1] is AutocompleteDelegate)
+ }
+
+ @Test
+ fun `focus change is forwarded to listener`() {
+ var listenerInvoked = false
+ var value = false
+
+ val toolbar = BrowserToolbar(testContext)
+ toolbar.edit.setOnEditFocusChangeListener { hasFocus ->
+ listenerInvoked = true
+ value = hasFocus
+ }
+
+ // Switch to editing mode and focus view.
+ toolbar.editMode()
+ toolbar.edit.views.url.requestFocus()
+
+ assertTrue(listenerInvoked)
+ assertTrue(value)
+
+ // Switch back to display mode
+ listenerInvoked = false
+ toolbar.displayMode()
+
+ assertTrue(listenerInvoked)
+ assertFalse(value)
+ }
+
+ @Test
+ fun `entering text emits facts`() {
+ CollectionProcessor.withFactCollection { facts ->
+ val toolbar = BrowserToolbar(testContext)
+ toolbar.edit.views.url.onAttachedToWindow()
+
+ assertEquals(0, facts.size)
+
+ toolbar.edit.views.url.setText("https://www.mozilla.org")
+ toolbar.edit.views.url.dispatchKeyEvent(
+ KeyEvent(
+ System.currentTimeMillis(),
+ System.currentTimeMillis(),
+ KeyEvent.ACTION_DOWN,
+ KeyEvent.KEYCODE_ENTER,
+ 0,
+ ),
+ )
+
+ assertEquals(2, facts.size)
+
+ val factDetail = facts[0]
+ assertEquals(Component.UI_AUTOCOMPLETE, factDetail.component)
+ assertEquals(Action.IMPLEMENTATION_DETAIL, factDetail.action)
+ assertEquals("onTextChanged", factDetail.item)
+ assertEquals("InlineAutocompleteEditText", factDetail.value)
+
+ val fact = facts[1]
+ assertEquals(Component.BROWSER_TOOLBAR, fact.component)
+ assertEquals(Action.COMMIT, fact.action)
+ assertEquals("toolbar", fact.item)
+ assertNull(fact.value)
+
+ val metadata = fact.metadata
+ assertNotNull(metadata!!)
+ assertEquals(1, metadata.size)
+ assertTrue(metadata.contains("autocomplete"))
+ assertTrue(metadata["autocomplete"] is Boolean)
+ assertFalse(metadata["autocomplete"] as Boolean)
+ }
+ }
+
+ @Test
+ fun `entering text emits facts with autocomplete metadata`() {
+ CollectionProcessor.withFactCollection { facts ->
+ val toolbar = BrowserToolbar(testContext)
+ toolbar.edit.views.url.onAttachedToWindow()
+
+ assertEquals(0, facts.size)
+
+ toolbar.edit.views.url.setText("https://www.mozilla.org")
+
+ // Fake autocomplete
+ toolbar.edit.views.url.autocompleteResult = InlineAutocompleteEditText.AutocompleteResult(
+ text = "hello world",
+ source = "test-source",
+ totalItems = 100,
+ )
+
+ toolbar.edit.views.url.dispatchKeyEvent(
+ KeyEvent(
+ System.currentTimeMillis(),
+ System.currentTimeMillis(),
+ KeyEvent.ACTION_DOWN,
+ KeyEvent.KEYCODE_ENTER,
+ 0,
+ ),
+ )
+
+ assertEquals(2, facts.size)
+
+ val factDetail = facts[0]
+ assertEquals(Component.UI_AUTOCOMPLETE, factDetail.component)
+ assertEquals(Action.IMPLEMENTATION_DETAIL, factDetail.action)
+ assertEquals("onTextChanged", factDetail.item)
+ assertEquals("InlineAutocompleteEditText", factDetail.value)
+
+ val factCommit = facts[1]
+ assertEquals(Component.BROWSER_TOOLBAR, factCommit.component)
+ assertEquals(Action.COMMIT, factCommit.action)
+ assertEquals("toolbar", factCommit.item)
+ assertNull(factCommit.value)
+
+ val metadata = factCommit.metadata
+ assertNotNull(metadata!!)
+ assertEquals(2, metadata.size)
+
+ assertTrue(metadata.contains("autocomplete"))
+ assertTrue(metadata["autocomplete"] is Boolean)
+ assertTrue(metadata["autocomplete"] as Boolean)
+
+ assertTrue(metadata.contains("source"))
+ assertEquals("test-source", metadata["source"])
+ }
+ }
+
+ @Test
+ fun `clearView gone on init`() {
+ val (_, editToolbar) = createEditToolbar()
+ val clearView = editToolbar.views.clear
+ assertTrue(clearView.visibility == View.GONE)
+ }
+
+ @Test
+ fun `clearView visible on updateUrl`() {
+ val (_, editToolbar) = createEditToolbar()
+ val clearView = editToolbar.views.clear
+
+ editToolbar.updateUrl("TestUrl", false)
+ assertTrue(clearView.visibility == View.VISIBLE)
+ }
+
+ @Test
+ fun `WHEN shouldAppend is set to true updateUrl should append text`() {
+ val (_, editToolbar) = createEditToolbar()
+
+ // Initial state
+ editToolbar.updateUrl(url = "what ")
+
+ // Simulate text update with voice input
+ val actual = editToolbar.updateUrl(url = "is this", shouldAppend = true, shouldHighlight = true)
+ val expected = "what is this"
+
+ assertEquals(expected, actual)
+ assertEquals(expected, editToolbar.views.url.text.toString())
+ assertEquals(5, editToolbar.views.url.selectionStart)
+ assertEquals(12, editToolbar.views.url.selectionEnd)
+ }
+
+ @Test
+ fun `setIconClickListener sets a click listener on the icon view`() {
+ val (_, editToolbar) = createEditToolbar()
+ val iconView = editToolbar.views.icon
+ assertFalse(iconView.hasOnClickListeners())
+ editToolbar.setIconClickListener { /* noop */ }
+ assertTrue(iconView.hasOnClickListeners())
+ }
+
+ @Test
+ fun `clearView clears text in urlView`() {
+ val (_, editToolbar) = createEditToolbar()
+ val clearView = editToolbar.views.clear
+
+ editToolbar.views.url.setText("https://www.mozilla.org")
+ assertTrue(editToolbar.views.url.text.isNotBlank())
+
+ assertNotNull(clearView)
+ clearView.performClick()
+ assertTrue(editToolbar.views.url.text.isBlank())
+ }
+
+ @Test
+ fun `editSuggestion sets text in urlView`() {
+ val (_, editToolbar) = createEditToolbar()
+ val url = editToolbar.views.url
+
+ url.setText("https://www.mozilla.org")
+ assertEquals("https://www.mozilla.org", url.text.toString())
+
+ var callbackCalled = false
+
+ editToolbar.editListener = object : Toolbar.OnEditListener {
+ override fun onTextChanged(text: String) {
+ callbackCalled = true
+ }
+ }
+
+ editToolbar.editSuggestion("firefox")
+
+ assertEquals("firefox", url.text.toString())
+ assertTrue(callbackCalled)
+ assertEquals("firefox".length, url.selectionStart)
+ assertTrue(url.hasFocus())
+ }
+}
diff --git a/mobile/android/android-components/components/browser/toolbar2/src/test/java/mozilla/components/browser/toolbar2/internal/ActionContainerTest.kt b/mobile/android/android-components/components/browser/toolbar2/src/test/java/mozilla/components/browser/toolbar2/internal/ActionContainerTest.kt
new file mode 100644
index 0000000000..e79c804f9e
--- /dev/null
+++ b/mobile/android/android-components/components/browser/toolbar2/src/test/java/mozilla/components/browser/toolbar2/internal/ActionContainerTest.kt
@@ -0,0 +1,99 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.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.browser.toolbar2.internal
+
+import android.view.View
+import mozilla.components.browser.toolbar2.BrowserToolbar
+import mozilla.components.concept.toolbar.Toolbar
+import mozilla.components.support.test.robolectric.testContext
+import org.junit.Assert.assertEquals
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.Mockito.mock
+import org.robolectric.RobolectricTestRunner
+
+@RunWith(RobolectricTestRunner::class)
+class ActionContainerTest {
+ private lateinit var actionContainer: ActionContainer
+ private lateinit var browserAction: Toolbar.Action
+
+ @Before
+ fun setUp() {
+ browserAction = BrowserToolbar.Button(
+ imageDrawable = mock(),
+ contentDescription = "Test",
+ visible = { true },
+ autoHide = { true },
+ weight = { 2 },
+ listener = mock(),
+ )
+ actionContainer = ActionContainer(testContext)
+ }
+
+ @Test
+ fun `GIVEN multiple actions with different weights WHEN calculateInsertionIndex is called THEN action is placed at right index`() {
+ actionContainer.addAction(
+ BrowserToolbar.Button(
+ imageDrawable = mock(),
+ contentDescription = "Share",
+ visible = { true },
+ weight = { 1 },
+ listener = mock(),
+ ),
+ )
+ actionContainer.addAction(
+ BrowserToolbar.Button(
+ imageDrawable = mock(),
+ contentDescription = "Reload",
+ visible = { true },
+ weight = { 3 },
+ listener = mock(),
+ ),
+ )
+ val newAction =
+ BrowserToolbar.Button(
+ imageDrawable = mock(),
+ contentDescription = "Translation",
+ visible = { true },
+ weight = { 2 },
+ listener = mock(),
+ )
+
+ val insertionIndex = actionContainer.calculateInsertionIndex(newAction)
+
+ assertEquals("The insertion index should be", 1, insertionIndex)
+ }
+
+ @Test
+ fun `WHEN addAction is called THEN child views are increased`() {
+ actionContainer.addAction(browserAction)
+
+ assertEquals(1, actionContainer.childCount)
+ }
+
+ @Test
+ fun `WHEN removeAction is called THEN child views are decreased`() {
+ actionContainer.addAction(browserAction)
+ actionContainer.removeAction(browserAction)
+
+ assertEquals(0, actionContainer.childCount)
+ }
+
+ @Test
+ fun `WHEN invalidateAction is called THEN action visibility is reconsidered`() {
+ val browserToolbarAction = BrowserToolbar.Button(
+ imageDrawable = mock(),
+ contentDescription = "Translation",
+ visible = { false },
+ weight = { 2 },
+ listener = mock(),
+ )
+ actionContainer.addAction(browserToolbarAction)
+ actionContainer.invalidateActions()
+
+ assertEquals(View.GONE, actionContainer.visibility)
+ }
+}
diff --git a/mobile/android/android-components/components/browser/toolbar2/src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker b/mobile/android/android-components/components/browser/toolbar2/src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker
new file mode 100644
index 0000000000..cf1c399ea8
--- /dev/null
+++ b/mobile/android/android-components/components/browser/toolbar2/src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker
@@ -0,0 +1,2 @@
+mock-maker-inline
+// This allows mocking final classes (classes are final by default in Kotlin)
diff --git a/mobile/android/android-components/components/compose/cfr/src/main/java/mozilla/components/compose/cfr/CFRPopupLayout.kt b/mobile/android/android-components/components/compose/cfr/src/main/java/mozilla/components/compose/cfr/CFRPopupLayout.kt
new file mode 100644
index 0000000000..4585c0303d
--- /dev/null
+++ b/mobile/android/android-components/components/compose/cfr/src/main/java/mozilla/components/compose/cfr/CFRPopupLayout.kt
@@ -0,0 +1,160 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+package mozilla.components.compose.cfr
+
+import android.view.View
+import androidx.compose.foundation.background
+import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.layout.Column
+import androidx.compose.foundation.layout.IntrinsicSize
+import androidx.compose.foundation.layout.Spacer
+import androidx.compose.foundation.layout.fillMaxSize
+import androidx.compose.foundation.layout.height
+import androidx.compose.foundation.layout.size
+import androidx.compose.material.Button
+import androidx.compose.material.Text
+import androidx.compose.material.TextButton
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.LaunchedEffect
+import androidx.compose.runtime.getValue
+import androidx.compose.runtime.mutableStateOf
+import androidx.compose.runtime.remember
+import androidx.compose.runtime.saveable.rememberSaveable
+import androidx.compose.runtime.setValue
+import androidx.compose.ui.Alignment
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.tooling.preview.Preview
+import androidx.compose.ui.unit.dp
+import androidx.compose.ui.viewinterop.AndroidView
+
+typealias DismissAction = () -> Unit
+
+/**
+ * A layout for displaying a [CFRPopup] anchored by [anchorContent].
+ *
+ * @param showCFR Whether to display the CFR.
+ * @param properties [CFRPopupProperties] allowing to customize the popup appearance and behavior.
+ * @param onCFRShown Invoked when the CFR is displayed.
+ * @param onDismiss Invoked when the CFR is dismissed. Returns true if the dismissal was
+ * explicit (e.g. clicked via the "X" button).
+ * @param text [Text] block containing the CFR's message.
+ * @param action Optional Composable displayed below [text]. Provides a [DismissAction] if the CFR needs
+ * to be dismissed after the action is invoked.
+ * @param anchorContent The Composable to anchor the CFR to.
+ */
+@Composable
+fun CFRPopupLayout(
+ showCFR: Boolean,
+ properties: CFRPopupProperties,
+ onCFRShown: () -> Unit,
+ onDismiss: (Boolean) -> Unit,
+ text: @Composable () -> Unit,
+ action: @Composable (dismissCFR: DismissAction) -> Unit = {},
+ anchorContent: @Composable () -> Unit,
+) {
+ var hasDismissedCFR by rememberSaveable { mutableStateOf(false) }
+
+ Box(
+ modifier = Modifier.height(intrinsicSize = IntrinsicSize.Min),
+ ) {
+ if (showCFR && !hasDismissedCFR) {
+ LaunchedEffect(Unit) {
+ onCFRShown()
+ }
+
+ var popup: CFRPopup? = null
+
+ val invokeDismiss: DismissAction = {
+ if (!hasDismissedCFR) {
+ popup?.dismiss()
+ }
+ popup = null
+ }
+
+ AndroidView(
+ modifier = Modifier.fillMaxSize(),
+ factory = { context ->
+ View(context).also {
+ popup = CFRPopup(
+ anchor = it,
+ properties = properties,
+ onDismiss = { dismissFromButton ->
+ onDismiss(dismissFromButton)
+ hasDismissedCFR = true
+ },
+ text = text,
+ action = {
+ action(invokeDismiss)
+ },
+ )
+ }
+ },
+ onRelease = {
+ invokeDismiss()
+ },
+ update = {
+ popup?.dismiss()
+ popup?.show()
+ },
+ )
+ }
+
+ anchorContent()
+ }
+}
+
+/**
+ * This is to validate the sizing of the underlying AndroidView. The current implementation of CFRs
+ * via [CFRPopupFullscreenLayout] do not render in previews.
+ */
+@Preview
+@Composable
+private fun CFRPopupLayoutPreview() {
+ var cfrVisible by remember { mutableStateOf(true) }
+
+ Column(
+ modifier = Modifier
+ .fillMaxSize()
+ .background(color = Color.LightGray),
+ ) {
+ CFRPopupLayout(
+ showCFR = cfrVisible,
+ properties = CFRPopupProperties(),
+ onCFRShown = {},
+ onDismiss = { cfrVisible = false },
+ text = {
+ Text(text = "This is a CFR in Compose")
+ },
+ action = {
+ TextButton(onClick = { cfrVisible = false }) {
+ Text(text = "Dismiss")
+ }
+ },
+ ) {
+ Box(modifier = Modifier.size(300.dp)) {
+ Text(
+ text = "This is the thing the CFR is anchored to",
+ modifier = Modifier.align(alignment = Alignment.Center),
+ )
+ }
+ }
+
+ Spacer(modifier = Modifier.height(60.dp))
+
+ Box(modifier = Modifier.size(100.dp)) {
+ Text(
+ text = "This is just another element",
+ modifier = Modifier.align(alignment = Alignment.Center),
+ )
+ }
+
+ Spacer(modifier = Modifier.height(60.dp))
+
+ Button(onClick = { cfrVisible = true }) {
+ Text(text = "Show CFR")
+ }
+ }
+}
diff --git a/mobile/android/android-components/components/concept/engine/src/main/java/mozilla/components/concept/engine/translate/TranslationEngineState.kt b/mobile/android/android-components/components/concept/engine/src/main/java/mozilla/components/concept/engine/translate/TranslationEngineState.kt
index 1885c650a4..faa1513ec9 100644
--- a/mobile/android/android-components/components/concept/engine/src/main/java/mozilla/components/concept/engine/translate/TranslationEngineState.kt
+++ b/mobile/android/android-components/components/concept/engine/src/main/java/mozilla/components/concept/engine/translate/TranslationEngineState.kt
@@ -10,6 +10,7 @@ package mozilla.components.concept.engine.translate
* @property detectedLanguages Detected information about preferences and page information.
* @property error If an error state occurred or an error was reported.
* @property isEngineReady If the translation engine is primed for use or will need to be loaded.
+* @property hasVisibleChange If the browser has visibly started showing the translation.
* @property requestedTranslationPair The language pair to translate. Usually populated after first request.
*/
@@ -17,6 +18,7 @@ data class TranslationEngineState(
val detectedLanguages: DetectedLanguages? = null,
val error: String? = null,
val isEngineReady: Boolean? = false,
+ val hasVisibleChange: Boolean? = false,
val requestedTranslationPair: TranslationPair? = null,
)
diff --git a/mobile/android/android-components/components/concept/engine/src/main/java/mozilla/components/concept/engine/translate/TranslationOperation.kt b/mobile/android/android-components/components/concept/engine/src/main/java/mozilla/components/concept/engine/translate/TranslationOperation.kt
index 0f9b62029f..28dfd8b80c 100644
--- a/mobile/android/android-components/components/concept/engine/src/main/java/mozilla/components/concept/engine/translate/TranslationOperation.kt
+++ b/mobile/android/android-components/components/concept/engine/src/main/java/mozilla/components/concept/engine/translate/TranslationOperation.kt
@@ -36,6 +36,13 @@ enum class TranslationOperation {
FETCH_PAGE_SETTINGS,
/**
+ * Fetch the translations offer setting.
+ * Note: this request is also encompassed in [FETCH_PAGE_SETTINGS], but intended for checking
+ * fetching for global settings or when only this setting is needed.
+ */
+ FETCH_OFFER_SETTING,
+
+ /**
* Fetch the user preference on whether to offer, always translate, or never translate for
* all supported language settings.
*/
diff --git a/mobile/android/android-components/components/concept/engine/src/main/java/mozilla/components/concept/engine/webextension/WebExtensionDelegate.kt b/mobile/android/android-components/components/concept/engine/src/main/java/mozilla/components/concept/engine/webextension/WebExtensionDelegate.kt
index fce18e3863..a2e8b18699 100644
--- a/mobile/android/android-components/components/concept/engine/src/main/java/mozilla/components/concept/engine/webextension/WebExtensionDelegate.kt
+++ b/mobile/android/android-components/components/concept/engine/src/main/java/mozilla/components/concept/engine/webextension/WebExtensionDelegate.kt
@@ -49,6 +49,13 @@ interface WebExtensionDelegate {
fun onReady(extension: WebExtension) = Unit
/**
+ * Invoked when optional permissions for a web extension have changed.
+ *
+ * @param extension The [WebExtension] for which permissions have changed.
+ */
+ fun onOptionalPermissionsChanged(extension: WebExtension) = Unit
+
+ /**
* Invoked when a web extension in private browsing allowed is set.
*
* @param extension the modified [WebExtension] instance.
diff --git a/mobile/android/android-components/components/concept/engine/src/test/resources/manifests/example_mdn.json b/mobile/android/android-components/components/concept/engine/src/test/resources/manifests/example_mdn.json
index d08b78f9b7..4e6b1d6a98 100644
--- a/mobile/android/android-components/components/concept/engine/src/test/resources/manifests/example_mdn.json
+++ b/mobile/android/android-components/components/concept/engine/src/test/resources/manifests/example_mdn.json
@@ -5,33 +5,42 @@
"display": "standalone",
"background_color": "#ffffff",
"description": "A simply readable Hacker News app.",
- "icons": [{
- "src": "images/touch/homescreen48.png",
- "sizes": "48x48",
- "type": "image/png"
- }, {
- "src": "images/touch/homescreen72.png",
- "sizes": "72x72",
- "type": "image/png"
- }, {
- "src": "images/touch/homescreen96.png",
- "sizes": "96x96",
- "type": "image/png"
- }, {
- "src": "images/touch/homescreen144.png",
- "sizes": "144x144",
- "type": "image/png"
- }, {
- "src": "images/touch/homescreen168.png",
- "sizes": "168x168",
- "type": "image/png"
- }, {
- "src": "images/touch/homescreen192.png",
- "sizes": "192x192",
- "type": "image/png"
- }],
- "related_applications": [{
- "platform": "play",
- "url": "https://play.google.com/store/apps/details?id=cheeaun.hackerweb"
- }]
+ "icons": [
+ {
+ "src": "images/touch/homescreen48.png",
+ "sizes": "48x48",
+ "type": "image/png"
+ },
+ {
+ "src": "images/touch/homescreen72.png",
+ "sizes": "72x72",
+ "type": "image/png"
+ },
+ {
+ "src": "images/touch/homescreen96.png",
+ "sizes": "96x96",
+ "type": "image/png"
+ },
+ {
+ "src": "images/touch/homescreen144.png",
+ "sizes": "144x144",
+ "type": "image/png"
+ },
+ {
+ "src": "images/touch/homescreen168.png",
+ "sizes": "168x168",
+ "type": "image/png"
+ },
+ {
+ "src": "images/touch/homescreen192.png",
+ "sizes": "192x192",
+ "type": "image/png"
+ }
+ ],
+ "related_applications": [
+ {
+ "platform": "play",
+ "url": "https://play.google.com/store/apps/details?id=cheeaun.hackerweb"
+ }
+ ]
}
diff --git a/mobile/android/android-components/components/concept/engine/src/test/resources/manifests/spec_typical.json b/mobile/android/android-components/components/concept/engine/src/test/resources/manifests/spec_typical.json
index 3f180353eb..82aeb2c95f 100644
--- a/mobile/android/android-components/components/concept/engine/src/test/resources/manifests/spec_typical.json
+++ b/mobile/android/android-components/components/concept/engine/src/test/resources/manifests/spec_typical.json
@@ -4,17 +4,21 @@
"name": "Super Racer 3000",
"description": "The ultimate futuristic racing game from the future!",
"short_name": "Racer3K",
- "icons": [{
- "src": "icon/lowres.webp",
- "sizes": "64x64",
- "type": "image/webp"
- },{
- "src": "icon/lowres.png",
- "sizes": "64x64"
- }, {
- "src": "icon/hd_hi",
- "sizes": "128x128"
- }],
+ "icons": [
+ {
+ "src": "icon/lowres.webp",
+ "sizes": "64x64",
+ "type": "image/webp"
+ },
+ {
+ "src": "icon/lowres.png",
+ "sizes": "64x64"
+ },
+ {
+ "src": "icon/hd_hi",
+ "sizes": "128x128"
+ }
+ ],
"scope": "/racer/",
"start_url": "/racer/start.html",
"display": "fullscreen",
@@ -26,26 +30,34 @@
"scope": "/racer/",
"update_via_cache": "none"
},
- "screenshots": [{
- "src": "screenshots/in-game-1x.jpg",
- "sizes": "640x480",
- "type": "image/jpeg"
- },{
- "src": "screenshots/in-game-2x.jpg",
- "sizes": "1280x920",
- "type": "image/jpeg"
- }],
- "related_applications": [{
- "platform": "play",
- "url": "https://play.google.com/store/apps/details?id=com.example.app1",
- "id": "com.example.app1",
- "min_version": "2",
- "fingerprints": [{
- "type": "sha256_cert",
- "value": "92:5A:39:05:C5:B9:EA:BC:71:48:5F:F2"
- }]
- }, {
- "platform": "itunes",
- "url": "https://itunes.apple.com/app/example-app1/id123456789"
- }]
+ "screenshots": [
+ {
+ "src": "screenshots/in-game-1x.jpg",
+ "sizes": "640x480",
+ "type": "image/jpeg"
+ },
+ {
+ "src": "screenshots/in-game-2x.jpg",
+ "sizes": "1280x920",
+ "type": "image/jpeg"
+ }
+ ],
+ "related_applications": [
+ {
+ "platform": "play",
+ "url": "https://play.google.com/store/apps/details?id=com.example.app1",
+ "id": "com.example.app1",
+ "min_version": "2",
+ "fingerprints": [
+ {
+ "type": "sha256_cert",
+ "value": "92:5A:39:05:C5:B9:EA:BC:71:48:5F:F2"
+ }
+ ]
+ },
+ {
+ "platform": "itunes",
+ "url": "https://itunes.apple.com/app/example-app1/id123456789"
+ }
+ ]
}
diff --git a/mobile/android/android-components/components/concept/engine/src/test/resources/manifests/twitter_mobile.json b/mobile/android/android-components/components/concept/engine/src/test/resources/manifests/twitter_mobile.json
index 142ce0317e..2f661ffc34 100644
--- a/mobile/android/android-components/components/concept/engine/src/test/resources/manifests/twitter_mobile.json
+++ b/mobile/android/android-components/components/concept/engine/src/test/resources/manifests/twitter_mobile.json
@@ -1 +1,28 @@
-{"background_color":"#ffffff","description":"It's what's happening. From breaking news and entertainment, sports and politics, to big events and everyday interests.","display":"standalone","gcm_sender_id":"49625052041","gcm_user_visible_only":true,"icons":[{"src":"https://abs.twimg.com/responsive-web/web/icon-default.604e2486a34a2f6e1.png","sizes":"192x192","type":"image/png"},{"src":"https://abs.twimg.com/responsive-web/web/icon-default.604e2486a34a2f6e1.png","sizes":"512x512","type":"image/png"}],"name":"Twitter","share_target":{"action":"compose/tweet","params":{"title":"title","text":"text","url":"url"}},"short_name":"Twitter","start_url":"/","theme_color":"#ffffff","scope":"/"}
+{
+ "background_color": "#ffffff",
+ "description": "It's what's happening. From breaking news and entertainment, sports and politics, to big events and everyday interests.",
+ "display": "standalone",
+ "gcm_sender_id": "49625052041",
+ "gcm_user_visible_only": true,
+ "icons": [
+ {
+ "src": "https://abs.twimg.com/responsive-web/web/icon-default.604e2486a34a2f6e1.png",
+ "sizes": "192x192",
+ "type": "image/png"
+ },
+ {
+ "src": "https://abs.twimg.com/responsive-web/web/icon-default.604e2486a34a2f6e1.png",
+ "sizes": "512x512",
+ "type": "image/png"
+ }
+ ],
+ "name": "Twitter",
+ "share_target": {
+ "action": "compose/tweet",
+ "params": { "title": "title", "text": "text", "url": "url" }
+ },
+ "short_name": "Twitter",
+ "start_url": "/",
+ "theme_color": "#ffffff",
+ "scope": "/"
+}
diff --git a/mobile/android/android-components/components/concept/sync/src/main/java/mozilla/components/concept/sync/AccountEvent.kt b/mobile/android/android-components/components/concept/sync/src/main/java/mozilla/components/concept/sync/AccountEvent.kt
index fe46cc5b90..e7c0b1650e 100644
--- a/mobile/android/android-components/components/concept/sync/src/main/java/mozilla/components/concept/sync/AccountEvent.kt
+++ b/mobile/android/android-components/components/concept/sync/src/main/java/mozilla/components/concept/sync/AccountEvent.kt
@@ -46,6 +46,9 @@ sealed class AccountEvent {
sealed class DeviceCommandIncoming {
/** A command to open a list of tabs on the current device */
class TabReceived(val from: Device?, val entries: List<TabData>) : DeviceCommandIncoming()
+
+ /** A command to close one or more tabs that are open on the current device */
+ class TabsClosed(val from: Device?, val urls: List<String>) : DeviceCommandIncoming()
}
/**
@@ -54,6 +57,9 @@ sealed class DeviceCommandIncoming {
sealed class DeviceCommandOutgoing {
/** A command to open a tab on another device */
class SendTab(val title: String, val url: String) : DeviceCommandOutgoing()
+
+ /** A command to close one or more tabs that are open on another device */
+ class CloseTab(val urls: List<String>) : DeviceCommandOutgoing()
}
/**
diff --git a/mobile/android/android-components/components/concept/sync/src/main/java/mozilla/components/concept/sync/Devices.kt b/mobile/android/android-components/components/concept/sync/src/main/java/mozilla/components/concept/sync/Devices.kt
index 94b022ce20..876ab86eb6 100644
--- a/mobile/android/android-components/components/concept/sync/src/main/java/mozilla/components/concept/sync/Devices.kt
+++ b/mobile/android/android-components/components/concept/sync/src/main/java/mozilla/components/concept/sync/Devices.kt
@@ -158,6 +158,7 @@ data class DeviceConfig(
*/
enum class DeviceCapability {
SEND_TAB,
+ CLOSE_TABS,
}
/**
diff --git a/mobile/android/android-components/components/concept/sync/src/main/java/mozilla/components/concept/sync/OAuthAccount.kt b/mobile/android/android-components/components/concept/sync/src/main/java/mozilla/components/concept/sync/OAuthAccount.kt
index 7737d4bc36..7ef087c86e 100644
--- a/mobile/android/android-components/components/concept/sync/src/main/java/mozilla/components/concept/sync/OAuthAccount.kt
+++ b/mobile/android/android-components/components/concept/sync/src/main/java/mozilla/components/concept/sync/OAuthAccount.kt
@@ -40,6 +40,17 @@ data class MigratingAccountInfo(
)
/**
+ * User data provided by the web content as a means of delivering the session token to the
+ * application
+ */
+data class UserData(
+ val sessionToken: String,
+ val email: String,
+ val uid: String,
+ val verified: Boolean,
+)
+
+/**
* Representing all the possible entry points into FxA
*
* These entry points will be reflected in the authentication URL and will be tracked
@@ -111,6 +122,14 @@ interface OAuthAccount : AutoCloseable {
suspend fun getProfile(ignoreCache: Boolean = false): Profile?
/**
+ * Sets the user data given by the web content finishing the OAuth flow.
+ * This should only be used by user agents that need the session token
+ *
+ * @param userData: The user data provided by the web content, including the session token
+ */
+ suspend fun setUserData(userData: UserData)
+
+ /**
* Authenticates the current account using the [code] and [state] parameters obtained via the
* OAuth flow initiated by [beginOAuthFlow].
*
diff --git a/mobile/android/android-components/components/feature/accounts-push/build.gradle b/mobile/android/android-components/components/feature/accounts-push/build.gradle
index c87fa7582a..17bc5d8313 100644
--- a/mobile/android/android-components/components/feature/accounts-push/build.gradle
+++ b/mobile/android/android-components/components/feature/accounts-push/build.gradle
@@ -37,6 +37,7 @@ tasks.withType(KotlinCompile).configureEach {
}
dependencies {
+ implementation project(':browser-state')
implementation project(':service-firefox-accounts')
implementation project(':support-ktx')
implementation project(':support-base')
@@ -47,7 +48,9 @@ dependencies {
implementation ComponentsDependencies.androidx_lifecycle_process
implementation ComponentsDependencies.kotlin_coroutines
+ testImplementation project(':concept-engine')
testImplementation project(':support-test')
+ testImplementation project(':support-test-libstate')
testImplementation ComponentsDependencies.androidx_test_core
testImplementation ComponentsDependencies.androidx_test_junit
diff --git a/mobile/android/android-components/components/feature/accounts-push/src/main/java/mozilla/components/feature/accounts/push/CloseTabsFeature.kt b/mobile/android/android-components/components/feature/accounts-push/src/main/java/mozilla/components/feature/accounts/push/CloseTabsFeature.kt
new file mode 100644
index 0000000000..8767064867
--- /dev/null
+++ b/mobile/android/android-components/components/feature/accounts-push/src/main/java/mozilla/components/feature/accounts/push/CloseTabsFeature.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.accounts.push
+
+import androidx.annotation.VisibleForTesting
+import androidx.lifecycle.LifecycleOwner
+import androidx.lifecycle.ProcessLifecycleOwner
+import mozilla.components.browser.state.action.TabListAction
+import mozilla.components.browser.state.state.TabSessionState
+import mozilla.components.browser.state.store.BrowserStore
+import mozilla.components.concept.sync.AccountEvent
+import mozilla.components.concept.sync.AccountEventsObserver
+import mozilla.components.concept.sync.Device
+import mozilla.components.concept.sync.DeviceCommandIncoming
+import mozilla.components.concept.sync.DeviceConstellation
+import mozilla.components.service.fxa.manager.FxaAccountManager
+
+/**
+ * A feature for closing tabs on this device from other devices
+ * in the [DeviceConstellation].
+ *
+ * This feature receives commands to close tabs using the [FxaAccountManager].
+ *
+ * See [CloseTabsUseCases] for the ability to close tabs that are open on
+ * other devices from this device.
+ *
+ * @param browserStore The [BrowserStore] that holds the currently open tabs.
+ * @param accountManager The account manager.
+ * @param owner The Android lifecycle owner for the observers. Defaults to
+ * the [ProcessLifecycleOwner].
+ * @param autoPause Whether or not the observer should automatically be
+ * paused/resumed with the bound lifecycle.
+ * @param onTabsClosed The callback invoked when one or more tabs are closed.
+ */
+class CloseTabsFeature(
+ private val browserStore: BrowserStore,
+ private val accountManager: FxaAccountManager,
+ private val owner: LifecycleOwner = ProcessLifecycleOwner.get(),
+ private val autoPause: Boolean = false,
+ onTabsClosed: (Device?, List<String>) -> Unit,
+) {
+ @VisibleForTesting internal val observer = TabsClosedEventsObserver { device, urls ->
+ val tabsToRemove = getTabsToRemove(urls)
+ if (tabsToRemove.isNotEmpty()) {
+ browserStore.dispatch(TabListAction.RemoveTabsAction(tabsToRemove.map { it.id }))
+ onTabsClosed(device, tabsToRemove.map { it.content.url })
+ }
+ }
+
+ /**
+ * Begins observing the [accountManager] for "tabs closed" events.
+ */
+ fun observe() {
+ accountManager.registerForAccountEvents(observer, owner, autoPause)
+ }
+
+ private fun getTabsToRemove(remotelyClosedUrls: List<String>): List<TabSessionState> {
+ // The user might have the same URL open in multiple tabs on this device, and might want
+ // to remotely close some or all of those tabs. Synced tabs don't carry enough
+ // information to know which duplicates the user meant to close, so we use a heuristic:
+ // if a URL appears N times in the remotely closed URLs list, we'll close up to
+ // N instances of that URL.
+ val countsByUrl = remotelyClosedUrls.groupingBy { it }.eachCount()
+ return browserStore.state.tabs
+ .groupBy { it.content.url }
+ .asSequence()
+ .mapNotNull { (url, tabs) ->
+ countsByUrl[url]?.let { count -> tabs.take(count) }
+ }
+ .flatten()
+ .toList()
+ }
+}
+
+internal class TabsClosedEventsObserver(
+ internal val onTabsClosed: (Device?, List<String>) -> Unit,
+) : AccountEventsObserver {
+ override fun onEvents(events: List<AccountEvent>) {
+ // Group multiple commands from the same device, so that we can close
+ // more tabs at once.
+ events.asSequence()
+ .filterIsInstance<AccountEvent.DeviceCommandIncoming>()
+ .map { it.command }
+ .filterIsInstance<DeviceCommandIncoming.TabsClosed>()
+ .groupingBy { it.from }
+ .fold(emptyList<String>()) { urls, command -> urls + command.urls }
+ .forEach { (device, urls) ->
+ onTabsClosed(device, urls)
+ }
+ }
+}
diff --git a/mobile/android/android-components/components/feature/accounts-push/src/main/java/mozilla/components/feature/accounts/push/CloseTabsUseCases.kt b/mobile/android/android-components/components/feature/accounts-push/src/main/java/mozilla/components/feature/accounts/push/CloseTabsUseCases.kt
new file mode 100644
index 0000000000..845ae27a98
--- /dev/null
+++ b/mobile/android/android-components/components/feature/accounts-push/src/main/java/mozilla/components/feature/accounts/push/CloseTabsUseCases.kt
@@ -0,0 +1,63 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+package mozilla.components.feature.accounts.push
+
+import androidx.annotation.VisibleForTesting
+import androidx.annotation.WorkerThread
+import mozilla.components.concept.sync.Device
+import mozilla.components.concept.sync.DeviceCapability
+import mozilla.components.concept.sync.DeviceCommandOutgoing
+import mozilla.components.concept.sync.DeviceConstellation
+import mozilla.components.service.fxa.manager.FxaAccountManager
+
+/**
+ * Use cases for closing tabs that are open on other devices in the [DeviceConstellation].
+ *
+ * The use cases send commands to close tabs using the [FxaAccountManager].
+ *
+ * See [CloseTabsFeature] for the ability to close tabs on this device from
+ * other devices.
+ *
+ * @param accountManager The account manager.
+ */
+class CloseTabsUseCases(private val accountManager: FxaAccountManager) {
+ /**
+ * Closes a tab that's currently open on another device.
+ *
+ * @param deviceId The ID of the device on which the tab is currently open.
+ * @param url The URL of the tab to close.
+ * @return Whether the command to close the tab was sent to the device.
+ */
+ @WorkerThread
+ suspend fun close(deviceId: String, url: String): Boolean {
+ filterCloseTabsDevices(accountManager) { constellation, devices ->
+ val device = devices.firstOrNull { it.id == deviceId }
+ device?.let {
+ return constellation.sendCommandToDevice(
+ device.id,
+ DeviceCommandOutgoing.CloseTab(listOf(url)),
+ )
+ }
+ }
+
+ return false
+ }
+}
+
+@VisibleForTesting
+internal inline fun filterCloseTabsDevices(
+ accountManager: FxaAccountManager,
+ block: (DeviceConstellation, Collection<Device>) -> Unit,
+) {
+ val constellation = accountManager.authenticatedAccount()?.deviceConstellation() ?: return
+
+ constellation.state()?.let { state ->
+ state.otherDevices.filter {
+ it.capabilities.contains(DeviceCapability.CLOSE_TABS)
+ }.let { devices ->
+ block(constellation, devices)
+ }
+ }
+}
diff --git a/mobile/android/android-components/components/feature/accounts-push/src/main/java/mozilla/components/feature/accounts/push/SendTabFeature.kt b/mobile/android/android-components/components/feature/accounts-push/src/main/java/mozilla/components/feature/accounts/push/SendTabFeature.kt
index 4f049a790b..931dcf59a6 100644
--- a/mobile/android/android-components/components/feature/accounts-push/src/main/java/mozilla/components/feature/accounts/push/SendTabFeature.kt
+++ b/mobile/android/android-components/components/feature/accounts-push/src/main/java/mozilla/components/feature/accounts/push/SendTabFeature.kt
@@ -24,7 +24,7 @@ import mozilla.components.support.base.log.logger.Logger
*
* See [SendTabUseCases] for the ability to send tabs to other devices.
*
- * @param accountManager Firefox account manager.
+ * @param accountManager Account manager.
* @param owner Android lifecycle owner for the observers. Defaults to the [ProcessLifecycleOwner]
* so that we can always observe events throughout the application lifecycle.
* @param autoPause whether or not the observer should automatically be
@@ -38,7 +38,7 @@ class SendTabFeature(
onTabsReceived: (Device?, List<TabData>) -> Unit,
) {
init {
- val observer = EventsObserver(onTabsReceived)
+ val observer = TabReceivedEventsObserver(onTabsReceived)
// Observe the account for all account events, although we'll ignore
// non send-tab command events.
@@ -46,10 +46,10 @@ class SendTabFeature(
}
}
-internal class EventsObserver(
+internal class TabReceivedEventsObserver(
private val onTabsReceived: (Device?, List<TabData>) -> Unit,
) : AccountEventsObserver {
- private val logger = Logger("EventsObserver")
+ private val logger = Logger("TabReceivedEventsObserver")
override fun onEvents(events: List<AccountEvent>) {
events.asSequence()
diff --git a/mobile/android/android-components/components/feature/accounts-push/src/test/java/mozilla/components/feature/accounts/push/CloseTabsFeatureTest.kt b/mobile/android/android-components/components/feature/accounts-push/src/test/java/mozilla/components/feature/accounts/push/CloseTabsFeatureTest.kt
new file mode 100644
index 0000000000..7b18681dce
--- /dev/null
+++ b/mobile/android/android-components/components/feature/accounts-push/src/test/java/mozilla/components/feature/accounts/push/CloseTabsFeatureTest.kt
@@ -0,0 +1,136 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+package mozilla.components.feature.accounts.push
+
+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.sync.Device
+import mozilla.components.concept.sync.DeviceCapability
+import mozilla.components.concept.sync.DeviceType
+import mozilla.components.support.test.any
+import mozilla.components.support.test.eq
+import mozilla.components.support.test.libstate.ext.waitUntilIdle
+import mozilla.components.support.test.mock
+import mozilla.components.support.test.rule.MainCoroutineRule
+import org.junit.Assert.assertEquals
+import org.junit.Assert.assertTrue
+import org.junit.Rule
+import org.junit.Test
+import org.mockito.Mockito.never
+import org.mockito.Mockito.verify
+
+class CloseTabsFeatureTest {
+ @get:Rule
+ val coroutinesTestRule = MainCoroutineRule()
+
+ private val device123 = Device(
+ id = "123",
+ displayName = "Charcoal",
+ deviceType = DeviceType.DESKTOP,
+ isCurrentDevice = false,
+ lastAccessTime = null,
+ capabilities = listOf(DeviceCapability.CLOSE_TABS),
+ subscriptionExpired = true,
+ subscription = null,
+ )
+
+ @Test
+ fun `GIVEN a notification to close multiple URLs WHEN all URLs are open in tabs THEN all tabs are closed and the callback is invoked`() {
+ val urls = listOf(
+ "https://mozilla.org",
+ "https://getfirefox.com",
+ "https://example.org",
+ "https://getthunderbird.com",
+ )
+ val browserStore = BrowserStore(
+ BrowserState(
+ tabs = urls.map { createTab(it) },
+ ),
+ )
+ val callback: (Device?, List<String>) -> Unit = mock()
+ val feature = CloseTabsFeature(
+ browserStore,
+ accountManager = mock(),
+ owner = mock(),
+ onTabsClosed = callback,
+ )
+
+ feature.observer.onTabsClosed(device123, urls)
+
+ browserStore.waitUntilIdle()
+
+ assertTrue(browserStore.state.tabs.isEmpty())
+ verify(callback).invoke(eq(device123), eq(urls))
+ }
+
+ @Test
+ fun `GIVEN a notification to close a URL WHEN the URL is not open in a tab THEN the callback is not invoked`() {
+ val browserStore = BrowserStore()
+ val callback: (Device?, List<String>) -> Unit = mock()
+ val feature = CloseTabsFeature(
+ browserStore,
+ accountManager = mock(),
+ owner = mock(),
+ onTabsClosed = callback,
+ )
+
+ feature.observer.onTabsClosed(device123, listOf("https://mozilla.org"))
+
+ browserStore.waitUntilIdle()
+
+ verify(callback, never()).invoke(any(), any())
+ }
+
+ @Test
+ fun `GIVEN a notification to close duplicate URLs WHEN the duplicate URLs are open in tabs THEN the number of tabs closed matches the number of URLs and the callback is invoked`() {
+ val browserStore = BrowserStore(
+ BrowserState(
+ tabs = listOf(
+ createTab("https://mozilla.org", id = "1"),
+ createTab("https://mozilla.org", id = "2"),
+ createTab("https://getfirefox.com", id = "3"),
+ createTab("https://getfirefox.com", id = "4"),
+ createTab("https://getfirefox.com", id = "5"),
+ createTab("https://getthunderbird.com", id = "6"),
+ createTab("https://example.org", id = "7"),
+ ),
+ ),
+ )
+ val callback: (Device?, List<String>) -> Unit = mock()
+ val feature = CloseTabsFeature(
+ browserStore,
+ accountManager = mock(),
+ owner = mock(),
+ onTabsClosed = callback,
+ )
+
+ feature.observer.onTabsClosed(
+ device123,
+ listOf(
+ "https://mozilla.org",
+ "https://getfirefox.com",
+ "https://getfirefox.com",
+ "https://example.org",
+ "https://example.org",
+ ),
+ )
+
+ browserStore.waitUntilIdle()
+
+ assertEquals(listOf("2", "5", "6"), browserStore.state.tabs.map { it.id })
+ verify(callback).invoke(
+ eq(device123),
+ eq(
+ listOf(
+ "https://mozilla.org",
+ "https://getfirefox.com",
+ "https://getfirefox.com",
+ "https://example.org",
+ ),
+ ),
+ )
+ }
+}
diff --git a/mobile/android/android-components/components/feature/accounts-push/src/test/java/mozilla/components/feature/accounts/push/CloseTabsUseCasesTest.kt b/mobile/android/android-components/components/feature/accounts-push/src/test/java/mozilla/components/feature/accounts/push/CloseTabsUseCasesTest.kt
new file mode 100644
index 0000000000..4aae8c84f6
--- /dev/null
+++ b/mobile/android/android-components/components/feature/accounts-push/src/test/java/mozilla/components/feature/accounts/push/CloseTabsUseCasesTest.kt
@@ -0,0 +1,100 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.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.accounts.push
+
+import mozilla.components.concept.sync.ConstellationState
+import mozilla.components.concept.sync.Device
+import mozilla.components.concept.sync.DeviceCapability
+import mozilla.components.concept.sync.DeviceConstellation
+import mozilla.components.concept.sync.DeviceType
+import mozilla.components.concept.sync.OAuthAccount
+import mozilla.components.service.fxa.manager.FxaAccountManager
+import mozilla.components.support.test.any
+import mozilla.components.support.test.mock
+import mozilla.components.support.test.rule.MainCoroutineRule
+import mozilla.components.support.test.rule.runTestOnMain
+import org.junit.Assert.assertEquals
+import org.junit.Before
+import org.junit.Rule
+import org.junit.Test
+import org.mockito.Mockito.never
+import org.mockito.Mockito.verify
+import org.mockito.Mockito.`when`
+
+class CloseTabsUseCasesTest {
+ @get:Rule
+ val coroutinesTestRule = MainCoroutineRule()
+
+ private val device123 = Device(
+ id = "123",
+ displayName = "Charcoal",
+ deviceType = DeviceType.DESKTOP,
+ isCurrentDevice = false,
+ lastAccessTime = null,
+ capabilities = listOf(DeviceCapability.CLOSE_TABS),
+ subscriptionExpired = true,
+ subscription = null,
+ )
+
+ private val device1234 = Device(
+ id = "1234",
+ displayName = "Ruby",
+ deviceType = DeviceType.DESKTOP,
+ isCurrentDevice = false,
+ lastAccessTime = null,
+ capabilities = emptyList(),
+ subscriptionExpired = true,
+ subscription = null,
+ )
+
+ private val manager: FxaAccountManager = mock()
+ private val account: OAuthAccount = mock()
+ private val constellation: DeviceConstellation = mock()
+ private val state: ConstellationState = mock()
+
+ @Before
+ fun setUp() {
+ `when`(manager.authenticatedAccount()).thenReturn(account)
+ `when`(account.deviceConstellation()).thenReturn(constellation)
+ `when`(constellation.state()).thenReturn(state)
+ }
+
+ @Test
+ fun `GIVEN a list of devices WHEN one device supports the close tabs command THEN filtering returns that device`() {
+ val deviceIds = mutableListOf<String>()
+ `when`(state.otherDevices).thenReturn(listOf(device123, device1234))
+ filterCloseTabsDevices(manager) { _, devices ->
+ deviceIds.addAll(devices.map { it.id })
+ }
+
+ assertEquals(listOf("123"), deviceIds)
+ }
+
+ @Test
+ fun `GIVEN a constellation with one capable device WHEN sending a close tabs command to that device THEN the command is sent`() = runTestOnMain {
+ val useCases = CloseTabsUseCases(manager)
+
+ `when`(state.otherDevices).thenReturn(listOf(device123))
+ `when`(constellation.sendCommandToDevice(any(), any()))
+ .thenReturn(true)
+
+ useCases.close("123", "http://example.com")
+
+ verify(constellation).sendCommandToDevice(any(), any())
+ }
+
+ @Test
+ fun `GIVEN a constellation with one incapable device WHEN sending a close tabs command to that device THEN the command is not sent`() = runTestOnMain {
+ val useCases = CloseTabsUseCases(manager)
+
+ `when`(state.otherDevices).thenReturn(listOf(device1234))
+ `when`(constellation.sendCommandToDevice(any(), any()))
+ .thenReturn(false)
+
+ useCases.close("1234", "http://example.com")
+
+ verify(constellation, never()).sendCommandToDevice(any(), any())
+ }
+}
diff --git a/mobile/android/android-components/components/feature/accounts-push/src/test/java/mozilla/components/feature/accounts/push/EventsObserverTest.kt b/mobile/android/android-components/components/feature/accounts-push/src/test/java/mozilla/components/feature/accounts/push/TabReceivedEventsObserverTest.kt
index 6de8ff42f6..1b8128d4ba 100644
--- a/mobile/android/android-components/components/feature/accounts-push/src/test/java/mozilla/components/feature/accounts/push/EventsObserverTest.kt
+++ b/mobile/android/android-components/components/feature/accounts-push/src/test/java/mozilla/components/feature/accounts/push/TabReceivedEventsObserverTest.kt
@@ -15,11 +15,11 @@ import org.junit.Test
import org.mockito.Mockito.times
import org.mockito.Mockito.verify
-class EventsObserverTest {
+class TabReceivedEventsObserverTest {
@Test
fun `events are delivered successfully`() {
val callback: (Device?, List<TabData>) -> Unit = mock()
- val observer = EventsObserver(callback)
+ val observer = TabReceivedEventsObserver(callback)
val events = listOf(AccountEvent.DeviceCommandIncoming(command = DeviceCommandIncoming.TabReceived(mock(), mock())))
observer.onEvents(events)
@@ -34,7 +34,7 @@ class EventsObserverTest {
@Test
fun `only TabReceived commands are delivered`() {
val callback: (Device?, List<TabData>) -> Unit = mock()
- val observer = EventsObserver(callback)
+ val observer = TabReceivedEventsObserver(callback)
val events = listOf(
AccountEvent.ProfileUpdated,
AccountEvent.DeviceCommandIncoming(command = DeviceCommandIncoming.TabReceived(mock(), mock())),
diff --git a/mobile/android/android-components/components/feature/accounts-push/src/test/java/mozilla/components/feature/accounts/push/TabsClosedEventsObserverTest.kt b/mobile/android/android-components/components/feature/accounts-push/src/test/java/mozilla/components/feature/accounts/push/TabsClosedEventsObserverTest.kt
new file mode 100644
index 0000000000..8d51d0b812
--- /dev/null
+++ b/mobile/android/android-components/components/feature/accounts-push/src/test/java/mozilla/components/feature/accounts/push/TabsClosedEventsObserverTest.kt
@@ -0,0 +1,183 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.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.accounts.push
+
+import mozilla.components.concept.sync.AccountEvent
+import mozilla.components.concept.sync.Device
+import mozilla.components.concept.sync.DeviceCapability
+import mozilla.components.concept.sync.DeviceCommandIncoming
+import mozilla.components.concept.sync.DeviceType
+import mozilla.components.support.test.any
+import mozilla.components.support.test.eq
+import mozilla.components.support.test.mock
+import org.junit.Test
+import org.mockito.Mockito.times
+import org.mockito.Mockito.verify
+
+class TabsClosedEventsObserverTest {
+ private val device123 = Device(
+ id = "123",
+ displayName = "Charcoal",
+ deviceType = DeviceType.DESKTOP,
+ isCurrentDevice = false,
+ lastAccessTime = null,
+ capabilities = listOf(DeviceCapability.CLOSE_TABS),
+ subscriptionExpired = true,
+ subscription = null,
+ )
+
+ private val device1234 = Device(
+ id = "1234",
+ displayName = "Emerald",
+ deviceType = DeviceType.MOBILE,
+ isCurrentDevice = false,
+ lastAccessTime = null,
+ capabilities = listOf(DeviceCapability.CLOSE_TABS),
+ subscriptionExpired = true,
+ subscription = null,
+ )
+
+ private val device12345 = Device(
+ id = "12345",
+ displayName = "Sapphire",
+ deviceType = DeviceType.MOBILE,
+ isCurrentDevice = false,
+ lastAccessTime = null,
+ capabilities = listOf(DeviceCapability.CLOSE_TABS),
+ subscriptionExpired = true,
+ subscription = null,
+ )
+
+ @Test
+ fun `GIVEN a tabs closed command WHEN the observer is notified THEN the callback is invoked`() {
+ val callback: (Device?, List<String>) -> Unit = mock()
+ val observer = TabsClosedEventsObserver(callback)
+ val events = listOf(
+ AccountEvent.DeviceCommandIncoming(
+ command = DeviceCommandIncoming.TabsClosed(
+ null,
+ listOf("https://mozilla.org"),
+ ),
+ ),
+ )
+
+ observer.onEvents(events)
+
+ verify(callback).invoke(eq(null), eq(listOf("https://mozilla.org")))
+ }
+
+ @Test
+ fun `GIVEN a tabs closed command from a device WHEN the observer is notified THEN the callback is invoked`() {
+ val callback: (Device?, List<String>) -> Unit = mock()
+ val observer = TabsClosedEventsObserver(callback)
+ val events = listOf(
+ AccountEvent.DeviceCommandIncoming(
+ command = DeviceCommandIncoming.TabsClosed(
+ device123,
+ listOf("https://mozilla.org"),
+ ),
+ ),
+ )
+
+ observer.onEvents(events)
+
+ verify(callback).invoke(eq(device123), eq(listOf("https://mozilla.org")))
+ }
+
+ @Test
+ fun `GIVEN multiple commands WHEN the observer is notified THEN the callback is only invoked for the tabs closed commands`() {
+ val callback: (Device?, List<String>) -> Unit = mock()
+ val observer = TabsClosedEventsObserver(callback)
+ val events = listOf(
+ AccountEvent.ProfileUpdated,
+ AccountEvent.DeviceCommandIncoming(
+ command = DeviceCommandIncoming.TabsClosed(
+ device123,
+ listOf("https://mozilla.org"),
+ ),
+ ),
+ )
+
+ observer.onEvents(events)
+
+ verify(callback, times(1)).invoke(eq(device123), eq(listOf("https://mozilla.org")))
+ }
+
+ @Test
+ fun `GIVEN multiple tabs closed commands from the same device WHEN the observer is notified THEN the callback is invoked once`() {
+ val callback: (Device?, List<String>) -> Unit = mock()
+ val observer = TabsClosedEventsObserver(callback)
+ val events = listOf(
+ AccountEvent.DeviceCommandIncoming(
+ command = DeviceCommandIncoming.TabsClosed(
+ device123,
+ listOf("https://mozilla.org", "https://getfirefox.com"),
+ ),
+ ),
+ AccountEvent.DeviceCommandIncoming(
+ command = DeviceCommandIncoming.TabsClosed(
+ device123,
+ listOf("https://example.org"),
+ ),
+ ),
+ AccountEvent.DeviceCommandIncoming(
+ command = DeviceCommandIncoming.TabsClosed(
+ device123,
+ listOf("https://getthunderbird.com"),
+ ),
+ ),
+ )
+
+ observer.onEvents(events)
+
+ verify(callback, times(1)).invoke(
+ eq(device123),
+ eq(
+ listOf(
+ "https://mozilla.org",
+ "https://getfirefox.com",
+ "https://example.org",
+ "https://getthunderbird.com",
+ ),
+ ),
+ )
+ }
+
+ @Test
+ fun `GIVEN multiple tabs closed commands from different devices WHEN the observer is notified THEN the callback is invoked once per device`() {
+ val callback: (Device?, List<String>) -> Unit = mock()
+ val observer = TabsClosedEventsObserver(callback)
+ val events = listOf(
+ AccountEvent.DeviceCommandIncoming(
+ command = DeviceCommandIncoming.TabsClosed(
+ null,
+ listOf("https://mozilla.org"),
+ ),
+ ),
+ AccountEvent.DeviceCommandIncoming(
+ command = DeviceCommandIncoming.TabsClosed(
+ device123,
+ listOf("https://mozilla.org"),
+ ),
+ ),
+ AccountEvent.DeviceCommandIncoming(
+ command = DeviceCommandIncoming.TabsClosed(
+ device1234,
+ listOf("https://mozilla.org"),
+ ),
+ ),
+ AccountEvent.DeviceCommandIncoming(
+ command = DeviceCommandIncoming.TabsClosed(
+ device12345,
+ listOf("https://mozilla.org"),
+ ),
+ ),
+ )
+
+ observer.onEvents(events)
+
+ verify(callback, times(4)).invoke(any(), eq(listOf("https://mozilla.org")))
+ }
+}
diff --git a/mobile/android/android-components/components/feature/accounts/src/main/assets/extensions/fxawebchannel/background.js b/mobile/android/android-components/components/feature/accounts/src/main/assets/extensions/fxawebchannel/background.js
index b90f57154a..e8cf40ba8d 100644
--- a/mobile/android/android-components/components/feature/accounts/src/main/assets/extensions/fxawebchannel/background.js
+++ b/mobile/android/android-components/components/feature/accounts/src/main/assets/extensions/fxawebchannel/background.js
@@ -10,12 +10,12 @@ let port = browser.runtime.connectNative(WEB_CHANNEL_BACKGROUND_MESSAGING_ID);
/*
Handle messages from native application, register content script for specific url.
*/
-port.onMessage.addListener( event => {
- if(event.type == "overrideFxAServer"){
+port.onMessage.addListener(event => {
+ if (event.type == "overrideFxAServer") {
browser.contentScripts.register({
- "matches": [ event.url+"/*" ],
- "js": [{file: "fxawebchannel.js"}],
- "runAt": "document_start"
+ matches: [event.url + "/*"],
+ js: [{ file: "fxawebchannel.js" }],
+ runAt: "document_start",
});
port.disconnect();
}
diff --git a/mobile/android/android-components/components/feature/accounts/src/main/assets/extensions/fxawebchannel/fxawebchannel.js b/mobile/android/android-components/components/feature/accounts/src/main/assets/extensions/fxawebchannel/fxawebchannel.js
index 2f5934dff1..16614d3069 100644
--- a/mobile/android/android-components/components/feature/accounts/src/main/assets/extensions/fxawebchannel/fxawebchannel.js
+++ b/mobile/android/android-components/components/feature/accounts/src/main/assets/extensions/fxawebchannel/fxawebchannel.js
@@ -10,16 +10,18 @@ let port = browser.runtime.connectNative("mozacWebchannel");
/*
Handle messages from native application, dispatch them to FxA via an event.
*/
-port.onMessage.addListener((event) => {
- window.dispatchEvent(new CustomEvent('WebChannelMessageToContent', {
- detail: JSON.stringify(event)
- }));
+port.onMessage.addListener(event => {
+ window.dispatchEvent(
+ new CustomEvent("WebChannelMessageToContent", {
+ detail: JSON.stringify(event),
+ })
+ );
});
/*
Handle messages from FxA. Messages are posted to the native application for processing.
*/
-window.addEventListener('WebChannelMessageToChrome', function (e) {
+window.addEventListener("WebChannelMessageToChrome", function (e) {
const detail = JSON.parse(e.detail);
port.postMessage(detail);
});
diff --git a/mobile/android/android-components/components/feature/accounts/src/main/java/mozilla/components/feature/accounts/FirefoxAccountsAuthFeature.kt b/mobile/android/android-components/components/feature/accounts/src/main/java/mozilla/components/feature/accounts/FirefoxAccountsAuthFeature.kt
index 60913282b7..b244eb0de8 100644
--- a/mobile/android/android-components/components/feature/accounts/src/main/java/mozilla/components/feature/accounts/FirefoxAccountsAuthFeature.kt
+++ b/mobile/android/android-components/components/feature/accounts/src/main/java/mozilla/components/feature/accounts/FirefoxAccountsAuthFeature.kt
@@ -38,10 +38,15 @@ class FirefoxAccountsAuthFeature(
* @param context [Context] The application context
* @param entrypoint [FxAEntryPoint] The Firefox Accounts feature/entrypoint that is launching
* authentication
+ * @param scopes [Set<String>] The oAuth scopes being requested
*/
- fun beginAuthentication(context: Context, entrypoint: FxAEntryPoint) {
+ fun beginAuthentication(
+ context: Context,
+ entrypoint: FxAEntryPoint,
+ scopes: Set<String> = emptySet(),
+ ) {
beginAuthenticationAsync(context) {
- accountManager.beginAuthentication(entrypoint = entrypoint)
+ accountManager.beginAuthentication(entrypoint = entrypoint, authScopes = scopes)
}
}
@@ -50,15 +55,17 @@ class FirefoxAccountsAuthFeature(
* @param context [Context] The application context
* @param pairingUrl [String] The pairing URL retrieved from the QR scanner
* @param entrypoint [FxAEntryPoint] The Firefox Accounts feature/entrypoint that is launching
+ * @param scopes [Set<String>] The oAuth scopes being requested
* authentication
*/
fun beginPairingAuthentication(
context: Context,
pairingUrl: String,
entrypoint: FxAEntryPoint,
+ scopes: Set<String> = emptySet(),
) {
beginAuthenticationAsync(context) {
- accountManager.beginAuthentication(pairingUrl, entrypoint = entrypoint)
+ accountManager.beginAuthentication(pairingUrl, entrypoint = entrypoint, scopes)
}
}
diff --git a/mobile/android/android-components/components/feature/accounts/src/main/java/mozilla/components/feature/accounts/FxaWebChannelFeature.kt b/mobile/android/android-components/components/feature/accounts/src/main/java/mozilla/components/feature/accounts/FxaWebChannelFeature.kt
index f5554c99e4..377d6b0d93 100644
--- a/mobile/android/android-components/components/feature/accounts/src/main/java/mozilla/components/feature/accounts/FxaWebChannelFeature.kt
+++ b/mobile/android/android-components/components/feature/accounts/src/main/java/mozilla/components/feature/accounts/FxaWebChannelFeature.kt
@@ -20,6 +20,7 @@ import mozilla.components.concept.engine.webextension.MessageHandler
import mozilla.components.concept.engine.webextension.Port
import mozilla.components.concept.engine.webextension.WebExtensionRuntime
import mozilla.components.concept.sync.AuthType
+import mozilla.components.concept.sync.UserData
import mozilla.components.lib.state.ext.flowScoped
import mozilla.components.service.fxa.FxaAuthData
import mozilla.components.service.fxa.ServerConfig
@@ -157,6 +158,7 @@ class FxaWebChannelFeature(
WebChannelCommand.CAN_LINK_ACCOUNT -> processCanLinkAccountCommand(messageId)
WebChannelCommand.FXA_STATUS -> processFxaStatusCommand(accountManager, messageId, fxaCapabilities)
WebChannelCommand.OAUTH_LOGIN -> processOauthLoginCommand(accountManager, payload)
+ WebChannelCommand.LOGIN -> processLoginCommand(accountManager, payload)
}
response?.let { port.postMessage(it) }
}
@@ -195,6 +197,7 @@ class FxaWebChannelFeature(
enum class WebChannelCommand {
CAN_LINK_ACCOUNT,
+ LOGIN,
OAUTH_LOGIN,
FXA_STATUS,
}
@@ -222,6 +225,12 @@ class FxaWebChannelFeature(
private const val COMMAND_STATUS = "fxaccounts:fxa_status"
/**
+ * Gets triggered when the web content is signed in/up, but not necessarily verified
+ * it passes in its payload the session token the web content is holding on to
+ */
+ private const val COMMAND_LOGIN = "fxaccounts:login"
+
+ /**
* Handles the [COMMAND_CAN_LINK_ACCOUNT] event from the web-channel.
* Currently this always response with 'ok=true'.
* On Fx Desktop, this event prompts a possible "another user was previously logged in on
@@ -329,6 +338,32 @@ class FxaWebChannelFeature(
}
/**
+ * Handles the [COMMAND_LOGIN] event from the web-channel
+ */
+ private fun processLoginCommand(accountManager: FxaAccountManager, payload: JSONObject): JSONObject? {
+ val sessionToken: String
+ val email: String
+ val uid: String
+ val verified: Boolean
+
+ try {
+ val data = payload.getJSONObject("data")
+ sessionToken = data.getString("sessionToken")
+ email = data.getString("email")
+ uid = data.getString("uid")
+ verified = data.getBoolean("verified")
+ } catch (e: JSONException) {
+ logger.error("Error while processing WebChannel login command", e)
+ return null
+ }
+ val userData = UserData(sessionToken, email, uid, verified)
+ CoroutineScope(Dispatchers.Main).launch {
+ accountManager.setUserData(userData)
+ }
+ return null
+ }
+
+ /**
* Handles the [COMMAND_OAUTH_LOGIN] event from the web-channel.
*/
private fun processOauthLoginCommand(accountManager: FxaAccountManager, payload: JSONObject): JSONObject? {
@@ -368,6 +403,7 @@ class FxaWebChannelFeature(
COMMAND_CAN_LINK_ACCOUNT -> WebChannelCommand.CAN_LINK_ACCOUNT
COMMAND_OAUTH_LOGIN -> WebChannelCommand.OAUTH_LOGIN
COMMAND_STATUS -> WebChannelCommand.FXA_STATUS
+ COMMAND_LOGIN -> WebChannelCommand.LOGIN
else -> {
logger.warn("Unrecognized WebChannel command: $this")
null
diff --git a/mobile/android/android-components/components/feature/accounts/src/test/java/mozilla/components/feature/accounts/FirefoxAccountsAuthFeatureTest.kt b/mobile/android/android-components/components/feature/accounts/src/test/java/mozilla/components/feature/accounts/FirefoxAccountsAuthFeatureTest.kt
index a32681e8fe..ef7f78b336 100644
--- a/mobile/android/android-components/components/feature/accounts/src/test/java/mozilla/components/feature/accounts/FirefoxAccountsAuthFeatureTest.kt
+++ b/mobile/android/android-components/components/feature/accounts/src/test/java/mozilla/components/feature/accounts/FirefoxAccountsAuthFeatureTest.kt
@@ -17,8 +17,8 @@ import mozilla.components.concept.sync.AuthType
import mozilla.components.concept.sync.DeviceConfig
import mozilla.components.concept.sync.DeviceType
import mozilla.components.concept.sync.FxAEntryPoint
-import mozilla.components.concept.sync.OAuthAccount
import mozilla.components.concept.sync.Profile
+import mozilla.components.service.fxa.FirefoxAccount
import mozilla.components.service.fxa.FxaAuthData
import mozilla.components.service.fxa.ServerConfig
import mozilla.components.service.fxa.StorageWrapper
@@ -45,13 +45,13 @@ internal class TestableStorageWrapper(
manager: FxaAccountManager,
accountEventObserverRegistry: ObserverRegistry<AccountEventsObserver>,
serverConfig: ServerConfig,
- private val block: () -> OAuthAccount = {
- val account: OAuthAccount = mock()
+ private val block: () -> FirefoxAccount = {
+ val account: FirefoxAccount = mock()
`when`(account.deviceConstellation()).thenReturn(mock())
account
},
) : StorageWrapper(manager, accountEventObserverRegistry, serverConfig) {
- override fun obtainAccount(): OAuthAccount = block()
+ override fun obtainAccount(): FirefoxAccount = block()
}
// Same as the actual account manager, except we get to control how FirefoxAccountShaped instances
@@ -63,7 +63,7 @@ class TestableFxaAccountManager(
config: ServerConfig,
scopes: Set<String>,
coroutineContext: CoroutineContext,
- block: () -> OAuthAccount = { mock() },
+ block: () -> FirefoxAccount = { mock() },
) : FxaAccountManager(context, config, DeviceConfig("test", DeviceType.MOBILE, setOf()), null, scopes, null, coroutineContext) {
private val testableStorageWrapper = TestableStorageWrapper(this, accountEventObserverRegistry, serverConfig, block)
override fun getStorageWrapper(): StorageWrapper {
@@ -252,7 +252,7 @@ class FirefoxAccountsAuthFeatureTest {
private suspend fun prepareAccountManagerForSuccessfulAuthentication(
coroutineContext: CoroutineContext,
): TestableFxaAccountManager {
- val mockAccount: OAuthAccount = mock()
+ val mockAccount: FirefoxAccount = mock()
val profile = Profile(uid = "testUID", avatar = null, email = "test@example.com", displayName = "test profile")
`when`(mockAccount.deviceConstellation()).thenReturn(mock())
@@ -279,7 +279,7 @@ class FirefoxAccountsAuthFeatureTest {
private suspend fun prepareAccountManagerForFailedAuthentication(
coroutineContext: CoroutineContext,
): TestableFxaAccountManager {
- val mockAccount: OAuthAccount = mock()
+ val mockAccount: FirefoxAccount = mock()
val profile = Profile(uid = "testUID", avatar = null, email = "test@example.com", displayName = "test profile")
`when`(mockAccount.getProfile(anyBoolean())).thenReturn(profile)
diff --git a/mobile/android/android-components/components/feature/accounts/src/test/java/mozilla/components/feature/accounts/FxaWebChannelFeatureTest.kt b/mobile/android/android-components/components/feature/accounts/src/test/java/mozilla/components/feature/accounts/FxaWebChannelFeatureTest.kt
index 809ed7a703..3a49633f61 100644
--- a/mobile/android/android-components/components/feature/accounts/src/test/java/mozilla/components/feature/accounts/FxaWebChannelFeatureTest.kt
+++ b/mobile/android/android-components/components/feature/accounts/src/test/java/mozilla/components/feature/accounts/FxaWebChannelFeatureTest.kt
@@ -19,6 +19,7 @@ import mozilla.components.concept.engine.webextension.WebExtension
import mozilla.components.concept.sync.AuthType
import mozilla.components.concept.sync.OAuthAccount
import mozilla.components.concept.sync.Profile
+import mozilla.components.concept.sync.UserData
import mozilla.components.service.fxa.FxaAuthData
import mozilla.components.service.fxa.ServerConfig
import mozilla.components.service.fxa.SyncEngine
@@ -701,6 +702,56 @@ class FxaWebChannelFeatureTest {
assertTrue(FxaWebChannelFeature.isCommunicationAllowed("http://localhost", "http://localhost"))
}
+ @Test
+ fun `COMMAND_LOGIN must be processed and sets the user's data`() = runTest {
+ val accountManager: FxaAccountManager = mock() // syncConfig is null by default (is not configured)
+ val engineSession: EngineSession = mock()
+ val ext: WebExtension = mock()
+ val port: Port = mock()
+ val messageHandler = argumentCaptor<MessageHandler>()
+
+ WebExtensionController.installedExtensions[FxaWebChannelFeature.WEB_CHANNEL_EXTENSION_ID] = ext
+
+ val webchannelFeature = prepareFeatureForTest(ext, port, engineSession, null, emptySet(), accountManager)
+ webchannelFeature.start()
+ shadowOf(getMainLooper()).idle()
+
+ verify(ext).registerContentMessageHandler(
+ eq(engineSession),
+ eq(FxaWebChannelFeature.WEB_CHANNEL_MESSAGING_ID),
+ messageHandler.capture(),
+ )
+ messageHandler.value.onPortConnected(port)
+
+ // Action: signin
+ verifyLogin("sessiontoken123", "foo@bar.com", "uid123", false, messageHandler.value, accountManager)
+ }
+
+ @Test
+ fun `COMMAND_LOGIN invalid json sends back`() = runTest {
+ val accountManager: FxaAccountManager = mock() // syncConfig is null by default (is not configured)
+ val engineSession: EngineSession = mock()
+ val ext: WebExtension = mock()
+ val port: Port = mock()
+ val messageHandler = argumentCaptor<MessageHandler>()
+
+ WebExtensionController.installedExtensions[FxaWebChannelFeature.WEB_CHANNEL_EXTENSION_ID] = ext
+
+ val webchannelFeature = prepareFeatureForTest(ext, port, engineSession, null, emptySet(), accountManager)
+ webchannelFeature.start()
+ shadowOf(getMainLooper()).idle()
+
+ verify(ext).registerContentMessageHandler(
+ eq(engineSession),
+ eq(FxaWebChannelFeature.WEB_CHANNEL_MESSAGING_ID),
+ messageHandler.capture(),
+ )
+ messageHandler.value.onPortConnected(port)
+
+ // Action: signin
+ verifyLogin("sessiontoken123", "foo@bar.com", "uid123", false, messageHandler.value, accountManager)
+ }
+
private fun JSONObject.getSupportedEngines(): List<String> {
val engines = this.getJSONObject("message")
.getJSONObject("data")
@@ -798,6 +849,41 @@ class FxaWebChannelFeatureTest {
)
}
+ private suspend fun verifyLogin(sessionToken: String, email: String, uid: String, verified: Boolean, messageHandler: MessageHandler, accountManager: FxaAccountManager) {
+ val jsonToWebChannel = jsonLogin(sessionToken, email, uid, verified)
+ val port = mock<Port>()
+ whenever(port.senderUrl()).thenReturn("https://foo.bar/email")
+ messageHandler.onPortMessage(jsonToWebChannel, port)
+
+ val expectedUserData = UserData(
+ sessionToken = sessionToken,
+ email = email,
+ uid = uid,
+ verified = verified,
+ )
+ shadowOf(getMainLooper()).idle()
+
+ verify(accountManager).setUserData(expectedUserData)
+ }
+
+ private fun jsonLogin(sessionToken: String, email: String, uid: String, verified: Boolean): JSONObject {
+ return JSONObject(
+ """{
+ "message":{
+ "command": "fxaccounts:login",
+ "messageId":123,
+ "data":{
+ "email":"$email",
+ "sessionToken":"$sessionToken",
+ "uid":"$uid",
+ "verified":$verified
+ }
+ }
+ }
+ """.trimIndent(),
+ )
+ }
+
private fun prepareFeatureForTest(
ext: WebExtension = mock(),
port: Port = mock(),
diff --git a/mobile/android/android-components/components/feature/addons/src/main/java/mozilla/components/feature/addons/AddonManager.kt b/mobile/android/android-components/components/feature/addons/src/main/java/mozilla/components/feature/addons/AddonManager.kt
index d3e12a0171..723d3e6eb1 100644
--- a/mobile/android/android-components/components/feature/addons/src/main/java/mozilla/components/feature/addons/AddonManager.kt
+++ b/mobile/android/android-components/components/feature/addons/src/main/java/mozilla/components/feature/addons/AddonManager.kt
@@ -252,9 +252,9 @@ class AddonManager(
permissions = permissions,
origins = origins,
onSuccess = { ext ->
- val enabledAddon = addon.copy(installedState = toInstalledState(ext))
+ val updatedAddon = Addon.newFromWebExtension(ext, toInstalledState(ext))
completePendingAddonAction(pendingAction)
- onSuccess(enabledAddon)
+ onSuccess(updatedAddon)
},
onError = {
completePendingAddonAction(pendingAction)
@@ -296,9 +296,9 @@ class AddonManager(
permissions = permissions,
origins = origins,
onSuccess = { ext ->
- val enabledAddon = addon.copy(installedState = toInstalledState(ext))
+ val updatedAddon = Addon.newFromWebExtension(ext, toInstalledState(ext))
completePendingAddonAction(pendingAction)
- onSuccess(enabledAddon)
+ onSuccess(updatedAddon)
},
onError = {
completePendingAddonAction(pendingAction)
diff --git a/mobile/android/android-components/components/feature/addons/src/main/java/mozilla/components/feature/addons/ui/PermissionsDialogFragment.kt b/mobile/android/android-components/components/feature/addons/src/main/java/mozilla/components/feature/addons/ui/PermissionsDialogFragment.kt
index 92e555e722..a19a5a61f5 100644
--- a/mobile/android/android-components/components/feature/addons/src/main/java/mozilla/components/feature/addons/ui/PermissionsDialogFragment.kt
+++ b/mobile/android/android-components/components/feature/addons/src/main/java/mozilla/components/feature/addons/ui/PermissionsDialogFragment.kt
@@ -153,9 +153,10 @@ class PermissionsDialogFragment : AddonDialogFragment() {
},
addon.translateName(requireContext()),
)
- rootView.findViewById<TextView>(R.id.optional_or_required_text).text = buildOptionalOrRequiredText()
-
val listPermissions = buildPermissionsList()
+ rootView.findViewById<TextView>(R.id.optional_or_required_text).text =
+ buildOptionalOrRequiredText(listPermissions.isNotEmpty())
+
val permissionsRecyclerView = rootView.findViewById<RecyclerView>(R.id.permissions)
val positiveButton = rootView.findViewById<Button>(R.id.allow_button)
val negativeButton = rootView.findViewById<Button>(R.id.deny_button)
@@ -217,7 +218,10 @@ class PermissionsDialogFragment : AddonDialogFragment() {
}
@VisibleForTesting
- internal fun buildOptionalOrRequiredText(): String {
+ internal fun buildOptionalOrRequiredText(hasPermissions: Boolean): String {
+ if (!hasPermissions) {
+ return ""
+ }
val optionalOrRequiredText = if (forOptionalPermissions) {
getString(R.string.mozac_feature_addons_optional_permissions_dialog_subtitle)
} else {
diff --git a/mobile/android/android-components/components/feature/addons/src/main/res/values-be/strings.xml b/mobile/android/android-components/components/feature/addons/src/main/res/values-be/strings.xml
index 30c37d9ad9..ac9b647423 100644
--- a/mobile/android/android-components/components/feature/addons/src/main/res/values-be/strings.xml
+++ b/mobile/android/android-components/components/feature/addons/src/main/res/values-be/strings.xml
@@ -88,6 +88,8 @@
<string name="mozac_feature_addons_rating">Ацэнка</string>
<!-- A link that points to the detail page of the add-on. -->
<string name="mozac_feature_addons_more_info_link" moz:removedIn="126" tools:ignore="UnusedResources">Падрабязней аб гэтым дадатку</string>
+ <!-- A link that points to the detail page of the extension. -->
+ <string name="mozac_feature_addons_more_info_link_2">Падрабязней аб гэтым пашырэнні</string>
<!-- The settings of the add-on. -->
<string name="mozac_feature_addons_settings">Налады</string>
<!-- Indicates the add-on is enabled. -->
@@ -148,16 +150,24 @@
<string name="mozac_feature_addons_user_rating_count_2">Водгукі: %1$s</string>
<!-- Accessibility content description for the amount of stars that add-on has, where %1$.02f will be the amount of stars and / separator and 5 the maximum number of stars e.g (2/5, 4.5/5 or 5/5) . -->
<string name="mozac_feature_addons_rating_content_description" moz:removedIn="124" tools:ignore="UnusedResources">%1$.02f/5</string>
+ <!-- Accessibility content description for the amount of stars that add-on has, where %1$.02f will be the amount of stars. -->
+ <string name="mozac_feature_addons_rating_content_description_2">Ацэнка: %1$.02f з 5</string>
<!-- This is the title of page where all the add-ons are listed-->
<string name="mozac_feature_addons_addons">Дадаткі</string>
<!-- Label for add-ons sub menu item for add-ons manager-->
<string name="mozac_feature_addons_addons_manager">Менеджар дадаткаў</string>
<!-- The title of the "crash" notification in the add-ons manager -->
<string name="mozac_feature_addons_manager_notification_title_text" moz:removedIn="126" tools:ignore="UnusedResources">Дадаткі часова адключаны</string>
+ <!-- The title of the "crash" notification in the extensions manager -->
+ <string name="mozac_feature_extensions_manager_notification_title_text">Пашырэнні часова адключаны</string>
<!-- The content of the "crash" notification in the add-ons manager -->
<string name="mozac_feature_addons_manager_notification_content_text" moz:removedIn="126" tools:ignore="UnusedResources">Адзін або некалькі дадатковых кампанентаў перасталі працаваць, што зрабіла вашу сістэму нестабільнай.</string>
+ <!-- The content of the "crash" notification in the extensions manager -->
+ <string name="mozac_feature_extensions_manager_notification_content_text">Адно або некалькі пашырэнняў перасталі працаваць, што зрабіла вашу сістэму нестабільнай.</string>
<!-- Button to re-enable the add-ons in the "crash" notification -->
<string name="mozac_feature_addons_manager_notification_restart_button" moz:removedIn="126" tools:ignore="UnusedResources">Перазапусціць дадаткі</string>
+ <!-- Button to re-enable the extensions in the "crash" notification -->
+ <string name="mozac_feature_extensions_manager_notification_restart_button">Перазапусціць пашырэнні</string>
<!-- Button in the add-ons manager that opens AMO in a tab -->
<string name="mozac_feature_addons_find_more_addons_button_text" moz:removedIn="126" tools:ignore="UnusedResources">Знайсці больш дадаткаў</string>
<!-- Button in the extensions manager that opens AMO in a tab -->
@@ -238,6 +248,8 @@
<string name="mozac_feature_addons_unsupported_caption_2">1 пашырэнне</string>
<!-- Text shown in not yet supported add-ons section in AddonsManagerAdapter - plural. %1$s is the number of unsupported add-ons -->
<string name="mozac_feature_addons_unsupported_caption_plural" moz:removedIn="126" tools:ignore="UnusedResources">Дадаткаў: %1$s</string>
+ <!-- Text shown in not yet supported add-ons section - plural. %1$s is the number of unsupported extensions. -->
+ <string name="mozac_feature_addons_unsupported_caption_plural_2">%1$s пашырэнняў</string>
<!-- Text link to a sumo page for learning more about unsupported add-ons. -->
<string name="mozac_feature_addons_unsupported_learn_more">Даведацца больш</string>
<!-- Displayed in the "Status" field for the updater when an add-on has been correctly updated. -->
@@ -256,6 +268,8 @@
<string name="mozac_feature_addons_installed_dialog_title">%1$s было дададзена ў %2$s</string>
<!-- Text shown in the dialog when add-on installation is completed. -->
<string name="mozac_feature_addons_installed_dialog_description" moz:removedIn="124" tools:ignore="UnusedResources">Адкрыць яго ў меню</string>
+ <!-- Text shown in the dialog when add-on installation is completed. %1$s is the add-on name. %2$s is the app name. -->
+ <string name="mozac_feature_addons_installed_dialog_description_2">Доступ да %1$s з меню %2$s.</string>
<!-- Confirmation button text for the dialog when add-on installation is completed. -->
<string name="mozac_feature_addons_installed_dialog_okay_button" moz:removedIn="124" tools:ignore="UnusedResources">Добра, зразумела</string>
<!-- Confirmation button text for the dialog when add-on installation is completed. -->
diff --git a/mobile/android/android-components/components/feature/addons/src/main/res/values-br/strings.xml b/mobile/android/android-components/components/feature/addons/src/main/res/values-br/strings.xml
index 2fb0506106..2f02310fe1 100644
--- a/mobile/android/android-components/components/feature/addons/src/main/res/values-br/strings.xml
+++ b/mobile/android/android-components/components/feature/addons/src/main/res/values-br/strings.xml
@@ -76,8 +76,6 @@
<string name="mozac_feature_addons_version">Handelv</string>
<!-- The author of an add-on. -->
<string name="mozac_feature_addons_author">Aozer</string>
- <!-- The authors of an add-on. -->
- <string name="mozac_feature_addons_authors" moz:removedIn="123" tools:ignore="UnusedResources">Aozerien</string>
<!-- The last date that the add-on was updated. -->
<string name="mozac_feature_addons_last_updated">Hizivadur diwezhañ</string>
<!-- The developer website (Homepage) of the add-on. -->
@@ -94,8 +92,6 @@
<string name="mozac_feature_addons_settings">Arventennoù</string>
<!-- Indicates the add-on is enabled. -->
<string name="mozac_feature_addons_settings_on">Gweredekaet</string>
- <!-- Indicates the add-on is disabled. -->
- <string name="mozac_feature_addons_settings_off" moz:removedIn="125" tools:ignore="UnusedResources">Diweredekaet</string>
<!-- Indicates the add-on is allowed in private browsing mode. -->
<string name="mozac_feature_addons_settings_allow_in_private_browsing">Aotren er Merdeiñ Prevez</string>
<!-- Indicates the add-on is allowed in private browsing mode. -->
@@ -104,8 +100,6 @@
<string name="mozac_feature_addons_not_allowed_in_private_browsing">N’eo ket aotreet er prenestroù prevez</string>
<!-- Indicates the add-on is enabled. -->
<string name="mozac_feature_addons_enabled">Gweredekaet</string>
- <!-- Indicates the add-on is disabled. -->
- <string name="mozac_feature_addons_disabled" moz:removedIn="125" tools:ignore="UnusedResources">Diweredekaet</string>
<!-- This is displayed in a page where the user can see the installed and recommended(not installed yet) add-ons, this string indicates the installed section. -->
<string name="mozac_feature_addons_installed_section">Staliet</string>
<!-- This is displayed in a page where the user can see the installed and recommended(not installed yet) add-ons, this string indicates the recommended section. -->
@@ -140,22 +134,26 @@
<string name="mozac_feature_addons_permissions_dialog_deny">Nac’hañ</string>
<!-- This is a button to cancel the add-on installation . -->
<string name="mozac_feature_addons_permissions_dialog_cancel">Nullañ</string>
- <!-- Accessibility content description to install add-on button. -->
- <string name="mozac_feature_addons_install_addon_content_description" tools:ignore="UnusedResources" moz:removedIn="124">Staliañ an askouezh</string>
<!-- Accessibility content description to install add-on button. %1$s is the add-on name. -->
<string name="mozac_feature_addons_install_addon_content_description_2">Staliañ %1$s</string>
<!-- This is the label of a button to cancel an ongoing add-on installation. -->
<string name="mozac_feature_addons_install_addon_dialog_cancel">Nullañ</string>
<!-- Indicates how many users have rated an add-on. %1$s will be replaced with number of reviews -->
<string name="mozac_feature_addons_user_rating_count_2">Burutelladennoù: %1$s</string>
- <!-- Accessibility content description for the amount of stars that add-on has, where %1$.02f will be the amount of stars and / separator and 5 the maximum number of stars e.g (2/5, 4.5/5 or 5/5) . -->
- <string name="mozac_feature_addons_rating_content_description" moz:removedIn="124" tools:ignore="UnusedResources">%1$.02f/5</string>
+ <!-- Accessibility content description for the amount of stars that add-on has, where %1$.02f will be the amount of stars. -->
+ <string name="mozac_feature_addons_rating_content_description_2">Notenn: %1$.02f war 5</string>
<!-- This is the title of page where all the add-ons are listed-->
<string name="mozac_feature_addons_addons">Askouezhioù</string>
<!-- Label for add-ons sub menu item for add-ons manager-->
<string name="mozac_feature_addons_addons_manager">Ardoer an askouezhioù</string>
<!-- The title of the "crash" notification in the add-ons manager -->
<string name="mozac_feature_addons_manager_notification_title_text" moz:removedIn="126" tools:ignore="UnusedResources">Diweredekaet eo an askouezhioù evit ar mare</string>
+ <!-- The title of the "crash" notification in the extensions manager -->
+ <string name="mozac_feature_extensions_manager_notification_title_text">Diweredekaet eo an askouezhioù evit ar mare</string>
+ <!-- The content of the "crash" notification in the add-ons manager -->
+ <string name="mozac_feature_addons_manager_notification_content_text" moz:removedIn="126" tools:ignore="UnusedResources">Un enlugellad pe meur a hini o deus sac’het, ar pezh a ya da zistabilaat ho reizhiad.</string>
+ <!-- The content of the "crash" notification in the extensions manager -->
+ <string name="mozac_feature_extensions_manager_notification_content_text">Un askouezh pe meur a hini o deus sac’het, ar pezh a ya da zistabilaat ho reizhiad.</string>
<!-- Button to re-enable the add-ons in the "crash" notification -->
<string name="mozac_feature_addons_manager_notification_restart_button" moz:removedIn="126" tools:ignore="UnusedResources">Adloc’hañ an askouezhioù</string>
<!-- Button to re-enable the extensions in the "crash" notification -->
@@ -200,6 +198,8 @@
<string name="mozac_extension_install_progress_caption">O pellgargañ hag o wiriañ an askouezh…</string>
<!-- Error shown when something unexpected happened while trying to get the add-on list from the server -->
<string name="mozac_feature_addons_failed_to_query_add_ons" moz:removedIn="126" tools:ignore="UnusedResources">Ne cʼhaller ket kaout roll an askouezhioù!</string>
+ <!-- Error shown when something unexpected happened while trying to get the extension list from the server -->
+ <string name="mozac_feature_addons_failed_to_query_extensions">Ne cʼhaller ket kaout roll an enlugelladoù!</string>
<!-- Error shown when unable to find a translation for an add-on field. %1$s is the locale of the user and %2$s is the default language of the add-on -->
<string name="mozac_feature_addons_failed_to_translate">N’eo ket bet kavet an droidigezh, nag evit ar yezh %1$s nag evit ar yezh dre ziouer %2$s</string>
<!-- Text shown after successfully installed an add-on. %1$s is the add-on name. -->
@@ -208,12 +208,20 @@
<string name="mozac_feature_addons_failed_to_install">Cʼhwitadenn war staliadur %1$s</string>
<!-- Text shown after failing to install an add-on for which we don't have its name. -->
<string name="mozac_feature_addons_failed_to_install_generic" moz:removedIn="126" tools:ignore="UnusedResources">Staliadur an askouezh c’hwitet.</string>
+ <!-- Text shown after failing to install an extension for which we don't have its name. -->
+ <string name="mozac_feature_addons_extension_failed_to_install">Staliadur an askouezh c’hwitet.</string>
<!-- Text shown when attempting to install an add-on and a network error happened. -->
<string name="mozac_feature_addons_failed_to_install_network_error" moz:removedIn="126" tools:ignore="UnusedResources">An askouezh-mañ n’hall ket bezañ pellgarget en abeg d’ur fazi kennask.</string>
+ <!-- Text shown when attempting to install an extension and a network error happened. -->
+ <string name="mozac_feature_addons_extension_failed_to_install_network_error">An askouezh-mañ n’hall ket bezañ pellgarget en abeg d’ur fazi kennask.</string>
<!-- Text shown when attempting to install an add-on and the downloaded file is corrupted. -->
<string name="mozac_feature_addons_failed_to_install_corrupt_error" moz:removedIn="126" tools:ignore="UnusedResources">An askouezh-mañ n’hall ket bezañ staliet rak kontronet eo war ar seblant.</string>
+ <!-- Text shown when attempting to install an extension and the downloaded file is corrupted. -->
+ <string name="mozac_feature_addons_extension_failed_to_install_corrupt_error">An askouezh-mañ n\'hall ket bezañ staliet rak kontronet eo war ar seblant.</string>
<!-- Text shown when attempting to install an add-on and an error occurred because the extension was not signed. -->
<string name="mozac_feature_addons_failed_to_install_not_signed_error" moz:removedIn="126" tools:ignore="UnusedResources">An askouezh-mañ n’hall ket bezañ staliet rak n’eo ket bet gwiriet.</string>
+ <!-- Text shown when attempting to install an add-on and an error occurred because the extension was not signed. -->
+ <string name="mozac_feature_addons_extension_failed_to_install_not_signed_error">An askouezh-mañ n\'hall ket bezañ staliet rak n\'eo ket bet gwiriet.</string>
<!-- Text shown when attempting to install an add-on and an error occurred because the extension was incompatible. %1$s is the add-on name, %2$s is the app name and %3$s is the app version. -->
<string name="mozac_feature_addons_failed_to_install_incompatible_error">%1$s n’hall ket bezañ staliet rak ne glot ket gant %2$s %3$s.</string>
<!-- Text shown when attempting to install a blocklisted add-on. %1$s is the add-on name. -->
@@ -260,10 +268,8 @@
<string name="mozac_feature_addons_updater_dialog_status">Stad:</string>
<!-- Text shown in the dialog when add-on installation is completed. %1$s is the add-on name. %2$s is the app name. -->
<string name="mozac_feature_addons_installed_dialog_title">Ouzhpennet eo bet %1$s da %2$s.</string>
- <!-- Text shown in the dialog when add-on installation is completed. -->
- <string name="mozac_feature_addons_installed_dialog_description" moz:removedIn="124" tools:ignore="UnusedResources">Digeriñ anezhañ el lañser</string>
- <!-- Confirmation button text for the dialog when add-on installation is completed. -->
- <string name="mozac_feature_addons_installed_dialog_okay_button" moz:removedIn="124" tools:ignore="UnusedResources">Mat eo, komprenet am eus</string>
+ <!-- Text shown in the dialog when add-on installation is completed. %1$s is the add-on name. %2$s is the app name. -->
+ <string name="mozac_feature_addons_installed_dialog_description_2">Haezit %1$s adalek lañser %2$s.</string>
<!-- Confirmation button text for the dialog when add-on installation is completed. -->
<string name="mozac_feature_addons_installed_dialog_okay_button_2">Mat eo</string>
<!-- "Learn more" link displayed below an add-on status message. -->
diff --git a/mobile/android/android-components/components/feature/addons/src/main/res/values-cak/strings.xml b/mobile/android/android-components/components/feature/addons/src/main/res/values-cak/strings.xml
index 12c845c568..c12647a733 100644
--- a/mobile/android/android-components/components/feature/addons/src/main/res/values-cak/strings.xml
+++ b/mobile/android/android-components/components/feature/addons/src/main/res/values-cak/strings.xml
@@ -87,13 +87,15 @@
<!-- The rating of the add-on. -->
<string name="mozac_feature_addons_rating">Kejqalem</string>
<!-- A link that points to the detail page of the add-on. -->
- <string name="mozac_feature_addons_more_info_link">Ch\'aqa\' chik chi rij re tz\'aqat re\'</string>
+ <string name="mozac_feature_addons_more_info_link" moz:removedIn="126" tools:ignore="UnusedResources">Ch\'aqa\' chik chi rij re tz\'aqat re\'</string>
+ <!-- A link that points to the detail page of the extension. -->
+ <string name="mozac_feature_addons_more_info_link_2">Ch\'aqa\' chik chi rij re k\'amal re\'</string>
<!-- The settings of the add-on. -->
<string name="mozac_feature_addons_settings">Taq nuk\'ulem</string>
<!-- Indicates the add-on is enabled. -->
<string name="mozac_feature_addons_settings_on">Tzijïl</string>
<!-- Indicates the add-on is disabled. -->
- <string name="mozac_feature_addons_settings_off">Chupül</string>
+ <string name="mozac_feature_addons_settings_off" moz:removedIn="125" tools:ignore="UnusedResources">Chupül</string>
<!-- Indicates the add-on is allowed in private browsing mode. -->
<string name="mozac_feature_addons_settings_allow_in_private_browsing">Tiya\' q\'ij chi re pa ichinan okem pa k\'amaya\'l</string>
<!-- Indicates the add-on is allowed in private browsing mode. -->
@@ -103,7 +105,7 @@
<!-- Indicates the add-on is enabled. -->
<string name="mozac_feature_addons_enabled">Tzijon</string>
<!-- Indicates the add-on is disabled. -->
- <string name="mozac_feature_addons_disabled">Chupun</string>
+ <string name="mozac_feature_addons_disabled" moz:removedIn="125" tools:ignore="UnusedResources">Chupun</string>
<!-- This is displayed in a page where the user can see the installed and recommended(not installed yet) add-ons, this string indicates the installed section. -->
<string name="mozac_feature_addons_installed_section">Xyak</string>
<!-- This is displayed in a page where the user can see the installed and recommended(not installed yet) add-ons, this string indicates the recommended section. -->
@@ -155,13 +157,21 @@
<!-- Label for add-ons sub menu item for add-ons manager-->
<string name="mozac_feature_addons_addons_manager">Kinuk\'samajel taq Tz\'aqat</string>
<!-- The title of the "crash" notification in the add-ons manager -->
- <string name="mozac_feature_addons_manager_notification_title_text">Echupun jumej ri taq tz\'aqat</string>
+ <string name="mozac_feature_addons_manager_notification_title_text" moz:removedIn="126" tools:ignore="UnusedResources">Echupun jumej ri taq tz\'aqat</string>
+ <!-- The title of the "crash" notification in the extensions manager -->
+ <string name="mozac_feature_extensions_manager_notification_title_text">Echupun jumej ri taq k\'amal</string>
<!-- The content of the "crash" notification in the add-ons manager -->
- <string name="mozac_feature_addons_manager_notification_content_text">Jun o ka\'i\' oxi\' taq tz\'aqat xkiq\'ät kisamaj, ri nub\'än chi man jikil ta ri q\'inoj.</string>
+ <string name="mozac_feature_addons_manager_notification_content_text" moz:removedIn="126" tools:ignore="UnusedResources">Jun o ka\'i\' oxi\' taq tz\'aqat xkiq\'ät kisamaj, ri nub\'än chi man jikil ta ri q\'inoj.</string>
+ <!-- The content of the "crash" notification in the extensions manager -->
+ <string name="mozac_feature_extensions_manager_notification_content_text">Jun o ka\'i\' oxi\' taq k\'amal xkiq\'ät kisamaj, ri nub\'än chi man jikil ta ri q\'inoj.</string>
<!-- Button to re-enable the add-ons in the "crash" notification -->
- <string name="mozac_feature_addons_manager_notification_restart_button">Ketzij chik ri taq tz\'aqat</string>
+ <string name="mozac_feature_addons_manager_notification_restart_button" moz:removedIn="126" tools:ignore="UnusedResources">Ketzij chik ri taq tz\'aqat</string>
+ <!-- Button to re-enable the extensions in the "crash" notification -->
+ <string name="mozac_feature_extensions_manager_notification_restart_button">Ketzij chik k\'amal</string>
<!-- Button in the add-ons manager that opens AMO in a tab -->
- <string name="mozac_feature_addons_find_more_addons_button_text">Kekanöx ch\'aqa\' chik taq tz\'aqat</string>
+ <string name="mozac_feature_addons_find_more_addons_button_text" moz:removedIn="126" tools:ignore="UnusedResources">Kekanöx ch\'aqa\' chik taq tz\'aqat</string>
+ <!-- Button in the extensions manager that opens AMO in a tab -->
+ <string name="mozac_feature_addons_find_more_extensions_button_text">Ke\'ilitäj ch\'aqa\' chik taq k\'amal</string>
<!-- The label of the allow button, this will be shown to the user when an add-on needs new permissions, with the button the user will indicate that they want to accept the new permissions and update the add-on-->
<string name="mozac_feature_addons_updater_notification_allow_button">Tiya\' q\'ij</string>
<!-- The label of the deny button on a notification, this will be shown to the user when an add-on needs new permissions. Indicates the user denies the new permissions and prevents the add-on from be updated-->
@@ -173,13 +183,15 @@
<!-- The content of the notification displayed when an add-on needs a new permission-->
<string name="mozac_feature_addons_updater_notification_content_singular">Najowäx jun k\'ak\'a\' ya\'oj q\'ij</string>
<!-- Name of the "notification channel" used for displaying a notification for updating an add-on. See https://developer.android.com/training/notify-user/channels -->
- <string name="mozac_feature_addons_updater_notification_channel">Kik\'exoj tz\'aqat</string>
+ <string name="mozac_feature_addons_updater_notification_channel" moz:removedIn="126" tools:ignore="UnusedResources">Kik\'exoj tz\'aqat</string>
+ <!-- Name of the "notification channel" used for displaying a notification for updating an extension. See https://developer.android.com/training/notify-user/channels -->
+ <string name="mozac_feature_addons_updater_notification_channel_2">Kik\'exoj k\'amal</string>
<!-- Name of the "notification channel" used for displaying a notification for new supported add-ons. See https://developer.android.com/training/notify-user/channels -->
- <string name="mozac_feature_addons_supported_checker_notification_channel">K\'amonel tojtob\'äl tz\'aqat</string>
+ <string name="mozac_feature_addons_supported_checker_notification_channel" tools:ignore="UnusedResources">K\'amonel tojtob\'äl tz\'aqat</string>
<!-- The tile of the notification, this will be shown to the user when one newly supported add-on is available.-->
- <string name="mozac_feature_addons_supported_checker_notification_title">K\'ak\'a\' tz\'aqat wachel</string>
+ <string name="mozac_feature_addons_supported_checker_notification_title" tools:ignore="UnusedResources">K\'ak\'a\' tz\'aqat wachel</string>
<!-- The tile of the notification, this will be shown to the user when more than one newly supported add-ons are available.-->
- <string name="mozac_feature_addons_supported_checker_notification_title_plural">K\'ak\'a\' taq tz\'aqat wachel</string>
+ <string name="mozac_feature_addons_supported_checker_notification_title_plural" tools:ignore="UnusedResources">K\'ak\'a\' taq tz\'aqat wachel</string>
<!-- The content of the notification, this will be shown to the user when one newly supported add-on is available. %1$s is the add-on name and %2$s is the app name (in most cases Firefox). -->
<string name="mozac_feature_addons_supported_checker_notification_content_one">Titz\'aqatisäx %1$s pa %2$s</string>
<!-- The content of the notification, this will be shown to the user when two newly supported add-ons are available. %1$s is the first add-on name. %2$s is the second add-on name. %3$s is the app name (in most cases Firefox). -->
@@ -187,13 +199,17 @@
<!-- The content of the notification, this will be shown to the user when more than two newly supported add-ons are available. %1$s is the app name (in most cases Firefox). -->
<string name="mozac_feature_addons_supported_checker_notification_content_more_than_two">Ketz\'aqatisäx pa %1$s</string>
<!-- This is the caption for not yet supported screen caption -->
- <string name="mozac_feature_addons_not_yet_supported_caption">Nib\'an k\'ak\'a\' chi re ri runa\'ob\'al rutz\'aqat Firefox. Re taq tz\'aqat re\' yekokisaj taq ruchi\' ri man kik\'amon ta ki\' rik\'in ri Firefox 75 &amp; ch\'aqa\' chik e nima\'q.</string>
+ <string name="mozac_feature_addons_not_yet_supported_caption" moz:removedIn="126" tools:ignore="UnusedResources">Nib\'an k\'ak\'a\' chi re ri runa\'ob\'al rutz\'aqat Firefox. Re taq tz\'aqat re\' yekokisaj taq ruchi\' ri man kik\'amon ta ki\' rik\'in ri Firefox 75 &amp; ch\'aqa\' chik e nima\'q.</string>
<!-- This is the caption for not yet supported screen caption -->
<string name="mozac_feature_addons_not_yet_supported_caption2">Wakami niqanük\' tob\'äl kichin nab\'ey cha\'oj taq K\'amal Echilab\'en.</string>
<!-- This is the caption for the add-on installation progress overlay -->
- <string name="mozac_add_on_install_progress_caption">Niqasäx chuqa\' ninik\'öx tz\'aqat…</string>
+ <string name="mozac_add_on_install_progress_caption" moz:removedIn="126" tools:ignore="UnusedResources">Niqasäx chuqa\' ninik\'öx tz\'aqat…</string>
+ <!-- This is the caption for the extension installation progress overlay -->
+ <string name="mozac_extension_install_progress_caption">Niqasäx chuqa\' ninik\'öx k\'amal…</string>
<!-- Error shown when something unexpected happened while trying to get the add-on list from the server -->
- <string name="mozac_feature_addons_failed_to_query_add_ons">¡Xsach toq xk\'utüx Tz\'aqat!</string>
+ <string name="mozac_feature_addons_failed_to_query_add_ons" moz:removedIn="126" tools:ignore="UnusedResources">¡Xsach toq xk\'utüx Tz\'aqat!</string>
+ <!-- Error shown when something unexpected happened while trying to get the extension list from the server -->
+ <string name="mozac_feature_addons_failed_to_query_extensions">¡Xsach toq xk\'utüx K\'amal!</string>
<!-- Error shown when unable to find a translation for an add-on field. %1$s is the locale of the user and %2$s is the default language of the add-on -->
<string name="mozac_feature_addons_failed_to_translate">Man xilitäj ta ri tzalq\'omanïk richin ri %1$s chuqa\' ni xa ta ri %2$s ch\'ab\'äl k\'o</string>
<!-- Text shown after successfully installed an add-on. %1$s is the add-on name. -->
@@ -201,13 +217,21 @@
<!-- Text shown after failed to install an add-on. %1$s is the add-on name. -->
<string name="mozac_feature_addons_failed_to_install">Xsach toq xyak ri %1$s</string>
<!-- Text shown after failing to install an add-on for which we don't have its name. -->
- <string name="mozac_feature_addons_failed_to_install_generic">Xsach toq niyak re tz\'aqat re\'.</string>
+ <string name="mozac_feature_addons_failed_to_install_generic" moz:removedIn="126" tools:ignore="UnusedResources">Xsach toq niyak re tz\'aqat re\'.</string>
+ <!-- Text shown after failing to install an extension for which we don't have its name. -->
+ <string name="mozac_feature_addons_extension_failed_to_install">Xsach toq niyak re k\'amal re\'.</string>
<!-- Text shown when attempting to install an add-on and a network error happened. -->
- <string name="mozac_feature_addons_failed_to_install_network_error">Man xqasäx ta re tz\'aqat re ruma man pa rub\'eyal taq ri rokem.</string>
+ <string name="mozac_feature_addons_failed_to_install_network_error" moz:removedIn="126" tools:ignore="UnusedResources">Man xqasäx ta re tz\'aqat re ruma man pa rub\'eyal taq ri rokem.</string>
+ <!-- Text shown when attempting to install an extension and a network error happened. -->
+ <string name="mozac_feature_addons_extension_failed_to_install_network_error">Man xqasäx ta re k\'amal re ruma man pa rub\'eyal taq ri rokem.</string>
<!-- Text shown when attempting to install an add-on and the downloaded file is corrupted. -->
- <string name="mozac_feature_addons_failed_to_install_corrupt_error">Man xyak ta kan re tz\'aqat xa ke xa man ütz ta.</string>
+ <string name="mozac_feature_addons_failed_to_install_corrupt_error" moz:removedIn="126" tools:ignore="UnusedResources">Man xyak ta kan re tz\'aqat xa ke xa man ütz ta.</string>
+ <!-- Text shown when attempting to install an extension and the downloaded file is corrupted. -->
+ <string name="mozac_feature_addons_extension_failed_to_install_corrupt_error">Man xyak ta kan re k\'amal xa ke xa man ütz ta.</string>
<!-- Text shown when attempting to install an add-on and an error occurred because the extension was not signed. -->
- <string name="mozac_feature_addons_failed_to_install_not_signed_error">Man xyak ta kan re jun rutz\'aqat re\' ruma chi man nik\'on ta.</string>
+ <string name="mozac_feature_addons_failed_to_install_not_signed_error" moz:removedIn="126" tools:ignore="UnusedResources">Man xyak ta kan re jun rutz\'aqat re\' ruma chi man nik\'on ta.</string>
+ <!-- Text shown when attempting to install an add-on and an error occurred because the extension was not signed. -->
+ <string name="mozac_feature_addons_extension_failed_to_install_not_signed_error">Man xyak ta kan re jun k\'amal re\' ruma chi man nik\'on ta.</string>
<!-- Text shown when attempting to install an add-on and an error occurred because the extension was incompatible. %1$s is the add-on name, %2$s is the app name and %3$s is the app version. -->
<string name="mozac_feature_addons_failed_to_install_incompatible_error">Man xyak ta ri %1$s ruma man nuk\'äm ta ri\' rik\'in %2$s %3$s.</string>
<!-- Text shown when attempting to install a blocklisted add-on. %1$s is the add-on name. -->
@@ -231,9 +255,13 @@
<!-- Label shown to indicate that the add-on was migrated from a previous version of the app. %1$s is the app name most of the case it will be Firefox. -->
<string name="mozac_feature_addons_migrated_from_a_previous_version_label" tools:ignore="UnusedResources">Re tz\'aqat re\' xk\'am pe pa jun kan ruwäch %1$s</string>
<!-- Text shown in not yet supported add-ons section in AddonsManagerAdapter. -->
- <string name="mozac_feature_addons_unsupported_caption">1 tz\'aqat</string>
+ <string name="mozac_feature_addons_unsupported_caption" moz:removedIn="126" tools:ignore="UnusedResources">1 tz\'aqat</string>
+ <!-- Text shown in not yet supported add-ons section. -->
+ <string name="mozac_feature_addons_unsupported_caption_2">1 k\'amal</string>
<!-- Text shown in not yet supported add-ons section in AddonsManagerAdapter - plural. %1$s is the number of unsupported add-ons -->
- <string name="mozac_feature_addons_unsupported_caption_plural">%1$s taq tz\'aqat</string>
+ <string name="mozac_feature_addons_unsupported_caption_plural" moz:removedIn="126" tools:ignore="UnusedResources">%1$s taq tz\'aqat</string>
+ <!-- Text shown in not yet supported add-ons section - plural. %1$s is the number of unsupported extensions. -->
+ <string name="mozac_feature_addons_unsupported_caption_plural_2">%1$s taq k\'amal</string>
<!-- Text link to a sumo page for learning more about unsupported add-ons. -->
<string name="mozac_feature_addons_unsupported_learn_more">Tetamäx ch\'aqa\' chik</string>
<!-- Displayed in the "Status" field for the updater when an add-on has been correctly updated. -->
diff --git a/mobile/android/android-components/components/feature/addons/src/main/res/values-eo/strings.xml b/mobile/android/android-components/components/feature/addons/src/main/res/values-eo/strings.xml
index 19c630e4a9..f61b58e7cd 100644
--- a/mobile/android/android-components/components/feature/addons/src/main/res/values-eo/strings.xml
+++ b/mobile/android/android-components/components/feature/addons/src/main/res/values-eo/strings.xml
@@ -87,13 +87,15 @@
<!-- The rating of the add-on. -->
<string name="mozac_feature_addons_rating">Taksado</string>
<!-- A link that points to the detail page of the add-on. -->
- <string name="mozac_feature_addons_more_info_link">Pli da informo pri tiu ĉi aldonaĵo</string>
+ <string name="mozac_feature_addons_more_info_link" moz:removedIn="126" tools:ignore="UnusedResources">Pli da informo pri tiu ĉi aldonaĵo</string>
+ <!-- A link that points to the detail page of the extension. -->
+ <string name="mozac_feature_addons_more_info_link_2">Pli da informo pri tiu ĉi etendaĵo</string>
<!-- The settings of the add-on. -->
<string name="mozac_feature_addons_settings">Agordoj</string>
<!-- Indicates the add-on is enabled. -->
<string name="mozac_feature_addons_settings_on">Ŝaltita</string>
<!-- Indicates the add-on is disabled. -->
- <string name="mozac_feature_addons_settings_off">Malŝaltita</string>
+ <string name="mozac_feature_addons_settings_off" moz:removedIn="125" tools:ignore="UnusedResources">Malŝaltita</string>
<!-- Indicates the add-on is allowed in private browsing mode. -->
<string name="mozac_feature_addons_settings_allow_in_private_browsing">Permesi en privata retumo</string>
<!-- Indicates the add-on is allowed in private browsing mode. -->
@@ -103,7 +105,7 @@
<!-- Indicates the add-on is enabled. -->
<string name="mozac_feature_addons_enabled">Aktiva</string>
<!-- Indicates the add-on is disabled. -->
- <string name="mozac_feature_addons_disabled">Malaktiva</string>
+ <string name="mozac_feature_addons_disabled" moz:removedIn="125" tools:ignore="UnusedResources">Malaktiva</string>
<!-- This is displayed in a page where the user can see the installed and recommended(not installed yet) add-ons, this string indicates the installed section. -->
<string name="mozac_feature_addons_installed_section">Instalita</string>
<!-- This is displayed in a page where the user can see the installed and recommended(not installed yet) add-ons, this string indicates the recommended section. -->
@@ -155,13 +157,21 @@
<!-- Label for add-ons sub menu item for add-ons manager-->
<string name="mozac_feature_addons_addons_manager">Administrilo de aldonaĵoj</string>
<!-- The title of the "crash" notification in the add-ons manager -->
- <string name="mozac_feature_addons_manager_notification_title_text">La aldonaĵoj estas provizore malaktivigitaj</string>
+ <string name="mozac_feature_addons_manager_notification_title_text" moz:removedIn="126" tools:ignore="UnusedResources">La aldonaĵoj estas provizore malaktivigitaj</string>
+ <!-- The title of the "crash" notification in the extensions manager -->
+ <string name="mozac_feature_extensions_manager_notification_title_text">La etendaĵoj estas provizore malaktivigitaj</string>
<!-- The content of the "crash" notification in the add-ons manager -->
- <string name="mozac_feature_addons_manager_notification_content_text">Unu aŭ pli da aldonaĵoj ĉesis funkcii, kaj tio igas vian sistemon nestabila.</string>
+ <string name="mozac_feature_addons_manager_notification_content_text" moz:removedIn="126" tools:ignore="UnusedResources">Unu aŭ pli da aldonaĵoj ĉesis funkcii, kaj tio igas vian sistemon nestabila.</string>
+ <!-- The content of the "crash" notification in the extensions manager -->
+ <string name="mozac_feature_extensions_manager_notification_content_text">Unu aŭ pli da etendaĵoj ĉesis funkcii, kaj tio igas vian sistemon nestabila.</string>
<!-- Button to re-enable the add-ons in the "crash" notification -->
- <string name="mozac_feature_addons_manager_notification_restart_button">Restartigi aldonaĵojn</string>
+ <string name="mozac_feature_addons_manager_notification_restart_button" moz:removedIn="126" tools:ignore="UnusedResources">Restartigi aldonaĵojn</string>
+ <!-- Button to re-enable the extensions in the "crash" notification -->
+ <string name="mozac_feature_extensions_manager_notification_restart_button">Restartigi etendaĵojn</string>
<!-- Button in the add-ons manager that opens AMO in a tab -->
- <string name="mozac_feature_addons_find_more_addons_button_text">Serĉi pli da aldonaĵoj</string>
+ <string name="mozac_feature_addons_find_more_addons_button_text" moz:removedIn="126" tools:ignore="UnusedResources">Serĉi pli da aldonaĵoj</string>
+ <!-- Button in the extensions manager that opens AMO in a tab -->
+ <string name="mozac_feature_addons_find_more_extensions_button_text">Serĉi pli da etendaĵoj</string>
<!-- The label of the allow button, this will be shown to the user when an add-on needs new permissions, with the button the user will indicate that they want to accept the new permissions and update the add-on-->
<string name="mozac_feature_addons_updater_notification_allow_button">Permesi</string>
<!-- The label of the deny button on a notification, this will be shown to the user when an add-on needs new permissions. Indicates the user denies the new permissions and prevents the add-on from be updated-->
@@ -173,13 +183,15 @@
<!-- The content of the notification displayed when an add-on needs a new permission-->
<string name="mozac_feature_addons_updater_notification_content_singular">Nova permeso postulata</string>
<!-- Name of the "notification channel" used for displaying a notification for updating an add-on. See https://developer.android.com/training/notify-user/channels -->
- <string name="mozac_feature_addons_updater_notification_channel">Ĝisdatigoj de aldonaĵoj</string>
+ <string name="mozac_feature_addons_updater_notification_channel" moz:removedIn="126" tools:ignore="UnusedResources">Ĝisdatigoj de aldonaĵoj</string>
+ <!-- Name of the "notification channel" used for displaying a notification for updating an extension. See https://developer.android.com/training/notify-user/channels -->
+ <string name="mozac_feature_addons_updater_notification_channel_2">Ĝisdatigoj por etendaĵoj</string>
<!-- Name of the "notification channel" used for displaying a notification for new supported add-ons. See https://developer.android.com/training/notify-user/channels -->
- <string name="mozac_feature_addons_supported_checker_notification_channel">Kontrolo de subtenataj aldonaĵoj</string>
+ <string name="mozac_feature_addons_supported_checker_notification_channel" tools:ignore="UnusedResources">Kontrolo de subtenataj aldonaĵoj</string>
<!-- The tile of the notification, this will be shown to the user when one newly supported add-on is available.-->
- <string name="mozac_feature_addons_supported_checker_notification_title">Nova aldonaĵo disponebla</string>
+ <string name="mozac_feature_addons_supported_checker_notification_title" tools:ignore="UnusedResources">Nova aldonaĵo disponebla</string>
<!-- The tile of the notification, this will be shown to the user when more than one newly supported add-ons are available.-->
- <string name="mozac_feature_addons_supported_checker_notification_title_plural">Novaj aldonaĵoj disponeblaj</string>
+ <string name="mozac_feature_addons_supported_checker_notification_title_plural" tools:ignore="UnusedResources">Novaj aldonaĵoj disponeblaj</string>
<!-- The content of the notification, this will be shown to the user when one newly supported add-on is available. %1$s is the add-on name and %2$s is the app name (in most cases Firefox). -->
<string name="mozac_feature_addons_supported_checker_notification_content_one">Aldoni %1$s al %2$s</string>
<!-- The content of the notification, this will be shown to the user when two newly supported add-ons are available. %1$s is the first add-on name. %2$s is the second add-on name. %3$s is the app name (in most cases Firefox). -->
@@ -187,13 +199,17 @@
<!-- The content of the notification, this will be shown to the user when more than two newly supported add-ons are available. %1$s is the app name (in most cases Firefox). -->
<string name="mozac_feature_addons_supported_checker_notification_content_more_than_two">Aldoni ilin al %1$s</string>
<!-- This is the caption for not yet supported screen caption -->
- <string name="mozac_feature_addons_not_yet_supported_caption">La teknologio de aldonaĵoj de Firefox moderniĝas. Tiuj ĉi aldonaĵoj uzas teknologiojn kiuj ne kongruas kun Firefox 75 kaj ĝiaj postaj versioj.</string>
+ <string name="mozac_feature_addons_not_yet_supported_caption" moz:removedIn="126" tools:ignore="UnusedResources">La teknologio de aldonaĵoj de Firefox moderniĝas. Tiuj ĉi aldonaĵoj uzas teknologiojn kiuj ne kongruas kun Firefox 75 kaj ĝiaj postaj versioj.</string>
<!-- This is the caption for not yet supported screen caption -->
<string name="mozac_feature_addons_not_yet_supported_caption2">Ni nun kreas la unuan liston kun elektitaj rekomenditaj etendaĵoj.</string>
<!-- This is the caption for the add-on installation progress overlay -->
- <string name="mozac_add_on_install_progress_caption">Aldonaĵo elŝutata kaj kontrolata…</string>
+ <string name="mozac_add_on_install_progress_caption" moz:removedIn="126" tools:ignore="UnusedResources">Aldonaĵo elŝutata kaj kontrolata…</string>
+ <!-- This is the caption for the extension installation progress overlay -->
+ <string name="mozac_extension_install_progress_caption">Etendaĵo elŝutata kaj kontrolata…</string>
<!-- Error shown when something unexpected happened while trying to get the add-on list from the server -->
- <string name="mozac_feature_addons_failed_to_query_add_ons">Ne eblis akiri la liston de aldonaĵoj!</string>
+ <string name="mozac_feature_addons_failed_to_query_add_ons" moz:removedIn="126" tools:ignore="UnusedResources">Ne eblis akiri la liston de aldonaĵoj!</string>
+ <!-- Error shown when something unexpected happened while trying to get the extension list from the server -->
+ <string name="mozac_feature_addons_failed_to_query_extensions">Ne eblis akiri la liston de etendaĵoj!</string>
<!-- Error shown when unable to find a translation for an add-on field. %1$s is the locale of the user and %2$s is the default language of the add-on -->
<string name="mozac_feature_addons_failed_to_translate">Traduko netrovita, nek por la lokaĵaro %1$s nek por la norma lingvo %2$s</string>
<!-- Text shown after successfully installed an add-on. %1$s is the add-on name. -->
@@ -201,13 +217,21 @@
<!-- Text shown after failed to install an add-on. %1$s is the add-on name. -->
<string name="mozac_feature_addons_failed_to_install">Malsukcesa instalo de %1$s</string>
<!-- Text shown after failing to install an add-on for which we don't have its name. -->
- <string name="mozac_feature_addons_failed_to_install_generic">Malsukcesa instalo de tiu ĉi aldonaĵo.</string>
+ <string name="mozac_feature_addons_failed_to_install_generic" moz:removedIn="126" tools:ignore="UnusedResources">Malsukcesa instalo de tiu ĉi aldonaĵo.</string>
+ <!-- Text shown after failing to install an extension for which we don't have its name. -->
+ <string name="mozac_feature_addons_extension_failed_to_install">Malsukcesa instalo de tiu ĉi etendaĵo.</string>
<!-- Text shown when attempting to install an add-on and a network error happened. -->
- <string name="mozac_feature_addons_failed_to_install_network_error">La aldonaĵo ne povis esti elŝutita pro eraro en la konekto.</string>
+ <string name="mozac_feature_addons_failed_to_install_network_error" moz:removedIn="126" tools:ignore="UnusedResources">La aldonaĵo ne povis esti elŝutita pro eraro en la konekto.</string>
+ <!-- Text shown when attempting to install an extension and a network error happened. -->
+ <string name="mozac_feature_addons_extension_failed_to_install_network_error">La etendaĵo ne povis esti elŝutita pro eraro en la konekto.</string>
<!-- Text shown when attempting to install an add-on and the downloaded file is corrupted. -->
- <string name="mozac_feature_addons_failed_to_install_corrupt_error">Tiu ĉi aldonaĵo ne povis esti instalita ĉar ĝi aspektas difektite.</string>
+ <string name="mozac_feature_addons_failed_to_install_corrupt_error" moz:removedIn="126" tools:ignore="UnusedResources">Tiu ĉi aldonaĵo ne povis esti instalita ĉar ĝi aspektas difektite.</string>
+ <!-- Text shown when attempting to install an extension and the downloaded file is corrupted. -->
+ <string name="mozac_feature_addons_extension_failed_to_install_corrupt_error">Tiu ĉi etendaĵo ne povis esti instalita ĉar ĝi aspektas difektite.</string>
<!-- Text shown when attempting to install an add-on and an error occurred because the extension was not signed. -->
- <string name="mozac_feature_addons_failed_to_install_not_signed_error">Tiu ĉi aldonaĵo ne povis esti instalita ĉar ĝi ne estas kontrolita.</string>
+ <string name="mozac_feature_addons_failed_to_install_not_signed_error" moz:removedIn="126" tools:ignore="UnusedResources">Tiu ĉi aldonaĵo ne povis esti instalita ĉar ĝi ne estas kontrolita.</string>
+ <!-- Text shown when attempting to install an add-on and an error occurred because the extension was not signed. -->
+ <string name="mozac_feature_addons_extension_failed_to_install_not_signed_error">Tiu ĉi etendaĵo ne povis esti instalita ĉar ĝi ne estis kontrolita.</string>
<!-- Text shown when attempting to install an add-on and an error occurred because the extension was incompatible. %1$s is the add-on name, %2$s is the app name and %3$s is the app version. -->
<string name="mozac_feature_addons_failed_to_install_incompatible_error">%1$s ne povi esti instalita ĉar ĝi ne kongruas kun %2$s %3$s.</string>
<!-- Text shown when attempting to install a blocklisted add-on. %1$s is the add-on name. -->
@@ -231,9 +255,13 @@
<!-- Label shown to indicate that the add-on was migrated from a previous version of the app. %1$s is the app name most of the case it will be Firefox. -->
<string name="mozac_feature_addons_migrated_from_a_previous_version_label" tools:ignore="UnusedResources">Tiu ĉi aldonaĵo migris el antaŭa versio de %1$s</string>
<!-- Text shown in not yet supported add-ons section in AddonsManagerAdapter. -->
- <string name="mozac_feature_addons_unsupported_caption">1 aldonaĵo</string>
+ <string name="mozac_feature_addons_unsupported_caption" moz:removedIn="126" tools:ignore="UnusedResources">1 aldonaĵo</string>
+ <!-- Text shown in not yet supported add-ons section. -->
+ <string name="mozac_feature_addons_unsupported_caption_2">1 etendaĵo</string>
<!-- Text shown in not yet supported add-ons section in AddonsManagerAdapter - plural. %1$s is the number of unsupported add-ons -->
- <string name="mozac_feature_addons_unsupported_caption_plural">%1$s aldonaĵoj</string>
+ <string name="mozac_feature_addons_unsupported_caption_plural" moz:removedIn="126" tools:ignore="UnusedResources">%1$s aldonaĵoj</string>
+ <!-- Text shown in not yet supported add-ons section - plural. %1$s is the number of unsupported extensions. -->
+ <string name="mozac_feature_addons_unsupported_caption_plural_2">%1$s etendaĵoj</string>
<!-- Text link to a sumo page for learning more about unsupported add-ons. -->
<string name="mozac_feature_addons_unsupported_learn_more">Pli da informo</string>
<!-- Displayed in the "Status" field for the updater when an add-on has been correctly updated. -->
diff --git a/mobile/android/android-components/components/feature/addons/src/main/res/values-eu/strings.xml b/mobile/android/android-components/components/feature/addons/src/main/res/values-eu/strings.xml
index 44fdf12323..f7af45b7ea 100644
--- a/mobile/android/android-components/components/feature/addons/src/main/res/values-eu/strings.xml
+++ b/mobile/android/android-components/components/feature/addons/src/main/res/values-eu/strings.xml
@@ -87,13 +87,15 @@
<!-- The rating of the add-on. -->
<string name="mozac_feature_addons_rating">Puntuazioa</string>
<!-- A link that points to the detail page of the add-on. -->
- <string name="mozac_feature_addons_more_info_link">Gehiago gehigarri honi buruz</string>
+ <string name="mozac_feature_addons_more_info_link" moz:removedIn="126" tools:ignore="UnusedResources">Gehiago gehigarri honi buruz</string>
+ <!-- A link that points to the detail page of the extension. -->
+ <string name="mozac_feature_addons_more_info_link_2">Gehiago hedapen honi buruz</string>
<!-- The settings of the add-on. -->
<string name="mozac_feature_addons_settings">Ezarpenak</string>
<!-- Indicates the add-on is enabled. -->
<string name="mozac_feature_addons_settings_on">Aktibatuta</string>
<!-- Indicates the add-on is disabled. -->
- <string name="mozac_feature_addons_settings_off">Desaktibatuta</string>
+ <string name="mozac_feature_addons_settings_off" moz:removedIn="125" tools:ignore="UnusedResources">Desaktibatuta</string>
<!-- Indicates the add-on is allowed in private browsing mode. -->
<string name="mozac_feature_addons_settings_allow_in_private_browsing">Baimendu nabigatze pribatuan</string>
<!-- Indicates the add-on is allowed in private browsing mode. -->
@@ -103,7 +105,7 @@
<!-- Indicates the add-on is enabled. -->
<string name="mozac_feature_addons_enabled">Gaituta</string>
<!-- Indicates the add-on is disabled. -->
- <string name="mozac_feature_addons_disabled">Desgaituta</string>
+ <string name="mozac_feature_addons_disabled" moz:removedIn="125" tools:ignore="UnusedResources">Desgaituta</string>
<!-- This is displayed in a page where the user can see the installed and recommended(not installed yet) add-ons, this string indicates the installed section. -->
<string name="mozac_feature_addons_installed_section">Instalatuta</string>
<!-- This is displayed in a page where the user can see the installed and recommended(not installed yet) add-ons, this string indicates the recommended section. -->
@@ -155,13 +157,21 @@
<!-- Label for add-ons sub menu item for add-ons manager-->
<string name="mozac_feature_addons_addons_manager">Gehigarrien kudeatzailea</string>
<!-- The title of the "crash" notification in the add-ons manager -->
- <string name="mozac_feature_addons_manager_notification_title_text">Gehigarriak aldi baterako desgaitu dira</string>
+ <string name="mozac_feature_addons_manager_notification_title_text" moz:removedIn="126" tools:ignore="UnusedResources">Gehigarriak aldi baterako desgaitu dira</string>
+ <!-- The title of the "crash" notification in the extensions manager -->
+ <string name="mozac_feature_extensions_manager_notification_title_text">Hedapenak aldi baterako desgaitu dira</string>
<!-- The content of the "crash" notification in the add-ons manager -->
- <string name="mozac_feature_addons_manager_notification_content_text">Gehigarri bat edo gehiago matxuratu egin dira, zure sistema desegonkortuz.</string>
+ <string name="mozac_feature_addons_manager_notification_content_text" moz:removedIn="126" tools:ignore="UnusedResources">Gehigarri bat edo gehiago matxuratu egin dira, zure sistema desegonkortuz.</string>
+ <!-- The content of the "crash" notification in the extensions manager -->
+ <string name="mozac_feature_extensions_manager_notification_content_text">Hedapen bat edo gehiago matxuratu egin dira, zure sistema desegonkortuz.</string>
<!-- Button to re-enable the add-ons in the "crash" notification -->
- <string name="mozac_feature_addons_manager_notification_restart_button">Berrabiarazi gehigarriak</string>
+ <string name="mozac_feature_addons_manager_notification_restart_button" moz:removedIn="126" tools:ignore="UnusedResources">Berrabiarazi gehigarriak</string>
+ <!-- Button to re-enable the extensions in the "crash" notification -->
+ <string name="mozac_feature_extensions_manager_notification_restart_button">Berrabiarazi hedapenak</string>
<!-- Button in the add-ons manager that opens AMO in a tab -->
- <string name="mozac_feature_addons_find_more_addons_button_text">Bilatu gehigarri gehiago</string>
+ <string name="mozac_feature_addons_find_more_addons_button_text" moz:removedIn="126" tools:ignore="UnusedResources">Bilatu gehigarri gehiago</string>
+ <!-- Button in the extensions manager that opens AMO in a tab -->
+ <string name="mozac_feature_addons_find_more_extensions_button_text">Bilatu hedapen gehiago</string>
<!-- The label of the allow button, this will be shown to the user when an add-on needs new permissions, with the button the user will indicate that they want to accept the new permissions and update the add-on-->
<string name="mozac_feature_addons_updater_notification_allow_button">Baimendu</string>
<!-- The label of the deny button on a notification, this will be shown to the user when an add-on needs new permissions. Indicates the user denies the new permissions and prevents the add-on from be updated-->
@@ -173,13 +183,15 @@
<!-- The content of the notification displayed when an add-on needs a new permission-->
<string name="mozac_feature_addons_updater_notification_content_singular">Baimen berri bat behar da</string>
<!-- Name of the "notification channel" used for displaying a notification for updating an add-on. See https://developer.android.com/training/notify-user/channels -->
- <string name="mozac_feature_addons_updater_notification_channel">Gehigarrien eguneraketak</string>
+ <string name="mozac_feature_addons_updater_notification_channel" moz:removedIn="126" tools:ignore="UnusedResources">Gehigarrien eguneraketak</string>
+ <!-- Name of the "notification channel" used for displaying a notification for updating an extension. See https://developer.android.com/training/notify-user/channels -->
+ <string name="mozac_feature_addons_updater_notification_channel_2">Hedapenen eguneraketak</string>
<!-- Name of the "notification channel" used for displaying a notification for new supported add-ons. See https://developer.android.com/training/notify-user/channels -->
- <string name="mozac_feature_addons_supported_checker_notification_channel">Onartutako gehigarrien egiaztatzailea</string>
+ <string name="mozac_feature_addons_supported_checker_notification_channel" tools:ignore="UnusedResources">Onartutako gehigarrien egiaztatzailea</string>
<!-- The tile of the notification, this will be shown to the user when one newly supported add-on is available.-->
- <string name="mozac_feature_addons_supported_checker_notification_title">Gehigarri berria erabilgarri</string>
+ <string name="mozac_feature_addons_supported_checker_notification_title" tools:ignore="UnusedResources">Gehigarri berria erabilgarri</string>
<!-- The tile of the notification, this will be shown to the user when more than one newly supported add-ons are available.-->
- <string name="mozac_feature_addons_supported_checker_notification_title_plural">Gehigarri berriak erabilgarri</string>
+ <string name="mozac_feature_addons_supported_checker_notification_title_plural" tools:ignore="UnusedResources">Gehigarri berriak erabilgarri</string>
<!-- The content of the notification, this will be shown to the user when one newly supported add-on is available. %1$s is the add-on name and %2$s is the app name (in most cases Firefox). -->
<string name="mozac_feature_addons_supported_checker_notification_content_one">Gehitu %1$s %2$s(e)ra</string>
<!-- The content of the notification, this will be shown to the user when two newly supported add-ons are available. %1$s is the first add-on name. %2$s is the second add-on name. %3$s is the app name (in most cases Firefox). -->
@@ -187,13 +199,17 @@
<!-- The content of the notification, this will be shown to the user when more than two newly supported add-ons are available. %1$s is the app name (in most cases Firefox). -->
<string name="mozac_feature_addons_supported_checker_notification_content_more_than_two">Gehitu hauek %1$s(e)ra</string>
<!-- This is the caption for not yet supported screen caption -->
- <string name="mozac_feature_addons_not_yet_supported_caption">Firefoxen gehigarrien teknologia modernizatzen ari da. Ondorengo gehigarriek Firefox 75 eta berriagoekin bateragarriak ez diren framework-ak erabiltzen dituzte.</string>
+ <string name="mozac_feature_addons_not_yet_supported_caption" moz:removedIn="126" tools:ignore="UnusedResources">Firefoxen gehigarrien teknologia modernizatzen ari da. Ondorengo gehigarriek Firefox 75 eta berriagoekin bateragarriak ez diren framework-ak erabiltzen dituzte.</string>
<!-- This is the caption for not yet supported screen caption -->
<string name="mozac_feature_addons_not_yet_supported_caption2">Gomendatutako hedapenen hasierako hautapena emateko euskarria eraikitzen ari gara une honetan.</string>
<!-- This is the caption for the add-on installation progress overlay -->
- <string name="mozac_add_on_install_progress_caption">Gehigarria deskargatzen eta egiaztatzen…</string>
+ <string name="mozac_add_on_install_progress_caption" moz:removedIn="126" tools:ignore="UnusedResources">Gehigarria deskargatzen eta egiaztatzen…</string>
+ <!-- This is the caption for the extension installation progress overlay -->
+ <string name="mozac_extension_install_progress_caption">Hedapena deskargatzen eta egiaztatzen…</string>
<!-- Error shown when something unexpected happened while trying to get the add-on list from the server -->
- <string name="mozac_feature_addons_failed_to_query_add_ons">Ezin izan dira gehigarriak kontsultatu!</string>
+ <string name="mozac_feature_addons_failed_to_query_add_ons" moz:removedIn="126" tools:ignore="UnusedResources">Ezin izan dira gehigarriak kontsultatu!</string>
+ <!-- Error shown when something unexpected happened while trying to get the extension list from the server -->
+ <string name="mozac_feature_addons_failed_to_query_extensions">Ezin izan dira hedapenak kontsultatu!</string>
<!-- Error shown when unable to find a translation for an add-on field. %1$s is the locale of the user and %2$s is the default language of the add-on -->
<string name="mozac_feature_addons_failed_to_translate">Ez da itzulpenik aurkitu, ez %1$s hizkuntzarentzat ez eta %2$s hizkuntza lehenetsiarentzat</string>
<!-- Text shown after successfully installed an add-on. %1$s is the add-on name. -->
@@ -201,13 +217,21 @@
<!-- Text shown after failed to install an add-on. %1$s is the add-on name. -->
<string name="mozac_feature_addons_failed_to_install">Ezin izan da %1$s instalatu</string>
<!-- Text shown after failing to install an add-on for which we don't have its name. -->
- <string name="mozac_feature_addons_failed_to_install_generic">Ezin izan da gehigarri hau instalatu.</string>
+ <string name="mozac_feature_addons_failed_to_install_generic" moz:removedIn="126" tools:ignore="UnusedResources">Ezin izan da gehigarri hau instalatu.</string>
+ <!-- Text shown after failing to install an extension for which we don't have its name. -->
+ <string name="mozac_feature_addons_extension_failed_to_install">Ezin izan da hedapen hau instalatu.</string>
<!-- Text shown when attempting to install an add-on and a network error happened. -->
- <string name="mozac_feature_addons_failed_to_install_network_error">Ezin izan da gehigarri hau deskargatu konexio-akats bat dela-eta.</string>
+ <string name="mozac_feature_addons_failed_to_install_network_error" moz:removedIn="126" tools:ignore="UnusedResources">Ezin izan da gehigarri hau deskargatu konexio-akats bat dela-eta.</string>
+ <!-- Text shown when attempting to install an extension and a network error happened. -->
+ <string name="mozac_feature_addons_extension_failed_to_install_network_error">Ezin izan da hedapen hau deskargatu konexio-akats bat dela-eta.</string>
<!-- Text shown when attempting to install an add-on and the downloaded file is corrupted. -->
- <string name="mozac_feature_addons_failed_to_install_corrupt_error">Ezin izan da gehigarri hau instalatu hondatuta dagoela dirudielako.</string>
+ <string name="mozac_feature_addons_failed_to_install_corrupt_error" moz:removedIn="126" tools:ignore="UnusedResources">Ezin izan da gehigarri hau instalatu hondatuta dagoela dirudielako.</string>
+ <!-- Text shown when attempting to install an extension and the downloaded file is corrupted. -->
+ <string name="mozac_feature_addons_extension_failed_to_install_corrupt_error">Ezin izan da hedapen hau instalatu hondatuta dagoela dirudielako.</string>
<!-- Text shown when attempting to install an add-on and an error occurred because the extension was not signed. -->
- <string name="mozac_feature_addons_failed_to_install_not_signed_error">Ezin izan da gehigarri hau instalatu egiaztatu gabea delako.</string>
+ <string name="mozac_feature_addons_failed_to_install_not_signed_error" moz:removedIn="126" tools:ignore="UnusedResources">Ezin izan da gehigarri hau instalatu egiaztatu gabea delako.</string>
+ <!-- Text shown when attempting to install an add-on and an error occurred because the extension was not signed. -->
+ <string name="mozac_feature_addons_extension_failed_to_install_not_signed_error">Ezin izan da hedapen hau instalatu egiaztatu gabea delako.</string>
<!-- Text shown when attempting to install an add-on and an error occurred because the extension was incompatible. %1$s is the add-on name, %2$s is the app name and %3$s is the app version. -->
<string name="mozac_feature_addons_failed_to_install_incompatible_error">Ezin da %1$s instalatu ez delako %2$s %3$s bertsioarekin bateragarria.</string>
<!-- Text shown when attempting to install a blocklisted add-on. %1$s is the add-on name. -->
@@ -231,9 +255,13 @@
<!-- Label shown to indicate that the add-on was migrated from a previous version of the app. %1$s is the app name most of the case it will be Firefox. -->
<string name="mozac_feature_addons_migrated_from_a_previous_version_label" tools:ignore="UnusedResources">Gehigarri hau %1$s(r)en aurreko bertsio batetik migratu da</string>
<!-- Text shown in not yet supported add-ons section in AddonsManagerAdapter. -->
- <string name="mozac_feature_addons_unsupported_caption">Gehigarri 1</string>
+ <string name="mozac_feature_addons_unsupported_caption" moz:removedIn="126" tools:ignore="UnusedResources">Gehigarri 1</string>
+ <!-- Text shown in not yet supported add-ons section. -->
+ <string name="mozac_feature_addons_unsupported_caption_2">Hedapen bat</string>
<!-- Text shown in not yet supported add-ons section in AddonsManagerAdapter - plural. %1$s is the number of unsupported add-ons -->
- <string name="mozac_feature_addons_unsupported_caption_plural">%1$s gehigarri</string>
+ <string name="mozac_feature_addons_unsupported_caption_plural" moz:removedIn="126" tools:ignore="UnusedResources">%1$s gehigarri</string>
+ <!-- Text shown in not yet supported add-ons section - plural. %1$s is the number of unsupported extensions. -->
+ <string name="mozac_feature_addons_unsupported_caption_plural_2">%1$s hedapen</string>
<!-- Text link to a sumo page for learning more about unsupported add-ons. -->
<string name="mozac_feature_addons_unsupported_learn_more">Argibide gehiago</string>
<!-- Displayed in the "Status" field for the updater when an add-on has been correctly updated. -->
diff --git a/mobile/android/android-components/components/feature/addons/src/main/res/values-it/strings.xml b/mobile/android/android-components/components/feature/addons/src/main/res/values-it/strings.xml
index 2c0f38c37d..e6e37d0846 100644
--- a/mobile/android/android-components/components/feature/addons/src/main/res/values-it/strings.xml
+++ b/mobile/android/android-components/components/feature/addons/src/main/res/values-it/strings.xml
@@ -76,8 +76,6 @@
<string name="mozac_feature_addons_version">Versione</string>
<!-- The author of an add-on. -->
<string name="mozac_feature_addons_author">Autore</string>
- <!-- The authors of an add-on. -->
- <string name="mozac_feature_addons_authors" moz:removedIn="123" tools:ignore="UnusedResources">Autori</string>
<!-- The last date that the add-on was updated. -->
<string name="mozac_feature_addons_last_updated">Ultimo aggiornamento</string>
<!-- The developer website (Homepage) of the add-on. -->
@@ -94,8 +92,6 @@
<string name="mozac_feature_addons_settings">Impostazioni</string>
<!-- Indicates the add-on is enabled. -->
<string name="mozac_feature_addons_settings_on">Attiva</string>
- <!-- Indicates the add-on is disabled. -->
- <string name="mozac_feature_addons_settings_off" moz:removedIn="125" tools:ignore="UnusedResources">Disattivata</string>
<!-- Indicates the add-on is allowed in private browsing mode. -->
<string name="mozac_feature_addons_settings_allow_in_private_browsing">Consenti in navigazione anonima</string>
<!-- Indicates the add-on is allowed in private browsing mode. -->
@@ -103,13 +99,11 @@
<!-- This is displayed when the add-on is not allowed to run in private browsing. -->
<string name="mozac_feature_addons_not_allowed_in_private_browsing">Disattivata in finestre anonime</string>
<!-- Indicates the add-on is enabled. -->
- <string name="mozac_feature_addons_enabled">Attivi</string>
- <!-- Indicates the add-on is disabled. -->
- <string name="mozac_feature_addons_disabled" moz:removedIn="125" tools:ignore="UnusedResources">Disattivato</string>
+ <string name="mozac_feature_addons_enabled">Attive</string>
<!-- This is displayed in a page where the user can see the installed and recommended(not installed yet) add-ons, this string indicates the installed section. -->
- <string name="mozac_feature_addons_installed_section">Installata</string>
+ <string name="mozac_feature_addons_installed_section">Installate</string>
<!-- This is displayed in a page where the user can see the installed and recommended(not installed yet) add-ons, this string indicates the recommended section. -->
- <string name="mozac_feature_addons_recommended_section">Consigliati</string>
+ <string name="mozac_feature_addons_recommended_section">Consigliate</string>
<!-- This is displayed in a page where the user can see the installed and recommended(not installed yet) add-ons, this string indicates the not yet supported section. -->
<string name="mozac_feature_addons_unsupported_section">Non ancora supportato</string>
<!-- This is displayed in a page where the user can see the installed and recommended(not installed yet) add-ons, this string indicates the not yet available section. -->
@@ -140,16 +134,12 @@
<string name="mozac_feature_addons_permissions_dialog_deny">Nega</string>
<!-- This is a button to cancel the add-on installation . -->
<string name="mozac_feature_addons_permissions_dialog_cancel">Annulla</string>
- <!-- Accessibility content description to install add-on button. -->
- <string name="mozac_feature_addons_install_addon_content_description" tools:ignore="UnusedResources" moz:removedIn="124">Installa componente aggiuntivo</string>
<!-- Accessibility content description to install add-on button. %1$s is the add-on name. -->
<string name="mozac_feature_addons_install_addon_content_description_2">Installa %1$s</string>
<!-- This is the label of a button to cancel an ongoing add-on installation. -->
<string name="mozac_feature_addons_install_addon_dialog_cancel">Annulla</string>
<!-- Indicates how many users have rated an add-on. %1$s will be replaced with number of reviews -->
<string name="mozac_feature_addons_user_rating_count_2">Recensioni: %1$s</string>
- <!-- Accessibility content description for the amount of stars that add-on has, where %1$.02f will be the amount of stars and / separator and 5 the maximum number of stars e.g (2/5, 4.5/5 or 5/5) . -->
- <string name="mozac_feature_addons_rating_content_description" moz:removedIn="124" tools:ignore="UnusedResources">%1$.02f/5</string>
<!-- Accessibility content description for the amount of stars that add-on has, where %1$.02f will be the amount of stars. -->
<string name="mozac_feature_addons_rating_content_description_2">Valutazione: %1$.02f su 5</string>
<!-- This is the title of page where all the add-ons are listed-->
@@ -278,13 +268,9 @@
<string name="mozac_feature_addons_updater_dialog_status">Stato:</string>
<!-- Text shown in the dialog when add-on installation is completed. %1$s is the add-on name. %2$s is the app name. -->
<string name="mozac_feature_addons_installed_dialog_title">%1$s è stato aggiunto a %2$s</string>
- <!-- Text shown in the dialog when add-on installation is completed. -->
- <string name="mozac_feature_addons_installed_dialog_description" moz:removedIn="124" tools:ignore="UnusedResources">Apri nel menu</string>
<!-- Text shown in the dialog when add-on installation is completed. %1$s is the add-on name. %2$s is the app name. -->
<string name="mozac_feature_addons_installed_dialog_description_2">Accedi a %1$s dal menu di %2$s.</string>
<!-- Confirmation button text for the dialog when add-on installation is completed. -->
- <string name="mozac_feature_addons_installed_dialog_okay_button" moz:removedIn="124" tools:ignore="UnusedResources">OK</string>
- <!-- Confirmation button text for the dialog when add-on installation is completed. -->
<string name="mozac_feature_addons_installed_dialog_okay_button_2">OK</string>
<!-- "Learn more" link displayed below an add-on status message. -->
<string name="mozac_feature_addons_status_learn_more">Ulteriori informazioni</string>
diff --git a/mobile/android/android-components/components/feature/addons/src/main/res/values-kab/strings.xml b/mobile/android/android-components/components/feature/addons/src/main/res/values-kab/strings.xml
index d154ecb99c..20100e7ce9 100644
--- a/mobile/android/android-components/components/feature/addons/src/main/res/values-kab/strings.xml
+++ b/mobile/android/android-components/components/feature/addons/src/main/res/values-kab/strings.xml
@@ -76,8 +76,6 @@
<string name="mozac_feature_addons_version">Lqem</string>
<!-- The author of an add-on. -->
<string name="mozac_feature_addons_author">Ameskar</string>
- <!-- The authors of an add-on. -->
- <string name="mozac_feature_addons_authors" moz:removedIn="123" tools:ignore="UnusedResources">Imeskaren</string>
<!-- The last date that the add-on was updated. -->
<string name="mozac_feature_addons_last_updated">Aleqqem aneggaru</string>
<!-- The developer website (Homepage) of the add-on. -->
@@ -88,20 +86,20 @@
<string name="mozac_feature_addons_rating">Tizmilin</string>
<!-- A link that points to the detail page of the add-on. -->
<string name="mozac_feature_addons_more_info_link" moz:removedIn="126" tools:ignore="UnusedResources">Ugar γef uzegrir-agi</string>
+ <!-- A link that points to the detail page of the extension. -->
+ <string name="mozac_feature_addons_more_info_link_2">Ugar ɣef usiɣzef-a</string>
<!-- The settings of the add-on. -->
<string name="mozac_feature_addons_settings">Iɣewwaṛen</string>
<!-- Indicates the add-on is enabled. -->
<string name="mozac_feature_addons_settings_on">Yermed</string>
- <!-- Indicates the add-on is disabled. -->
- <string name="mozac_feature_addons_settings_off" moz:removedIn="125" tools:ignore="UnusedResources">Yensa</string>
<!-- Indicates the add-on is allowed in private browsing mode. -->
<string name="mozac_feature_addons_settings_allow_in_private_browsing">Sireg di tunigin tusligt</string>
<!-- Indicates the add-on is allowed in private browsing mode. -->
<string name="mozac_feature_addons_settings_run_in_private_browsing">Selkem di tunigin tusligt</string>
+ <!-- This is displayed when the add-on is not allowed to run in private browsing. -->
+ <string name="mozac_feature_addons_not_allowed_in_private_browsing">Ur yettusireg ara deg yisfuyla usligen</string>
<!-- Indicates the add-on is enabled. -->
<string name="mozac_feature_addons_enabled">Irmed</string>
- <!-- Indicates the add-on is disabled. -->
- <string name="mozac_feature_addons_disabled" moz:removedIn="125" tools:ignore="UnusedResources">Yensa</string>
<!-- This is displayed in a page where the user can see the installed and recommended(not installed yet) add-ons, this string indicates the installed section. -->
<string name="mozac_feature_addons_installed_section">Ibded</string>
<!-- This is displayed in a page where the user can see the installed and recommended(not installed yet) add-ons, this string indicates the recommended section. -->
@@ -136,24 +134,24 @@
<string name="mozac_feature_addons_permissions_dialog_deny">Gdel</string>
<!-- This is a button to cancel the add-on installation . -->
<string name="mozac_feature_addons_permissions_dialog_cancel">Sefsex</string>
- <!-- Accessibility content description to install add-on button. -->
- <string name="mozac_feature_addons_install_addon_content_description" tools:ignore="UnusedResources" moz:removedIn="124">Asebded n uzegrir</string>
<!-- Accessibility content description to install add-on button. %1$s is the add-on name. -->
<string name="mozac_feature_addons_install_addon_content_description_2">Sebded %1$s</string>
<!-- This is the label of a button to cancel an ongoing add-on installation. -->
<string name="mozac_feature_addons_install_addon_dialog_cancel">Sefsex</string>
<!-- Indicates how many users have rated an add-on. %1$s will be replaced with number of reviews -->
<string name="mozac_feature_addons_user_rating_count_2">Cegger: %1$s</string>
- <!-- Accessibility content description for the amount of stars that add-on has, where %1$.02f will be the amount of stars and / separator and 5 the maximum number of stars e.g (2/5, 4.5/5 or 5/5) . -->
- <string name="mozac_feature_addons_rating_content_description" moz:removedIn="124" tools:ignore="UnusedResources">%1$.02f/55</string>
<!-- This is the title of page where all the add-ons are listed-->
<string name="mozac_feature_addons_addons">Izegrar</string>
<!-- Label for add-ons sub menu item for add-ons manager-->
<string name="mozac_feature_addons_addons_manager">Amsefrak n yizegrar</string>
<!-- The title of the "crash" notification in the add-ons manager -->
<string name="mozac_feature_addons_manager_notification_title_text" moz:removedIn="126" tools:ignore="UnusedResources">Azegrir yensa i kra n wakud</string>
+ <!-- The title of the "crash" notification in the extensions manager -->
+ <string name="mozac_feature_extensions_manager_notification_title_text">Isiɣzaf nsan i kra n wakud</string>
<!-- Button to re-enable the add-ons in the "crash" notification -->
<string name="mozac_feature_addons_manager_notification_restart_button" moz:removedIn="126" tools:ignore="UnusedResources">Ales asenker n yizegrar</string>
+ <!-- Button to re-enable the extensions in the "crash" notification -->
+ <string name="mozac_feature_extensions_manager_notification_restart_button">Ales asenker n yisiɣzaf</string>
<!-- Button in the add-ons manager that opens AMO in a tab -->
<string name="mozac_feature_addons_find_more_addons_button_text" moz:removedIn="126" tools:ignore="UnusedResources">Aff-d ugar n izegrar</string>
<!-- Button in the extensions manager that opens AMO in a tab -->
@@ -170,6 +168,8 @@
<string name="mozac_feature_addons_updater_notification_content_singular">Tasiregt tamaynut tlaq</string>
<!-- Name of the "notification channel" used for displaying a notification for updating an add-on. See https://developer.android.com/training/notify-user/channels -->
<string name="mozac_feature_addons_updater_notification_channel" moz:removedIn="126" tools:ignore="UnusedResources">Ileqman n uzegrir</string>
+ <!-- Name of the "notification channel" used for displaying a notification for updating an extension. See https://developer.android.com/training/notify-user/channels -->
+ <string name="mozac_feature_addons_updater_notification_channel_2">Ileqman n yisiɣzaf</string>
<!-- Name of the "notification channel" used for displaying a notification for new supported add-ons. See https://developer.android.com/training/notify-user/channels -->
<string name="mozac_feature_addons_supported_checker_notification_channel" tools:ignore="UnusedResources">Amsenqed n izegrar imṣaḍan</string>
<!-- The tile of the notification, this will be shown to the user when one newly supported add-on is available.-->
@@ -188,6 +188,8 @@
<string name="mozac_feature_addons_not_yet_supported_caption2">Aql-aɣ nbennu Tallelt i taggayt tamezwarut akked isiɣzaf ihullen.</string>
<!-- This is the caption for the add-on installation progress overlay -->
<string name="mozac_add_on_install_progress_caption" moz:removedIn="126" tools:ignore="UnusedResources">Azdam akked usenqed n uzegrir…</string>
+ <!-- This is the caption for the extension installation progress overlay -->
+ <string name="mozac_extension_install_progress_caption">Asader d usenqed n usiɣzef…</string>
<!-- Error shown when something unexpected happened while trying to get the add-on list from the server -->
<string name="mozac_feature_addons_failed_to_query_add_ons" moz:removedIn="126" tools:ignore="UnusedResources">Tuttra n izegrar ur teddi ara!</string>
<!-- Error shown when unable to find a translation for an add-on field. %1$s is the locale of the user and %2$s is the default language of the add-on -->
@@ -250,10 +252,8 @@
<string name="mozac_feature_addons_updater_dialog_status">Addaden:</string>
<!-- Text shown in the dialog when add-on installation is completed. %1$s is the add-on name. %2$s is the app name. -->
<string name="mozac_feature_addons_installed_dialog_title">%1$s yettwarna ɣer %2$s</string>
- <!-- Text shown in the dialog when add-on installation is completed. -->
- <string name="mozac_feature_addons_installed_dialog_description" moz:removedIn="124" tools:ignore="UnusedResources">Ldi-t deg wumuɣ</string>
- <!-- Confirmation button text for the dialog when add-on installation is completed. -->
- <string name="mozac_feature_addons_installed_dialog_okay_button" moz:removedIn="124" tools:ignore="UnusedResources">Ih, awi-t-id</string>
+ <!-- Text shown in the dialog when add-on installation is completed. %1$s is the add-on name. %2$s is the app name. -->
+ <string name="mozac_feature_addons_installed_dialog_description_2">Kcem ɣer %1$s seg wumuɣ %2$s.</string>
<!-- Confirmation button text for the dialog when add-on installation is completed. -->
<string name="mozac_feature_addons_installed_dialog_okay_button_2">IH</string>
<!-- "Learn more" link displayed below an add-on status message. -->
diff --git a/mobile/android/android-components/components/feature/addons/src/main/res/values-ko/strings.xml b/mobile/android/android-components/components/feature/addons/src/main/res/values-ko/strings.xml
index 60f62641ed..ce90feb55f 100644
--- a/mobile/android/android-components/components/feature/addons/src/main/res/values-ko/strings.xml
+++ b/mobile/android/android-components/components/feature/addons/src/main/res/values-ko/strings.xml
@@ -65,7 +65,7 @@
<!-- Description for proxy permission. -->
<string name="mozac_feature_addons_permissions_proxy_description">브라우저 프록시 설정 제어</string>
<!-- Description for sessions permission. -->
- <string name="mozac_feature_addons_permissions_sessions_description">최근에 닫힌 탭에 접근</string>
+ <string name="mozac_feature_addons_permissions_sessions_description">최근에 닫은 탭에 접근</string>
<!-- Description for tab_hide permission. -->
<string name="mozac_feature_addons_permissions_tab_hide_description">브라우저 탭 숨기기 및 표시</string>
<!-- Description for top_sites permission. -->
diff --git a/mobile/android/android-components/components/feature/addons/src/main/res/values-nn-rNO/strings.xml b/mobile/android/android-components/components/feature/addons/src/main/res/values-nn-rNO/strings.xml
index 0497c14100..841f8a0fc4 100644
--- a/mobile/android/android-components/components/feature/addons/src/main/res/values-nn-rNO/strings.xml
+++ b/mobile/android/android-components/components/feature/addons/src/main/res/values-nn-rNO/strings.xml
@@ -76,8 +76,6 @@
<string name="mozac_feature_addons_version">Versjon</string>
<!-- The author of an add-on. -->
<string name="mozac_feature_addons_author">Utviklar</string>
- <!-- The authors of an add-on. -->
- <string name="mozac_feature_addons_authors" moz:removedIn="123" tools:ignore="UnusedResources">Utviklarar</string>
<!-- The last date that the add-on was updated. -->
<string name="mozac_feature_addons_last_updated">Sist oppdatert</string>
<!-- The developer website (Homepage) of the add-on. -->
@@ -94,8 +92,6 @@
<string name="mozac_feature_addons_settings">Innstillingar</string>
<!-- Indicates the add-on is enabled. -->
<string name="mozac_feature_addons_settings_on">På</string>
- <!-- Indicates the add-on is disabled. -->
- <string name="mozac_feature_addons_settings_off" moz:removedIn="125" tools:ignore="UnusedResources">Av</string>
<!-- Indicates the add-on is allowed in private browsing mode. -->
<string name="mozac_feature_addons_settings_allow_in_private_browsing">Tillat i privat nettlesing</string>
<!-- Indicates the add-on is allowed in private browsing mode. -->
@@ -104,8 +100,6 @@
<string name="mozac_feature_addons_not_allowed_in_private_browsing">Ikkje tillate i private vindauge</string>
<!-- Indicates the add-on is enabled. -->
<string name="mozac_feature_addons_enabled">Påslått</string>
- <!-- Indicates the add-on is disabled. -->
- <string name="mozac_feature_addons_disabled" moz:removedIn="125" tools:ignore="UnusedResources">Avslått</string>
<!-- This is displayed in a page where the user can see the installed and recommended(not installed yet) add-ons, this string indicates the installed section. -->
<string name="mozac_feature_addons_installed_section">Installert</string>
<!-- This is displayed in a page where the user can see the installed and recommended(not installed yet) add-ons, this string indicates the recommended section. -->
@@ -140,16 +134,12 @@
<string name="mozac_feature_addons_permissions_dialog_deny">Avvis</string>
<!-- This is a button to cancel the add-on installation . -->
<string name="mozac_feature_addons_permissions_dialog_cancel">Avbryt</string>
- <!-- Accessibility content description to install add-on button. -->
- <string name="mozac_feature_addons_install_addon_content_description" tools:ignore="UnusedResources" moz:removedIn="124">Installer tillegg</string>
<!-- Accessibility content description to install add-on button. %1$s is the add-on name. -->
<string name="mozac_feature_addons_install_addon_content_description_2">Installer %1$s</string>
<!-- This is the label of a button to cancel an ongoing add-on installation. -->
<string name="mozac_feature_addons_install_addon_dialog_cancel">Avbryt</string>
<!-- Indicates how many users have rated an add-on. %1$s will be replaced with number of reviews -->
<string name="mozac_feature_addons_user_rating_count_2">Omtalar: %1$s</string>
- <!-- Accessibility content description for the amount of stars that add-on has, where %1$.02f will be the amount of stars and / separator and 5 the maximum number of stars e.g (2/5, 4.5/5 or 5/5) . -->
- <string name="mozac_feature_addons_rating_content_description" moz:removedIn="124" tools:ignore="UnusedResources">%1$.02f/5</string>
<!-- Accessibility content description for the amount of stars that add-on has, where %1$.02f will be the amount of stars. -->
<string name="mozac_feature_addons_rating_content_description_2">Vurdering: %1$.02f av 5</string>
<!-- This is the title of page where all the add-ons are listed-->
@@ -162,6 +152,8 @@
<string name="mozac_feature_extensions_manager_notification_title_text">Utvidinga er mellombels deaktivert</string>
<!-- The content of the "crash" notification in the add-ons manager -->
<string name="mozac_feature_addons_manager_notification_content_text" moz:removedIn="126" tools:ignore="UnusedResources">Eitt eller fleire tillegg slutta å verke, noko som gjorde systemet ditt ustabilt.</string>
+ <!-- The content of the "crash" notification in the extensions manager -->
+ <string name="mozac_feature_extensions_manager_notification_content_text">Ei eller fleire utvidingar slutta å fungere, noko som gjorde systemet ditt ustabilt.</string>
<!-- Button to re-enable the add-ons in the "crash" notification -->
<string name="mozac_feature_addons_manager_notification_restart_button" moz:removedIn="126" tools:ignore="UnusedResources">Start tillegga på nytt</string>
<!-- Button to re-enable the extensions in the "crash" notification -->
@@ -202,8 +194,12 @@
<string name="mozac_feature_addons_not_yet_supported_caption2">Vi utviklar for tida støtte for eit første utval av tilrådde utvidingar.</string>
<!-- This is the caption for the add-on installation progress overlay -->
<string name="mozac_add_on_install_progress_caption" moz:removedIn="126" tools:ignore="UnusedResources">Lastar ned og stadfestar tiillegget…</string>
+ <!-- This is the caption for the extension installation progress overlay -->
+ <string name="mozac_extension_install_progress_caption">Lastar ned og stadfestar utvidinga…</string>
<!-- Error shown when something unexpected happened while trying to get the add-on list from the server -->
<string name="mozac_feature_addons_failed_to_query_add_ons" moz:removedIn="126" tools:ignore="UnusedResources">Mislykka førespurnad om tlleggsprogram!</string>
+ <!-- Error shown when something unexpected happened while trying to get the extension list from the server -->
+ <string name="mozac_feature_addons_failed_to_query_extensions">Mislykka førespurnad etter utvidingar!</string>
<!-- Error shown when unable to find a translation for an add-on field. %1$s is the locale of the user and %2$s is the default language of the add-on -->
<string name="mozac_feature_addons_failed_to_translate">Fann ikkje omsettinga for språket %2$s, eller for standardspråket %1$s</string>
<!-- Text shown after successfully installed an add-on. %1$s is the add-on name. -->
@@ -212,12 +208,20 @@
<string name="mozac_feature_addons_failed_to_install">Klarte ikkje å installere %1$s</string>
<!-- Text shown after failing to install an add-on for which we don't have its name. -->
<string name="mozac_feature_addons_failed_to_install_generic" moz:removedIn="126" tools:ignore="UnusedResources">Klarte ikkje å installere dette tillegget.</string>
+ <!-- Text shown after failing to install an extension for which we don't have its name. -->
+ <string name="mozac_feature_addons_extension_failed_to_install">Klarte ikkje å installere denne utvidinga.</string>
<!-- Text shown when attempting to install an add-on and a network error happened. -->
<string name="mozac_feature_addons_failed_to_install_network_error" moz:removedIn="126" tools:ignore="UnusedResources">Klarte ikkje å laste ned tillegget på grunn av ein tilkoplingsfeil.</string>
+ <!-- Text shown when attempting to install an extension and a network error happened. -->
+ <string name="mozac_feature_addons_extension_failed_to_install_network_error">Klarte ikkje å laste ned utvidinga på grunn av ein tilkoplingsfeil.</string>
<!-- Text shown when attempting to install an add-on and the downloaded file is corrupted. -->
<string name="mozac_feature_addons_failed_to_install_corrupt_error" moz:removedIn="126" tools:ignore="UnusedResources">Klarte ikkje å installere dette tillegget fordi det ser ut til å vere skada.</string>
+ <!-- Text shown when attempting to install an extension and the downloaded file is corrupted. -->
+ <string name="mozac_feature_addons_extension_failed_to_install_corrupt_error">Klarte ikkje å installere denne utvidinga fordi ho ser ut til å vere skada.</string>
<!-- Text shown when attempting to install an add-on and an error occurred because the extension was not signed. -->
<string name="mozac_feature_addons_failed_to_install_not_signed_error" moz:removedIn="126" tools:ignore="UnusedResources">Klarte ikkje å installere dette tillegget fordi det ikkje er stadfesta.</string>
+ <!-- Text shown when attempting to install an add-on and an error occurred because the extension was not signed. -->
+ <string name="mozac_feature_addons_extension_failed_to_install_not_signed_error">Klarte ikkje å installere denne utvidinga fordi ho ikkje har blitt stadfesta.</string>
<!-- Text shown when attempting to install an add-on and an error occurred because the extension was incompatible. %1$s is the add-on name, %2$s is the app name and %3$s is the app version. -->
<string name="mozac_feature_addons_failed_to_install_incompatible_error">Klarte ikkje å installere %1$s fordi den ikkje er kompatibel med %2$s %3$s.</string>
<!-- Text shown when attempting to install a blocklisted add-on. %1$s is the add-on name. -->
@@ -264,13 +268,9 @@
<string name="mozac_feature_addons_updater_dialog_status">Status:</string>
<!-- Text shown in the dialog when add-on installation is completed. %1$s is the add-on name. %2$s is the app name. -->
<string name="mozac_feature_addons_installed_dialog_title">%1$s er lagt til i %2$s</string>
- <!-- Text shown in the dialog when add-on installation is completed. -->
- <string name="mozac_feature_addons_installed_dialog_description" moz:removedIn="124" tools:ignore="UnusedResources">Opne det i menyen</string>
<!-- Text shown in the dialog when add-on installation is completed. %1$s is the add-on name. %2$s is the app name. -->
<string name="mozac_feature_addons_installed_dialog_description_2">Få tilgang til %1$s frå %2$s-menyen.</string>
<!-- Confirmation button text for the dialog when add-on installation is completed. -->
- <string name="mozac_feature_addons_installed_dialog_okay_button" moz:removedIn="124" tools:ignore="UnusedResources">Ok, eg forstår</string>
- <!-- Confirmation button text for the dialog when add-on installation is completed. -->
<string name="mozac_feature_addons_installed_dialog_okay_button_2">OK</string>
<!-- "Learn more" link displayed below an add-on status message. -->
<string name="mozac_feature_addons_status_learn_more">Les meir</string>
diff --git a/mobile/android/android-components/components/feature/addons/src/main/res/values-sc/strings.xml b/mobile/android/android-components/components/feature/addons/src/main/res/values-sc/strings.xml
index d3dbbca241..5106df89be 100644
--- a/mobile/android/android-components/components/feature/addons/src/main/res/values-sc/strings.xml
+++ b/mobile/android/android-components/components/feature/addons/src/main/res/values-sc/strings.xml
@@ -74,8 +74,6 @@
<string name="mozac_feature_addons_version">Versione</string>
<!-- The author of an add-on. -->
<string name="mozac_feature_addons_author">Autoria</string>
- <!-- The authors of an add-on. -->
- <string name="mozac_feature_addons_authors" moz:removedIn="123" tools:ignore="UnusedResources">Autoria</string>
<!-- The last date that the add-on was updated. -->
<string name="mozac_feature_addons_last_updated">Ùrtima atualizatzione</string>
<!-- The developer website (Homepage) of the add-on. -->
@@ -85,21 +83,17 @@
<!-- The rating of the add-on. -->
<string name="mozac_feature_addons_rating">Valutatzione</string>
<!-- A link that points to the detail page of the add-on. -->
- <string name="mozac_feature_addons_more_info_link">Àteru in pitzus de custu cumplementu</string>
+ <string name="mozac_feature_addons_more_info_link" moz:removedIn="126" tools:ignore="UnusedResources">Àteru in pitzus de custu cumplementu</string>
<!-- The settings of the add-on. -->
<string name="mozac_feature_addons_settings">Cunfiguratzione</string>
<!-- Indicates the add-on is enabled. -->
<string name="mozac_feature_addons_settings_on">Ativu</string>
- <!-- Indicates the add-on is disabled. -->
- <string name="mozac_feature_addons_settings_off">Disativadu</string>
<!-- Indicates the add-on is allowed in private browsing mode. -->
<string name="mozac_feature_addons_settings_allow_in_private_browsing">Permite in sa navigatzione privada</string>
<!-- Indicates the add-on is allowed in private browsing mode. -->
<string name="mozac_feature_addons_settings_run_in_private_browsing">Esecuta in sa navigatzione privada</string>
<!-- Indicates the add-on is enabled. -->
<string name="mozac_feature_addons_enabled">Ativadu</string>
- <!-- Indicates the add-on is disabled. -->
- <string name="mozac_feature_addons_disabled">Disativadu</string>
<!-- This is displayed in a page where the user can see the installed and recommended(not installed yet) add-ons, this string indicates the installed section. -->
<string name="mozac_feature_addons_installed_section">Installadu</string>
<!-- This is displayed in a page where the user can see the installed and recommended(not installed yet) add-ons, this string indicates the recommended section. -->
@@ -134,24 +128,28 @@
<string name="mozac_feature_addons_permissions_dialog_deny">Refuda</string>
<!-- This is a button to cancel the add-on installation . -->
<string name="mozac_feature_addons_permissions_dialog_cancel">Annulla</string>
- <!-- Accessibility content description to install add-on button. -->
- <string name="mozac_feature_addons_install_addon_content_description">Installa su cumplementu</string>
<!-- This is the label of a button to cancel an ongoing add-on installation. -->
<string name="mozac_feature_addons_install_addon_dialog_cancel">Annulla</string>
<!-- Indicates how many users have rated an add-on. %1$s will be replaced with number of reviews -->
<string name="mozac_feature_addons_user_rating_count_2">Retzensiones: %1$s</string>
- <!-- Accessibility content description for the amount of stars that add-on has, where %1$.02f will be the amount of stars and / separator and 5 the maximum number of stars e.g (2/5, 4.5/5 or 5/5) . -->
- <string name="mozac_feature_addons_rating_content_description">%1$.02f/5</string>
<!-- This is the title of page where all the add-ons are listed-->
<string name="mozac_feature_addons_addons">Cumplementos</string>
<!-- Label for add-ons sub menu item for add-ons manager-->
<string name="mozac_feature_addons_addons_manager">Gestore de cumplementos</string>
<!-- The title of the "crash" notification in the add-ons manager -->
- <string name="mozac_feature_addons_manager_notification_title_text">Is cumplementos sunt istados disativados in manera temporànea</string>
+ <string name="mozac_feature_addons_manager_notification_title_text" moz:removedIn="126" tools:ignore="UnusedResources">Is cumplementos sunt istados disativados in manera temporànea</string>
+ <!-- The title of the "crash" notification in the extensions manager -->
+ <string name="mozac_feature_extensions_manager_notification_title_text">Is estensiones sunt disativadas in manera temporànea</string>
+ <!-- The content of the "crash" notification in the extensions manager -->
+ <string name="mozac_feature_extensions_manager_notification_content_text">Una o prus estensiones ant tzessadu de funtzionare, e cumpromitent s\'istabilidade de su sistema.</string>
<!-- Button to re-enable the add-ons in the "crash" notification -->
- <string name="mozac_feature_addons_manager_notification_restart_button">Torra a aviare is cumplementos</string>
+ <string name="mozac_feature_addons_manager_notification_restart_button" moz:removedIn="126" tools:ignore="UnusedResources">Torra a aviare is cumplementos</string>
+ <!-- Button to re-enable the extensions in the "crash" notification -->
+ <string name="mozac_feature_extensions_manager_notification_restart_button">Torra a aviare is estensiones</string>
<!-- Button in the add-ons manager that opens AMO in a tab -->
- <string name="mozac_feature_addons_find_more_addons_button_text">Agata àteros cumplementos</string>
+ <string name="mozac_feature_addons_find_more_addons_button_text" moz:removedIn="126" tools:ignore="UnusedResources">Agata àteros cumplementos</string>
+ <!-- Button in the extensions manager that opens AMO in a tab -->
+ <string name="mozac_feature_addons_find_more_extensions_button_text">Agata àteras estensiones</string>
<!-- The label of the allow button, this will be shown to the user when an add-on needs new permissions, with the button the user will indicate that they want to accept the new permissions and update the add-on-->
<string name="mozac_feature_addons_updater_notification_allow_button">Permite</string>
<!-- The label of the deny button on a notification, this will be shown to the user when an add-on needs new permissions. Indicates the user denies the new permissions and prevents the add-on from be updated-->
@@ -163,23 +161,27 @@
<!-- The content of the notification displayed when an add-on needs a new permission-->
<string name="mozac_feature_addons_updater_notification_content_singular">Permissu nou rechestu</string>
<!-- Name of the "notification channel" used for displaying a notification for updating an add-on. See https://developer.android.com/training/notify-user/channels -->
- <string name="mozac_feature_addons_updater_notification_channel">Atualizatziones de cumplementos</string>
+ <string name="mozac_feature_addons_updater_notification_channel" moz:removedIn="126" tools:ignore="UnusedResources">Atualizatziones de cumplementos</string>
<!-- Name of the "notification channel" used for displaying a notification for new supported add-ons. See https://developer.android.com/training/notify-user/channels -->
- <string name="mozac_feature_addons_supported_checker_notification_channel">Verificadore de cumplementos cumpatìbiles</string>
+ <string name="mozac_feature_addons_supported_checker_notification_channel" tools:ignore="UnusedResources">Verificadore de cumplementos cumpatìbiles</string>
<!-- The tile of the notification, this will be shown to the user when one newly supported add-on is available.-->
- <string name="mozac_feature_addons_supported_checker_notification_title">Cumplementu nou cumpatìbile</string>
+ <string name="mozac_feature_addons_supported_checker_notification_title" tools:ignore="UnusedResources">Cumplementu nou cumpatìbile</string>
<!-- The tile of the notification, this will be shown to the user when more than one newly supported add-ons are available.-->
- <string name="mozac_feature_addons_supported_checker_notification_title_plural">Cumplementos noos a disponimentu</string>
+ <string name="mozac_feature_addons_supported_checker_notification_title_plural" tools:ignore="UnusedResources">Cumplementos noos a disponimentu</string>
<!-- The content of the notification, this will be shown to the user when one newly supported add-on is available. %1$s is the add-on name and %2$s is the app name (in most cases Firefox). -->
<string name="mozac_feature_addons_supported_checker_notification_content_one">Agiunghe %1$s a %2$s</string>
<!-- The content of the notification, this will be shown to the user when two newly supported add-ons are available. %1$s is the first add-on name. %2$s is the second add-on name. %3$s is the app name (in most cases Firefox). -->
<string name="mozac_feature_addons_supported_checker_notification_content_two">Agiunghe %1$s e %2$s a %3$s</string>
<!-- The content of the notification, this will be shown to the user when more than two newly supported add-ons are available. %1$s is the app name (in most cases Firefox). -->
<string name="mozac_feature_addons_supported_checker_notification_content_more_than_two">Agiunghe·ddos a %1$s</string>
+ <!-- This is the caption for not yet supported screen caption -->
+ <string name="mozac_feature_addons_not_yet_supported_caption2">Semus traballende pro frunire una seletzione initziale de estensiones cussigiadas.</string>
<!-- This is the caption for the add-on installation progress overlay -->
- <string name="mozac_add_on_install_progress_caption">Iscarrighende e verifichende su cumplementu…</string>
+ <string name="mozac_add_on_install_progress_caption" moz:removedIn="126" tools:ignore="UnusedResources">Iscarrighende e verifichende su cumplementu…</string>
<!-- Error shown when something unexpected happened while trying to get the add-on list from the server -->
- <string name="mozac_feature_addons_failed_to_query_add_ons">Impossìbile otènnere sa lista de cumplementos.</string>
+ <string name="mozac_feature_addons_failed_to_query_add_ons" moz:removedIn="126" tools:ignore="UnusedResources">Impossìbile otènnere sa lista de cumplementos.</string>
+ <!-- Error shown when something unexpected happened while trying to get the extension list from the server -->
+ <string name="mozac_feature_addons_failed_to_query_extensions">Impossìbile otènnere sa lista de estensiones.</string>
<!-- Error shown when unable to find a translation for an add-on field. %1$s is the locale of the user and %2$s is the default language of the add-on -->
<string name="mozac_feature_addons_failed_to_translate">Nissuna tradutzione agatada, ne pro su %1$s nen pro sa lìngua predefinida %2$s</string>
<!-- Text shown after successfully installed an add-on. %1$s is the add-on name. -->
@@ -187,13 +189,13 @@
<!-- Text shown after failed to install an add-on. %1$s is the add-on name. -->
<string name="mozac_feature_addons_failed_to_install">Faddina in s’installatzione de %1$s</string>
<!-- Text shown after failing to install an add-on for which we don't have its name. -->
- <string name="mozac_feature_addons_failed_to_install_generic">Faddina in s’installatzione de custu cumplementu.</string>
+ <string name="mozac_feature_addons_failed_to_install_generic" moz:removedIn="126" tools:ignore="UnusedResources">Faddina in s’installatzione de custu cumplementu.</string>
<!-- Text shown when attempting to install an add-on and a network error happened. -->
- <string name="mozac_feature_addons_failed_to_install_network_error">Impossìbile iscarrigare custu cumplementu pro more de una faddina in sa connessione.</string>
+ <string name="mozac_feature_addons_failed_to_install_network_error" moz:removedIn="126" tools:ignore="UnusedResources">Impossìbile iscarrigare custu cumplementu pro more de una faddina in sa connessione.</string>
<!-- Text shown when attempting to install an add-on and the downloaded file is corrupted. -->
- <string name="mozac_feature_addons_failed_to_install_corrupt_error">Custu cumplementu non si podet installare ca paret corrùmpidu.</string>
+ <string name="mozac_feature_addons_failed_to_install_corrupt_error" moz:removedIn="126" tools:ignore="UnusedResources">Custu cumplementu non si podet installare ca paret corrùmpidu.</string>
<!-- Text shown when attempting to install an add-on and an error occurred because the extension was not signed. -->
- <string name="mozac_feature_addons_failed_to_install_not_signed_error">Custu cumplementu non si podet installare ca no est averiguadu.</string>
+ <string name="mozac_feature_addons_failed_to_install_not_signed_error" moz:removedIn="126" tools:ignore="UnusedResources">Custu cumplementu non si podet installare ca no est averiguadu.</string>
<!-- Text shown when attempting to install an add-on and an error occurred because the extension was incompatible. %1$s is the add-on name, %2$s is the app name and %3$s is the app version. -->
<string name="mozac_feature_addons_failed_to_install_incompatible_error">%1$s non si podet installare ca no est cumpatìbile cun %2$s %3$s.</string>
<!-- Text shown when attempting to install a blocklisted add-on. %1$s is the add-on name. -->
@@ -215,9 +217,11 @@
<!-- Text shown after failed to remove an add-on. %1$s is the add-on name. -->
<string name="mozac_feature_addons_failed_to_remove" tools:ignore="UnusedResources">Faddina in s’eliminatzione de %1$s</string>
<!-- Text shown in not yet supported add-ons section in AddonsManagerAdapter. -->
- <string name="mozac_feature_addons_unsupported_caption">1 cumplementu</string>
+ <string name="mozac_feature_addons_unsupported_caption" moz:removedIn="126" tools:ignore="UnusedResources">1 cumplementu</string>
<!-- Text shown in not yet supported add-ons section in AddonsManagerAdapter - plural. %1$s is the number of unsupported add-ons -->
- <string name="mozac_feature_addons_unsupported_caption_plural">%1$s cumplementos</string>
+ <string name="mozac_feature_addons_unsupported_caption_plural" moz:removedIn="126" tools:ignore="UnusedResources">%1$s cumplementos</string>
+ <!-- Text shown in not yet supported add-ons section - plural. %1$s is the number of unsupported extensions. -->
+ <string name="mozac_feature_addons_unsupported_caption_plural_2">%1$s estensiones</string>
<!-- Text link to a sumo page for learning more about unsupported add-ons. -->
<string name="mozac_feature_addons_unsupported_learn_more">Àteras informatziones</string>
<!-- Displayed in the "Status" field for the updater when an add-on has been correctly updated. -->
@@ -234,10 +238,6 @@
<string name="mozac_feature_addons_updater_dialog_status">Istadu:</string>
<!-- Text shown in the dialog when add-on installation is completed. %1$s is the add-on name. %2$s is the app name. -->
<string name="mozac_feature_addons_installed_dialog_title">%1$s agiuntu a %2$s</string>
- <!-- Text shown in the dialog when add-on installation is completed. %1$s is the add-on name. -->
- <string name="mozac_feature_addons_installed_dialog_description">Aberi·ddu dae su menù</string>
- <!-- Confirmation button text for the dialog when add-on installation is completed. -->
- <string name="mozac_feature_addons_installed_dialog_okay_button">AB, cumprèndidu</string>
<!-- "Learn more" link displayed below an add-on status message. -->
<string name="mozac_feature_addons_status_learn_more">Àteras informatziones</string>
<!-- Status message below an add-on in the add-ons manager when this add-on has been blocklisted. %1$s is the add-on name. -->
diff --git a/mobile/android/android-components/components/feature/addons/src/main/res/values-si/strings.xml b/mobile/android/android-components/components/feature/addons/src/main/res/values-si/strings.xml
index 6eb142ef1b..202cf37277 100644
--- a/mobile/android/android-components/components/feature/addons/src/main/res/values-si/strings.xml
+++ b/mobile/android/android-components/components/feature/addons/src/main/res/values-si/strings.xml
@@ -162,8 +162,12 @@
<string name="mozac_feature_addons_manager_notification_content_text" moz:removedIn="126" tools:ignore="UnusedResources">ඔබගේ පද්ධතිය අස්ථායී කරමින් එක්කහුවක් හෝ කිහිපයක් නතර විය.</string>
<!-- Button to re-enable the add-ons in the "crash" notification -->
<string name="mozac_feature_addons_manager_notification_restart_button" moz:removedIn="126" tools:ignore="UnusedResources">එක්කහු යළි අරඹන්න</string>
+ <!-- Button to re-enable the extensions in the "crash" notification -->
+ <string name="mozac_feature_extensions_manager_notification_restart_button">දිගු යළි අරඹන්න</string>
<!-- Button in the add-ons manager that opens AMO in a tab -->
<string name="mozac_feature_addons_find_more_addons_button_text" moz:removedIn="126" tools:ignore="UnusedResources">තවත් එක්කහු සොයාගන්න</string>
+ <!-- Button in the extensions manager that opens AMO in a tab -->
+ <string name="mozac_feature_addons_find_more_extensions_button_text">තවත් දිගු සොයන්න</string>
<!-- The label of the allow button, this will be shown to the user when an add-on needs new permissions, with the button the user will indicate that they want to accept the new permissions and update the add-on-->
<string name="mozac_feature_addons_updater_notification_allow_button">ඉඩ දෙන්න</string>
<!-- The label of the deny button on a notification, this will be shown to the user when an add-on needs new permissions. Indicates the user denies the new permissions and prevents the add-on from be updated-->
@@ -196,6 +200,8 @@
<string name="mozac_feature_addons_not_yet_supported_caption2">දැනට නිර්දේශිත දිගුවල ප්‍රාරම්භ තේරීමක් සඳහා සහාය තනමින් සිටියි.</string>
<!-- This is the caption for the add-on installation progress overlay -->
<string name="mozac_add_on_install_progress_caption" moz:removedIn="126" tools:ignore="UnusedResources">එක්කහුව බාගැනෙමින් හා සත්‍යාපනය වෙමින්…</string>
+ <!-- This is the caption for the extension installation progress overlay -->
+ <string name="mozac_extension_install_progress_caption">දිගුව බාගැනෙමින් හා සත්‍යාපනය වෙමින්…</string>
<!-- Error shown when something unexpected happened while trying to get the add-on list from the server -->
<string name="mozac_feature_addons_failed_to_query_add_ons" moz:removedIn="126" tools:ignore="UnusedResources">එක්කහු විමසීමට අසමත් විය!</string>
<!-- Error shown when unable to find a translation for an add-on field. %1$s is the locale of the user and %2$s is the default language of the add-on -->
@@ -206,6 +212,8 @@
<string name="mozac_feature_addons_failed_to_install">%1$s ස්ථාපනයට අසමත් විය</string>
<!-- Text shown after failing to install an add-on for which we don't have its name. -->
<string name="mozac_feature_addons_failed_to_install_generic" moz:removedIn="126" tools:ignore="UnusedResources">එක්කහුව ස්ථාපනයට අසමත් විය.</string>
+ <!-- Text shown after failing to install an extension for which we don't have its name. -->
+ <string name="mozac_feature_addons_extension_failed_to_install">මෙම දිගුව ස්ථාපනයට අසමත් විය.</string>
<!-- Text shown when attempting to install an add-on and a network error happened. -->
<string name="mozac_feature_addons_failed_to_install_network_error" moz:removedIn="126" tools:ignore="UnusedResources">සම්බන්ධතාවයට බාධා වීමක් නිසා එක්කහුව බාගැනීමට නොහැකි විය.</string>
<!-- Text shown when attempting to install an add-on and the downloaded file is corrupted. -->
diff --git a/mobile/android/android-components/components/feature/addons/src/main/res/values-su/strings.xml b/mobile/android/android-components/components/feature/addons/src/main/res/values-su/strings.xml
index 359ceede95..85eb4e0865 100644
--- a/mobile/android/android-components/components/feature/addons/src/main/res/values-su/strings.xml
+++ b/mobile/android/android-components/components/feature/addons/src/main/res/values-su/strings.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:tools="http://schemas.android.com/tools" xmlns:moz="http://schemas.android.com/apk/res-auto">
<!-- Description for privacy add-on permission. -->
- <string name="mozac_feature_addons_permissions_privacy_description">Bca jeung ropéa setélan pripasi</string>
+ <string name="mozac_feature_addons_permissions_privacy_description">Baca jeung ropéa setélan pripasi</string>
<!-- Description for all_urls add-on permission. -->
<string name="mozac_feature_addons_permissions_all_urls_description">Aksés data anjeun pikeun sakabéh raramatloka</string>
<!-- Description for giving an add-on access to users's data on one site. %1$s will be replaced by the DNS host name for which a web extension is requesting access (e.g., www.mozilla.org). -->
@@ -83,7 +83,7 @@
<!-- The developer website (Homepage) of the add-on. -->
<string name="mozac_feature_addons_home_page">Tepas</string>
<!-- A link where users can find more information about add-ons permissions. -->
- <string name="mozac_feature_addons_learn_more">Leuwih jéntré ngeunaan idin</string>
+ <string name="mozac_feature_addons_learn_more">Leuwih jéntré ngeunaan pedaran idin</string>
<!-- The rating of the add-on. -->
<string name="mozac_feature_addons_rating">Peunteun</string>
<!-- A link that points to the detail page of the add-on. -->
@@ -166,8 +166,12 @@
<string name="mozac_feature_extensions_manager_notification_content_text">Aya émboh nu mugen, ngabalukarkeun sistem anjeun teu stabil.</string>
<!-- Button to re-enable the add-ons in the "crash" notification -->
<string name="mozac_feature_addons_manager_notification_restart_button" moz:removedIn="126" tools:ignore="UnusedResources">Balikan deui émboh</string>
+ <!-- Button to re-enable the extensions in the "crash" notification -->
+ <string name="mozac_feature_extensions_manager_notification_restart_button">Jalankeun deui éksténsi</string>
<!-- Button in the add-ons manager that opens AMO in a tab -->
<string name="mozac_feature_addons_find_more_addons_button_text" moz:removedIn="126" tools:ignore="UnusedResources">Panggihan émboh lianna</string>
+ <!-- Button in the extensions manager that opens AMO in a tab -->
+ <string name="mozac_feature_addons_find_more_extensions_button_text">Téangan leuwih réa éksténsi </string>
<!-- The label of the allow button, this will be shown to the user when an add-on needs new permissions, with the button the user will indicate that they want to accept the new permissions and update the add-on-->
<string name="mozac_feature_addons_updater_notification_allow_button">Idinan</string>
<!-- The label of the deny button on a notification, this will be shown to the user when an add-on needs new permissions. Indicates the user denies the new permissions and prevents the add-on from be updated-->
@@ -180,6 +184,8 @@
<string name="mozac_feature_addons_updater_notification_content_singular">Perlu idin anyar</string>
<!-- Name of the "notification channel" used for displaying a notification for updating an add-on. See https://developer.android.com/training/notify-user/channels -->
<string name="mozac_feature_addons_updater_notification_channel" moz:removedIn="126" tools:ignore="UnusedResources">Apdét add-on</string>
+ <!-- Name of the "notification channel" used for displaying a notification for updating an extension. See https://developer.android.com/training/notify-user/channels -->
+ <string name="mozac_feature_addons_updater_notification_channel_2">Apdet éksténsi</string>
<!-- Name of the "notification channel" used for displaying a notification for new supported add-ons. See https://developer.android.com/training/notify-user/channels -->
<string name="mozac_feature_addons_supported_checker_notification_channel" tools:ignore="UnusedResources">Pamariksa add-on nu didukung</string>
<!-- The tile of the notification, this will be shown to the user when one newly supported add-on is available.-->
@@ -198,8 +204,12 @@
<string name="mozac_feature_addons_not_yet_supported_caption2">Kami ayeuna ngawangun dukungan pikeun pilihan awal Éksténsi nu Disarankeun.</string>
<!-- This is the caption for the add-on installation progress overlay -->
<string name="mozac_add_on_install_progress_caption" moz:removedIn="126" tools:ignore="UnusedResources">Ngeundeur jeung verifikasi add-on…</string>
+ <!-- This is the caption for the extension installation progress overlay -->
+ <string name="mozac_extension_install_progress_caption">Ngeundeur jeung verifikasi add-on…</string>
<!-- Error shown when something unexpected happened while trying to get the add-on list from the server -->
<string name="mozac_feature_addons_failed_to_query_add_ons" moz:removedIn="126" tools:ignore="UnusedResources">Gagal pikeun pamundut Add-on!</string>
+ <!-- Error shown when something unexpected happened while trying to get the extension list from the server -->
+ <string name="mozac_feature_addons_failed_to_query_extensions">Gagal pikeun pamundut Add-on!</string>
<!-- Error shown when unable to find a translation for an add-on field. %1$s is the locale of the user and %2$s is the default language of the add-on -->
<string name="mozac_feature_addons_failed_to_translate">Tarjamahan teu kapanggih, pikeun daérah %1$s pon kitu ogé basa bawaan %2$s</string>
<!-- Text shown after successfully installed an add-on. %1$s is the add-on name. -->
@@ -208,12 +218,20 @@
<string name="mozac_feature_addons_failed_to_install">Gagal masang %1$s</string>
<!-- Text shown after failing to install an add-on for which we don't have its name. -->
<string name="mozac_feature_addons_failed_to_install_generic" moz:removedIn="126" tools:ignore="UnusedResources">Gagal masang ieu émboh.</string>
+ <!-- Text shown after failing to install an extension for which we don't have its name. -->
+ <string name="mozac_feature_addons_extension_failed_to_install">Gagal masang ieu éksténsi.</string>
<!-- Text shown when attempting to install an add-on and a network error happened. -->
<string name="mozac_feature_addons_failed_to_install_network_error" moz:removedIn="126" tools:ignore="UnusedResources">Ieu émboh teu bisa diundeur alatan gagal nyambung.</string>
+ <!-- Text shown when attempting to install an extension and a network error happened. -->
+ <string name="mozac_feature_addons_extension_failed_to_install_network_error">Ieu émboh teu bisa diundeur alatan gagal nyambung.</string>
<!-- Text shown when attempting to install an add-on and the downloaded file is corrupted. -->
<string name="mozac_feature_addons_failed_to_install_corrupt_error" moz:removedIn="126" tools:ignore="UnusedResources">Ieu émboh teu bisa dipasang, sigana alatan korup.</string>
+ <!-- Text shown when attempting to install an extension and the downloaded file is corrupted. -->
+ <string name="mozac_feature_addons_extension_failed_to_install_corrupt_error">Ieu émboh teu bisa dipasang, sigana alatan korup.</string>
<!-- Text shown when attempting to install an add-on and an error occurred because the extension was not signed. -->
<string name="mozac_feature_addons_failed_to_install_not_signed_error" moz:removedIn="126" tools:ignore="UnusedResources">Ieu émboh teu bisa dipasang alatan acan dipéripikasi.</string>
+ <!-- Text shown when attempting to install an add-on and an error occurred because the extension was not signed. -->
+ <string name="mozac_feature_addons_extension_failed_to_install_not_signed_error">Ieu émboh teu bisa dipasang alatan acan dipéripikasi.</string>
<!-- Text shown when attempting to install an add-on and an error occurred because the extension was incompatible. %1$s is the add-on name, %2$s is the app name and %3$s is the app version. -->
<string name="mozac_feature_addons_failed_to_install_incompatible_error">%1$s teu bisa dipasang alatan teu kompatibel jeung %2$s %3$s.</string>
<!-- Text shown when attempting to install a blocklisted add-on. %1$s is the add-on name. -->
@@ -238,8 +256,12 @@
<string name="mozac_feature_addons_migrated_from_a_previous_version_label" tools:ignore="UnusedResources">Ieu add-on dipindahkeun ti pérsi heubeul %1$s</string>
<!-- Text shown in not yet supported add-ons section in AddonsManagerAdapter. -->
<string name="mozac_feature_addons_unsupported_caption" moz:removedIn="126" tools:ignore="UnusedResources">1 add-on</string>
+ <!-- Text shown in not yet supported add-ons section. -->
+ <string name="mozac_feature_addons_unsupported_caption_2">éksténsi</string>
<!-- Text shown in not yet supported add-ons section in AddonsManagerAdapter - plural. %1$s is the number of unsupported add-ons -->
<string name="mozac_feature_addons_unsupported_caption_plural" moz:removedIn="126" tools:ignore="UnusedResources">%1$s add-on</string>
+ <!-- Text shown in not yet supported add-ons section - plural. %1$s is the number of unsupported extensions. -->
+ <string name="mozac_feature_addons_unsupported_caption_plural_2">%1$s éksténsi</string>
<!-- Text link to a sumo page for learning more about unsupported add-ons. -->
<string name="mozac_feature_addons_unsupported_learn_more">Lenyepan</string>
<!-- Displayed in the "Status" field for the updater when an add-on has been correctly updated. -->
@@ -258,8 +280,12 @@
<string name="mozac_feature_addons_installed_dialog_title">%1$s geus ditambahkeun ka %2$s</string>
<!-- Text shown in the dialog when add-on installation is completed. -->
<string name="mozac_feature_addons_installed_dialog_description" moz:removedIn="124" tools:ignore="UnusedResources">Buka dina menu</string>
+ <!-- Text shown in the dialog when add-on installation is completed. %1$s is the add-on name. %2$s is the app name. -->
+ <string name="mozac_feature_addons_installed_dialog_description_2">Aksés %1$s tina ménu %2$s.</string>
<!-- Confirmation button text for the dialog when add-on installation is completed. -->
<string name="mozac_feature_addons_installed_dialog_okay_button" moz:removedIn="124" tools:ignore="UnusedResources">Heug, Ngarti</string>
+ <!-- Confirmation button text for the dialog when add-on installation is completed. -->
+ <string name="mozac_feature_addons_installed_dialog_okay_button_2">HEUG</string>
<!-- "Learn more" link displayed below an add-on status message. -->
<string name="mozac_feature_addons_status_learn_more">Lenyepan</string>
<!-- Status message below an add-on in the add-ons manager when this add-on has been blocklisted. %1$s is the add-on name. -->
diff --git a/mobile/android/android-components/components/feature/addons/src/test/java/AddonManagerTest.kt b/mobile/android/android-components/components/feature/addons/src/test/java/AddonManagerTest.kt
index 9c30bd8c0e..c8d3fe8972 100644
--- a/mobile/android/android-components/components/feature/addons/src/test/java/AddonManagerTest.kt
+++ b/mobile/android/android-components/components/feature/addons/src/test/java/AddonManagerTest.kt
@@ -666,7 +666,12 @@ class AddonManagerTest {
val extension: WebExtension = mock()
whenever(extension.id).thenReturn("ext1")
WebExtensionSupport.installedExtensions[addon.id] = extension
-
+ val metadata: Metadata = mock()
+ whenever(extension.getMetadata()).thenReturn(metadata)
+ whenever(metadata.optionalPermissions).thenReturn(permission)
+ whenever(metadata.grantedOptionalPermissions).thenReturn(permission)
+ whenever(metadata.optionalOrigins).thenReturn(origin)
+ whenever(metadata.grantedOptionalOrigins).thenReturn(origin)
val engine: Engine = mock()
val onSuccessCaptor = argumentCaptor<((WebExtension) -> Unit)>()
@@ -685,6 +690,10 @@ class AddonManagerTest {
onSuccessCaptor.value.invoke(extension)
assertNotNull(updateAddon)
assertEquals(addon.id, updateAddon!!.id)
+ assertEquals("permission1", updateAddon!!.optionalPermissions.first().name)
+ assertEquals(true, updateAddon!!.optionalPermissions.first().granted)
+ assertEquals("origin", updateAddon!!.optionalOrigins.first().name)
+ assertEquals(true, updateAddon!!.optionalOrigins.first().granted)
assertTrue(manager.pendingAddonActions.isEmpty())
}
diff --git a/mobile/android/android-components/components/feature/addons/src/test/java/mozilla/components/feature/addons/ui/PermissionsDialogFragmentTest.kt b/mobile/android/android-components/components/feature/addons/src/test/java/mozilla/components/feature/addons/ui/PermissionsDialogFragmentTest.kt
index 339c880380..88a1ff223f 100644
--- a/mobile/android/android-components/components/feature/addons/src/test/java/mozilla/components/feature/addons/ui/PermissionsDialogFragmentTest.kt
+++ b/mobile/android/android-components/components/feature/addons/src/test/java/mozilla/components/feature/addons/ui/PermissionsDialogFragmentTest.kt
@@ -48,8 +48,8 @@ class PermissionsDialogFragmentTest {
val optionalOrRequiredTextView = dialog.findViewById<TextView>(R.id.optional_or_required_text)
val permissionsRecyclerView = dialog.findViewById<RecyclerView>(R.id.permissions)
val recyclerAdapter = permissionsRecyclerView.adapter!! as RequiredPermissionsAdapter
- val optionalOrRequiredText = fragment.buildOptionalOrRequiredText()
val permissionList = fragment.buildPermissionsList()
+ val optionalOrRequiredText = fragment.buildOptionalOrRequiredText(hasPermissions = permissionList.isNotEmpty())
assertTrue(titleTextView.text.contains(name))
assertTrue(optionalOrRequiredText.contains(testContext.getString(R.string.mozac_feature_addons_permissions_dialog_subtitle)))
@@ -153,12 +153,12 @@ class PermissionsDialogFragmentTest {
val optionalOrRequiredTextView = dialog.findViewById<TextView>(R.id.optional_or_required_text)
val permissionsRecyclerView = dialog.findViewById<RecyclerView>(R.id.permissions)
val recyclerAdapter = permissionsRecyclerView.adapter!! as RequiredPermissionsAdapter
- val optionalOrRequiredText = fragment.buildOptionalOrRequiredText()
val permissionList = fragment.buildPermissionsList()
+ val optionalOrRequiredText = fragment.buildOptionalOrRequiredText(hasPermissions = permissionList.isNotEmpty())
assertTrue(titleTextView.text.contains(name))
- assertTrue(optionalOrRequiredText.contains(testContext.getString(R.string.mozac_feature_addons_permissions_dialog_subtitle)))
- assertTrue(optionalOrRequiredTextView.text.contains(testContext.getString(R.string.mozac_feature_addons_permissions_dialog_subtitle)))
+ assertFalse(optionalOrRequiredText.contains(testContext.getString(R.string.mozac_feature_addons_permissions_dialog_subtitle)))
+ assertFalse(optionalOrRequiredTextView.text.contains(testContext.getString(R.string.mozac_feature_addons_permissions_dialog_subtitle)))
assertEquals(0, recyclerAdapter.itemCount)
assertFalse(permissionList.contains(testContext.getString(R.string.mozac_feature_addons_permissions_privacy_description)))
assertFalse(permissionList.contains(testContext.getString(R.string.mozac_feature_addons_permissions_all_urls_description)))
@@ -185,8 +185,8 @@ class PermissionsDialogFragmentTest {
val recyclerAdapter = permissionsRecyclerView.adapter!! as RequiredPermissionsAdapter
val allowButton = dialog.findViewById<Button>(R.id.allow_button)
val denyButton = dialog.findViewById<Button>(R.id.deny_button)
- val optionalOrRequiredText = fragment.buildOptionalOrRequiredText()
val permissionsList = fragment.buildPermissionsList()
+ val optionalOrRequiredText = fragment.buildOptionalOrRequiredText(hasPermissions = permissionsList.isNotEmpty())
assertEquals(
titleTextView.text,
diff --git a/mobile/android/android-components/components/feature/addons/src/test/resources/amo_search_localized_single_result.json b/mobile/android/android-components/components/feature/addons/src/test/resources/amo_search_localized_single_result.json
index 94aeed1f64..5bae00d2f6 100644
--- a/mobile/android/android-components/components/feature/addons/src/test/resources/amo_search_localized_single_result.json
+++ b/mobile/android/android-components/components/feature/addons/src/test/resources/amo_search_localized_single_result.json
@@ -17,12 +17,8 @@
],
"average_daily_users": 6229783,
"categories": {
- "android": [
- "security-privacy"
- ],
- "firefox": [
- "privacy-security"
- ]
+ "android": ["security-privacy"],
+ "firefox": ["privacy-security"]
},
"contributions_url": "",
"created": "2015-04-25T07:26:22Z",
@@ -110,93 +106,54 @@
{
"id": 238546,
"caption": "The popup panel: default mode",
- "image_size": [
- 1011,
- 758
- ],
+ "image_size": [1011, 758],
"image_url": "https://addons.mozilla.org/user-media/previews/full/238/238546.png?modified=1622132421",
- "thumbnail_size": [
- 533,
- 400
- ],
+ "thumbnail_size": [533, 400],
"thumbnail_url": "https://addons.mozilla.org/user-media/previews/thumbs/238/238546.jpg?modified=1622132421"
},
{
"id": 238548,
"caption": "The dashboard: stock filter lists",
- "image_size": [
- 1011,
- 758
- ],
+ "image_size": [1011, 758],
"image_url": "https://addons.mozilla.org/user-media/previews/full/238/238548.png?modified=1622132423",
- "thumbnail_size": [
- 533,
- 400
- ],
+ "thumbnail_size": [533, 400],
"thumbnail_url": "https://addons.mozilla.org/user-media/previews/thumbs/238/238548.jpg?modified=1622132423"
},
{
"id": 238547,
"caption": "The popup panel: default-deny mode",
- "image_size": [
- 1011,
- 758
- ],
+ "image_size": [1011, 758],
"image_url": "https://addons.mozilla.org/user-media/previews/full/238/238547.png?modified=1622132425",
- "thumbnail_size": [
- 533,
- 400
- ],
+ "thumbnail_size": [533, 400],
"thumbnail_url": "https://addons.mozilla.org/user-media/previews/thumbs/238/238547.jpg?modified=1622132425"
},
{
"id": 238549,
"caption": "The dashboard: settings",
- "image_size": [
- 1011,
- 758
- ],
+ "image_size": [1011, 758],
"image_url": "https://addons.mozilla.org/user-media/previews/full/238/238549.png?modified=1622132426",
- "thumbnail_size": [
- 533,
- 400
- ],
+ "thumbnail_size": [533, 400],
"thumbnail_url": "https://addons.mozilla.org/user-media/previews/thumbs/238/238549.jpg?modified=1622132426"
},
{
"id": 238552,
"caption": "The popup panel in Firefox Preview: default mode with more blocking options revealed",
- "image_size": [
- 970,
- 1800
- ],
+ "image_size": [970, 1800],
"image_url": "https://addons.mozilla.org/user-media/previews/full/238/238552.png?modified=1622132430",
- "thumbnail_size": [
- 216,
- 400
- ],
+ "thumbnail_size": [216, 400],
"thumbnail_url": "https://addons.mozilla.org/user-media/previews/thumbs/238/238552.jpg?modified=1622132430"
},
{
"id": 230370,
"caption": "The unified logger tells you all that uBO is seeing and doing",
- "image_size": [
- 800,
- 600
- ],
+ "image_size": [800, 600],
"image_url": "https://addons.mozilla.org/user-media/previews/full/230/230370.png?modified=1622132432",
- "thumbnail_size": [
- 533,
- 400
- ],
+ "thumbnail_size": [533, 400],
"thumbnail_url": "https://addons.mozilla.org/user-media/previews/thumbs/230/230370.jpg?modified=1622132432"
}
],
"promoted": {
- "apps": [
- "firefox",
- "android"
- ],
+ "apps": ["firefox", "android"],
"category": "recommended"
},
"ratings": {
diff --git a/mobile/android/android-components/components/feature/addons/src/test/resources/amo_search_multiple_results.json b/mobile/android/android-components/components/feature/addons/src/test/resources/amo_search_multiple_results.json
index 8d0b13dad1..30b0a8fc6b 100644
--- a/mobile/android/android-components/components/feature/addons/src/test/resources/amo_search_multiple_results.json
+++ b/mobile/android/android-components/components/feature/addons/src/test/resources/amo_search_multiple_results.json
@@ -17,12 +17,8 @@
],
"average_daily_users": 6229783,
"categories": {
- "android": [
- "security-privacy"
- ],
- "firefox": [
- "privacy-security"
- ]
+ "android": ["security-privacy"],
+ "firefox": ["privacy-security"]
},
"contributions_url": "",
"created": "2015-04-25T07:26:22Z",
@@ -192,15 +188,9 @@
"caption": {
"en-US": "The popup panel: default mode"
},
- "image_size": [
- 1011,
- 758
- ],
+ "image_size": [1011, 758],
"image_url": "https://addons.mozilla.org/user-media/previews/full/238/238546.png?modified=1622132421",
- "thumbnail_size": [
- 533,
- 400
- ],
+ "thumbnail_size": [533, 400],
"thumbnail_url": "https://addons.mozilla.org/user-media/previews/thumbs/238/238546.jpg?modified=1622132421"
},
{
@@ -208,15 +198,9 @@
"caption": {
"en-US": "The dashboard: stock filter lists"
},
- "image_size": [
- 1011,
- 758
- ],
+ "image_size": [1011, 758],
"image_url": "https://addons.mozilla.org/user-media/previews/full/238/238548.png?modified=1622132423",
- "thumbnail_size": [
- 533,
- 400
- ],
+ "thumbnail_size": [533, 400],
"thumbnail_url": "https://addons.mozilla.org/user-media/previews/thumbs/238/238548.jpg?modified=1622132423"
},
{
@@ -224,15 +208,9 @@
"caption": {
"en-US": "The popup panel: default-deny mode"
},
- "image_size": [
- 1011,
- 758
- ],
+ "image_size": [1011, 758],
"image_url": "https://addons.mozilla.org/user-media/previews/full/238/238547.png?modified=1622132425",
- "thumbnail_size": [
- 533,
- 400
- ],
+ "thumbnail_size": [533, 400],
"thumbnail_url": "https://addons.mozilla.org/user-media/previews/thumbs/238/238547.jpg?modified=1622132425"
},
{
@@ -240,15 +218,9 @@
"caption": {
"en-US": "The dashboard: settings"
},
- "image_size": [
- 1011,
- 758
- ],
+ "image_size": [1011, 758],
"image_url": "https://addons.mozilla.org/user-media/previews/full/238/238549.png?modified=1622132426",
- "thumbnail_size": [
- 533,
- 400
- ],
+ "thumbnail_size": [533, 400],
"thumbnail_url": "https://addons.mozilla.org/user-media/previews/thumbs/238/238549.jpg?modified=1622132426"
},
{
@@ -256,15 +228,9 @@
"caption": {
"en-US": "The popup panel in Firefox Preview: default mode with more blocking options revealed"
},
- "image_size": [
- 970,
- 1800
- ],
+ "image_size": [970, 1800],
"image_url": "https://addons.mozilla.org/user-media/previews/full/238/238552.png?modified=1622132430",
- "thumbnail_size": [
- 216,
- 400
- ],
+ "thumbnail_size": [216, 400],
"thumbnail_url": "https://addons.mozilla.org/user-media/previews/thumbs/238/238552.jpg?modified=1622132430"
},
{
@@ -272,23 +238,14 @@
"caption": {
"en-US": "The unified logger tells you all that uBO is seeing and doing"
},
- "image_size": [
- 800,
- 600
- ],
+ "image_size": [800, 600],
"image_url": "https://addons.mozilla.org/user-media/previews/full/230/230370.png?modified=1622132432",
- "thumbnail_size": [
- 533,
- 400
- ],
+ "thumbnail_size": [533, 400],
"thumbnail_url": "https://addons.mozilla.org/user-media/previews/thumbs/230/230370.jpg?modified=1622132432"
}
],
"promoted": {
- "apps": [
- "firefox",
- "android"
- ],
+ "apps": ["firefox", "android"],
"category": "recommended"
},
"ratings": {
@@ -378,12 +335,8 @@
],
"average_daily_users": 111124,
"categories": {
- "android": [
- "other"
- ],
- "firefox": [
- "search-tools"
- ]
+ "android": ["other"],
+ "firefox": ["search-tools"]
},
"contributions_url": "",
"created": "2017-10-31T15:35:56Z",
@@ -653,9 +606,7 @@
},
"previews": [],
"promoted": {
- "apps": [
- "android"
- ],
+ "apps": ["android"],
"category": "recommended"
},
"ratings": {
diff --git a/mobile/android/android-components/components/feature/addons/src/test/resources/amo_search_single_result.json b/mobile/android/android-components/components/feature/addons/src/test/resources/amo_search_single_result.json
index b6a3a79892..1bc5ba8b99 100644
--- a/mobile/android/android-components/components/feature/addons/src/test/resources/amo_search_single_result.json
+++ b/mobile/android/android-components/components/feature/addons/src/test/resources/amo_search_single_result.json
@@ -17,12 +17,8 @@
],
"average_daily_users": 6229783,
"categories": {
- "android": [
- "security-privacy"
- ],
- "firefox": [
- "privacy-security"
- ]
+ "android": ["security-privacy"],
+ "firefox": ["privacy-security"]
},
"contributions_url": "",
"created": "2015-04-25T07:26:22Z",
@@ -192,15 +188,9 @@
"caption": {
"en-US": "The popup panel: default mode"
},
- "image_size": [
- 1011,
- 758
- ],
+ "image_size": [1011, 758],
"image_url": "https://addons.mozilla.org/user-media/previews/full/238/238546.png?modified=1622132421",
- "thumbnail_size": [
- 533,
- 400
- ],
+ "thumbnail_size": [533, 400],
"thumbnail_url": "https://addons.mozilla.org/user-media/previews/thumbs/238/238546.jpg?modified=1622132421"
},
{
@@ -208,15 +198,9 @@
"caption": {
"en-US": "The dashboard: stock filter lists"
},
- "image_size": [
- 1011,
- 758
- ],
+ "image_size": [1011, 758],
"image_url": "https://addons.mozilla.org/user-media/previews/full/238/238548.png?modified=1622132423",
- "thumbnail_size": [
- 533,
- 400
- ],
+ "thumbnail_size": [533, 400],
"thumbnail_url": "https://addons.mozilla.org/user-media/previews/thumbs/238/238548.jpg?modified=1622132423"
},
{
@@ -224,15 +208,9 @@
"caption": {
"en-US": "The popup panel: default-deny mode"
},
- "image_size": [
- 1011,
- 758
- ],
+ "image_size": [1011, 758],
"image_url": "https://addons.mozilla.org/user-media/previews/full/238/238547.png?modified=1622132425",
- "thumbnail_size": [
- 533,
- 400
- ],
+ "thumbnail_size": [533, 400],
"thumbnail_url": "https://addons.mozilla.org/user-media/previews/thumbs/238/238547.jpg?modified=1622132425"
},
{
@@ -240,15 +218,9 @@
"caption": {
"en-US": "The dashboard: settings"
},
- "image_size": [
- 1011,
- 758
- ],
+ "image_size": [1011, 758],
"image_url": "https://addons.mozilla.org/user-media/previews/full/238/238549.png?modified=1622132426",
- "thumbnail_size": [
- 533,
- 400
- ],
+ "thumbnail_size": [533, 400],
"thumbnail_url": "https://addons.mozilla.org/user-media/previews/thumbs/238/238549.jpg?modified=1622132426"
},
{
@@ -256,15 +228,9 @@
"caption": {
"en-US": "The popup panel in Firefox Preview: default mode with more blocking options revealed"
},
- "image_size": [
- 970,
- 1800
- ],
+ "image_size": [970, 1800],
"image_url": "https://addons.mozilla.org/user-media/previews/full/238/238552.png?modified=1622132430",
- "thumbnail_size": [
- 216,
- 400
- ],
+ "thumbnail_size": [216, 400],
"thumbnail_url": "https://addons.mozilla.org/user-media/previews/thumbs/238/238552.jpg?modified=1622132430"
},
{
@@ -272,23 +238,14 @@
"caption": {
"en-US": "The unified logger tells you all that uBO is seeing and doing"
},
- "image_size": [
- 800,
- 600
- ],
+ "image_size": [800, 600],
"image_url": "https://addons.mozilla.org/user-media/previews/full/230/230370.png?modified=1622132432",
- "thumbnail_size": [
- 533,
- 400
- ],
+ "thumbnail_size": [533, 400],
"thumbnail_url": "https://addons.mozilla.org/user-media/previews/thumbs/230/230370.jpg?modified=1622132432"
}
],
"promoted": {
- "apps": [
- "firefox",
- "android"
- ],
+ "apps": ["firefox", "android"],
"category": "recommended"
},
"ratings": {
diff --git a/mobile/android/android-components/components/feature/addons/src/test/resources/collection.json b/mobile/android/android-components/components/feature/addons/src/test/resources/collection.json
index a337ed148f..15d7ab9d40 100644
--- a/mobile/android/android-components/components/feature/addons/src/test/resources/collection.json
+++ b/mobile/android/android-components/components/feature/addons/src/test/resources/collection.json
@@ -18,12 +18,8 @@
],
"average_daily_users": 6229783,
"categories": {
- "android": [
- "security-privacy"
- ],
- "firefox": [
- "privacy-security"
- ]
+ "android": ["security-privacy"],
+ "firefox": ["privacy-security"]
},
"contributions_url": "",
"created": "2015-04-25T07:26:22Z",
@@ -193,15 +189,9 @@
"caption": {
"en-US": "The popup panel: default mode"
},
- "image_size": [
- 1011,
- 758
- ],
+ "image_size": [1011, 758],
"image_url": "https://addons.mozilla.org/user-media/previews/full/238/238546.png?modified=1622132421",
- "thumbnail_size": [
- 533,
- 400
- ],
+ "thumbnail_size": [533, 400],
"thumbnail_url": "https://addons.mozilla.org/user-media/previews/thumbs/238/238546.jpg?modified=1622132421"
},
{
@@ -209,15 +199,9 @@
"caption": {
"en-US": "The dashboard: stock filter lists"
},
- "image_size": [
- 1011,
- 758
- ],
+ "image_size": [1011, 758],
"image_url": "https://addons.mozilla.org/user-media/previews/full/238/238548.png?modified=1622132423",
- "thumbnail_size": [
- 533,
- 400
- ],
+ "thumbnail_size": [533, 400],
"thumbnail_url": "https://addons.mozilla.org/user-media/previews/thumbs/238/238548.jpg?modified=1622132423"
},
{
@@ -225,15 +209,9 @@
"caption": {
"en-US": "The popup panel: default-deny mode"
},
- "image_size": [
- 1011,
- 758
- ],
+ "image_size": [1011, 758],
"image_url": "https://addons.mozilla.org/user-media/previews/full/238/238547.png?modified=1622132425",
- "thumbnail_size": [
- 533,
- 400
- ],
+ "thumbnail_size": [533, 400],
"thumbnail_url": "https://addons.mozilla.org/user-media/previews/thumbs/238/238547.jpg?modified=1622132425"
},
{
@@ -241,15 +219,9 @@
"caption": {
"en-US": "The dashboard: settings"
},
- "image_size": [
- 1011,
- 758
- ],
+ "image_size": [1011, 758],
"image_url": "https://addons.mozilla.org/user-media/previews/full/238/238549.png?modified=1622132426",
- "thumbnail_size": [
- 533,
- 400
- ],
+ "thumbnail_size": [533, 400],
"thumbnail_url": "https://addons.mozilla.org/user-media/previews/thumbs/238/238549.jpg?modified=1622132426"
},
{
@@ -257,15 +229,9 @@
"caption": {
"en-US": "The popup panel in Firefox Preview: default mode with more blocking options revealed"
},
- "image_size": [
- 970,
- 1800
- ],
+ "image_size": [970, 1800],
"image_url": "https://addons.mozilla.org/user-media/previews/full/238/238552.png?modified=1622132430",
- "thumbnail_size": [
- 216,
- 400
- ],
+ "thumbnail_size": [216, 400],
"thumbnail_url": "https://addons.mozilla.org/user-media/previews/thumbs/238/238552.jpg?modified=1622132430"
},
{
@@ -273,23 +239,14 @@
"caption": {
"en-US": "The unified logger tells you all that uBO is seeing and doing"
},
- "image_size": [
- 800,
- 600
- ],
+ "image_size": [800, 600],
"image_url": "https://addons.mozilla.org/user-media/previews/full/230/230370.png?modified=1622132432",
- "thumbnail_size": [
- 533,
- 400
- ],
+ "thumbnail_size": [533, 400],
"thumbnail_url": "https://addons.mozilla.org/user-media/previews/thumbs/230/230370.jpg?modified=1622132432"
}
],
"promoted": {
- "apps": [
- "firefox",
- "android"
- ],
+ "apps": ["firefox", "android"],
"category": "recommended"
},
"ratings": {
diff --git a/mobile/android/android-components/components/feature/addons/src/test/resources/collection_with_empty_values.json b/mobile/android/android-components/components/feature/addons/src/test/resources/collection_with_empty_values.json
index fedd44adec..956247cfa1 100644
--- a/mobile/android/android-components/components/feature/addons/src/test/resources/collection_with_empty_values.json
+++ b/mobile/android/android-components/components/feature/addons/src/test/resources/collection_with_empty_values.json
@@ -162,15 +162,9 @@
"caption": {
"en-US": "Default mode"
},
- "image_size": [
- 640,
- 480
- ],
+ "image_size": [640, 480],
"image_url": "https://addons.cdn.mozilla.net/user-media/previews/full/157/157572.png?modified=1543520531",
- "thumbnail_size": [
- 640,
- 480
- ],
+ "thumbnail_size": [640, 480],
"thumbnail_url": "https://addons.cdn.mozilla.net/user-media/previews/thumbs/157/157572.png?modified=1543520531"
},
{
@@ -178,15 +172,9 @@
"caption": {
"en-US": "The dashboard: stock filter lists"
},
- "image_size": [
- 640,
- 480
- ],
+ "image_size": [640, 480],
"image_url": "https://addons.cdn.mozilla.net/user-media/previews/full/157/157576.png?modified=1543520531",
- "thumbnail_size": [
- 640,
- 480
- ],
+ "thumbnail_size": [640, 480],
"thumbnail_url": "https://addons.cdn.mozilla.net/user-media/previews/thumbs/157/157576.png?modified=1543520531"
},
{
@@ -194,15 +182,9 @@
"caption": {
"en-US": "Dynamic filtering allows default-deny mode"
},
- "image_size": [
- 640,
- 480
- ],
+ "image_size": [640, 480],
"image_url": "https://addons.cdn.mozilla.net/user-media/previews/full/157/157592.png?modified=1543520532",
- "thumbnail_size": [
- 640,
- 480
- ],
+ "thumbnail_size": [640, 480],
"thumbnail_url": "https://addons.cdn.mozilla.net/user-media/previews/thumbs/157/157592.png?modified=1543520532"
},
{
@@ -210,15 +192,9 @@
"caption": {
"en-US": "The dashboard: settings"
},
- "image_size": [
- 640,
- 480
- ],
+ "image_size": [640, 480],
"image_url": "https://addons.cdn.mozilla.net/user-media/previews/full/159/159634.png?modified=1543520533",
- "thumbnail_size": [
- 640,
- 480
- ],
+ "thumbnail_size": [640, 480],
"thumbnail_url": "https://addons.cdn.mozilla.net/user-media/previews/thumbs/159/159634.png?modified=1543520533"
},
{
@@ -226,15 +202,9 @@
"caption": {
"en-US": "Unified logger"
},
- "image_size": [
- 700,
- 525
- ],
+ "image_size": [700, 525],
"image_url": "https://addons.cdn.mozilla.net/user-media/previews/full/158/158734.png?modified=1543520534",
- "thumbnail_size": [
- 640,
- 480
- ],
+ "thumbnail_size": [640, 480],
"thumbnail_url": "https://addons.cdn.mozilla.net/user-media/previews/thumbs/158/158734.png?modified=1543520534"
}
],
diff --git a/mobile/android/android-components/components/feature/addons/src/test/resources/localized_collection.json b/mobile/android/android-components/components/feature/addons/src/test/resources/localized_collection.json
index db7a59ad18..1e2a5ffbb8 100644
--- a/mobile/android/android-components/components/feature/addons/src/test/resources/localized_collection.json
+++ b/mobile/android/android-components/components/feature/addons/src/test/resources/localized_collection.json
@@ -19,12 +19,8 @@
],
"average_daily_users": 5060298,
"categories": {
- "android": [
- "security-privacy"
- ],
- "firefox": [
- "privacy-security"
- ]
+ "android": ["security-privacy"],
+ "firefox": ["privacy-security"]
},
"contributions_url": "",
"created": "2015-04-25T07:26:22Z",
@@ -110,93 +106,54 @@
{
"id": 238546,
"caption": "The popup panel: default mode",
- "image_size": [
- 1011,
- 758
- ],
+ "image_size": [1011, 758],
"image_url": "https://addons.cdn.mozilla.net/user-media/previews/full/238/238546.png?modified=1590420038",
- "thumbnail_size": [
- 640,
- 480
- ],
+ "thumbnail_size": [640, 480],
"thumbnail_url": "https://addons.cdn.mozilla.net/user-media/previews/thumbs/238/238546.png?modified=1590420038"
},
{
"id": 238548,
"caption": "The dashboard: stock filter lists",
- "image_size": [
- 1011,
- 758
- ],
+ "image_size": [1011, 758],
"image_url": "https://addons.cdn.mozilla.net/user-media/previews/full/238/238548.png?modified=1590420038",
- "thumbnail_size": [
- 640,
- 480
- ],
+ "thumbnail_size": [640, 480],
"thumbnail_url": "https://addons.cdn.mozilla.net/user-media/previews/thumbs/238/238548.png?modified=1590420038"
},
{
"id": 238547,
"caption": "The popup panel: default-deny mode",
- "image_size": [
- 1011,
- 758
- ],
+ "image_size": [1011, 758],
"image_url": "https://addons.cdn.mozilla.net/user-media/previews/full/238/238547.png?modified=1590420038",
- "thumbnail_size": [
- 640,
- 480
- ],
+ "thumbnail_size": [640, 480],
"thumbnail_url": "https://addons.cdn.mozilla.net/user-media/previews/thumbs/238/238547.png?modified=1590420038"
},
{
"id": 238549,
"caption": "The dashboard: settings",
- "image_size": [
- 1011,
- 758
- ],
+ "image_size": [1011, 758],
"image_url": "https://addons.cdn.mozilla.net/user-media/previews/full/238/238549.png?modified=1590420038",
- "thumbnail_size": [
- 640,
- 480
- ],
+ "thumbnail_size": [640, 480],
"thumbnail_url": "https://addons.cdn.mozilla.net/user-media/previews/thumbs/238/238549.png?modified=1590420038"
},
{
"id": 238552,
"caption": "The popup panel in Firefox Preview: default mode with more blocking options revealed",
- "image_size": [
- 970,
- 1800
- ],
+ "image_size": [970, 1800],
"image_url": "https://addons.cdn.mozilla.net/user-media/previews/full/238/238552.png?modified=1590420044",
- "thumbnail_size": [
- 259,
- 480
- ],
+ "thumbnail_size": [259, 480],
"thumbnail_url": "https://addons.cdn.mozilla.net/user-media/previews/thumbs/238/238552.png?modified=1590420044"
},
{
"id": 230370,
"caption": "The unified logger tells you all that uBO is seeing and doing",
- "image_size": [
- 800,
- 600
- ],
+ "image_size": [800, 600],
"image_url": "https://addons.cdn.mozilla.net/user-media/previews/full/230/230370.png?modified=1590420038",
- "thumbnail_size": [
- 640,
- 480
- ],
+ "thumbnail_size": [640, 480],
"thumbnail_url": "https://addons.cdn.mozilla.net/user-media/previews/thumbs/230/230370.png?modified=1590420038"
}
],
"promoted": {
- "apps": [
- "firefox",
- "android"
- ],
+ "apps": ["firefox", "android"],
"category": "recommended"
},
"ratings": {
diff --git a/mobile/android/android-components/components/feature/app-links/src/main/res/values-sk/strings.xml b/mobile/android/android-components/components/feature/app-links/src/main/res/values-sk/strings.xml
index 0dbc181a50..3896b8371c 100644
--- a/mobile/android/android-components/components/feature/app-links/src/main/res/values-sk/strings.xml
+++ b/mobile/android/android-components/components/feature/app-links/src/main/res/values-sk/strings.xml
@@ -8,7 +8,7 @@
<string name="mozac_feature_applinks_normal_confirm_dialog_title">Otvoriť v inej aplikácii</string>
<!-- The message of the prompt to confirm with users that they want to open the link in another app
%s is a placeholder that will be replaced by the app name -->
- <string name="mozac_feature_applinks_normal_confirm_dialog_message">Chcete tento obsah zobraziť v aplikácii %s?</string>
+ <string name="mozac_feature_applinks_normal_confirm_dialog_message">Chcete opustiť %s a zobraziť tento obsah v aplikácii?</string>
<!-- Opens the selected time -->
<string name="mozac_feature_applinks_confirm_dialog_confirm">Otvoriť</string>
<!-- Cancels the prompt -->
diff --git a/mobile/android/android-components/components/feature/contextmenu/build.gradle b/mobile/android/android-components/components/feature/contextmenu/build.gradle
index f1ab6e0b64..a202c5bed9 100644
--- a/mobile/android/android-components/components/feature/contextmenu/build.gradle
+++ b/mobile/android/android-components/components/feature/contextmenu/build.gradle
@@ -41,6 +41,7 @@ dependencies {
implementation ComponentsDependencies.google_material
implementation ComponentsDependencies.androidx_constraintlayout
+ implementation ComponentsDependencies.androidx_core_ktx
testImplementation ComponentsDependencies.androidx_test_core
testImplementation ComponentsDependencies.androidx_test_junit
diff --git a/mobile/android/android-components/components/feature/downloads/src/main/java/mozilla/components/feature/downloads/DownloadMiddleware.kt b/mobile/android/android-components/components/feature/downloads/src/main/java/mozilla/components/feature/downloads/DownloadMiddleware.kt
index c7e480e038..ac5563aebb 100644
--- a/mobile/android/android-components/components/feature/downloads/src/main/java/mozilla/components/feature/downloads/DownloadMiddleware.kt
+++ b/mobile/android/android-components/components/feature/downloads/src/main/java/mozilla/components/feature/downloads/DownloadMiddleware.kt
@@ -27,6 +27,8 @@ import mozilla.components.feature.downloads.AbstractFetchDownloadService.Compani
import mozilla.components.lib.state.Middleware
import mozilla.components.lib.state.MiddlewareContext
import mozilla.components.lib.state.Store
+import mozilla.components.support.base.android.DefaultPowerManagerInfoProvider
+import mozilla.components.support.base.android.StartForegroundService
import mozilla.components.support.base.log.logger.Logger
import kotlin.coroutines.CoroutineContext
@@ -42,6 +44,9 @@ class DownloadMiddleware(
coroutineContext: CoroutineContext = Dispatchers.IO,
@get:VisibleForTesting
internal val downloadStorage: DownloadStorage = DownloadStorage(applicationContext),
+ private val startForegroundService: StartForegroundService = StartForegroundService(
+ powerManagerInfoProvider = DefaultPowerManagerInfoProvider(applicationContext),
+ ),
) : Middleware<BrowserState, BrowserAction> {
private val logger = Logger("DownloadMiddleware")
@@ -164,7 +169,12 @@ class DownloadMiddleware(
@VisibleForTesting
internal fun startForegroundService(intent: Intent) {
- ContextCompat.startForegroundService(applicationContext, intent)
+ /**
+ * @see [StartForegroundService]
+ */
+ startForegroundService {
+ ContextCompat.startForegroundService(applicationContext, intent)
+ }
}
@VisibleForTesting
diff --git a/mobile/android/android-components/components/feature/downloads/src/main/java/mozilla/components/feature/downloads/DownloadNotification.kt b/mobile/android/android-components/components/feature/downloads/src/main/java/mozilla/components/feature/downloads/DownloadNotification.kt
index 9b9c9aa34c..95ef2b5eea 100644
--- a/mobile/android/android-components/components/feature/downloads/src/main/java/mozilla/components/feature/downloads/DownloadNotification.kt
+++ b/mobile/android/android-components/components/feature/downloads/src/main/java/mozilla/components/feature/downloads/DownloadNotification.kt
@@ -89,12 +89,17 @@ internal object DownloadNotification {
val percentCopied = downloadJobState.getPercent() ?: -1
return NotificationCompat.Builder(context, channelId)
+ .setStyle(
+ NotificationCompat.BigTextStyle()
+ .setBigContentTitle(downloadState.fileName)
+ .setSummaryText(downloadJobState.getProgress()),
+ )
.setSmallIcon(R.drawable.mozac_feature_download_ic_ongoing_download)
.setContentTitle(downloadState.fileName)
.setContentText(downloadJobState.getProgress())
.setColor(ContextCompat.getColor(context, notificationAccentColor))
.setCategory(NotificationCompat.CATEGORY_PROGRESS)
- .setProgress(DownloadNotification.PERCENTAGE_MULTIPLIER, percentCopied, isIndeterminate)
+ .setProgress(PERCENTAGE_MULTIPLIER, percentCopied, isIndeterminate)
.setOngoing(true)
.setWhen(downloadJobState.createdTime)
.setOnlyAlertOnce(true)
diff --git a/mobile/android/android-components/components/feature/downloads/src/main/res/values-ast/strings.xml b/mobile/android/android-components/components/feature/downloads/src/main/res/values-ast/strings.xml
index 5f9d21334a..ae218de9c4 100644
--- a/mobile/android/android-components/components/feature/downloads/src/main/res/values-ast/strings.xml
+++ b/mobile/android/android-components/components/feature/downloads/src/main/res/values-ast/strings.xml
@@ -43,9 +43,6 @@
<!-- Message that appears when trying to download with an external app fails. %1$s will be replaced with the name the external app. -->--&gt;
<string name="mozac_feature_downloads_unable_to_open_third_party_app">Nun ye posible abrir «%1$s»</string>
- <!-- Text for the info dialog when write to storage permissions have been denied but user tries to download a file. -->
- <string name="mozac_feature_downloads_write_external_storage_permissions_needed_message">Tienes de permitir l\'accesu a los ficheros ya al conteníu multimedia pa baxar ficheros. Vete a la configuración d\'Android, dempués a los permisos ya toca Permitir.</string>
-
<!-- Alert dialog confirmation before cancelling downloads, this is the title -->
<string name="mozac_feature_downloads_cancel_active_downloads_warning_content_title">¿Quies encaboxar les descargues privaes?</string>
<!-- Alert dialog confirmation before cancelling private downloads, this is the body. %1$s will be replaced with the name of the file. -->
diff --git a/mobile/android/android-components/components/feature/findinpage/build.gradle b/mobile/android/android-components/components/feature/findinpage/build.gradle
index 7abc2177d8..cd778154b7 100644
--- a/mobile/android/android-components/components/feature/findinpage/build.gradle
+++ b/mobile/android/android-components/components/feature/findinpage/build.gradle
@@ -35,6 +35,7 @@ dependencies {
implementation project(':ui-icons')
implementation ComponentsDependencies.androidx_constraintlayout
+ implementation ComponentsDependencies.androidx_core_ktx
testImplementation ComponentsDependencies.androidx_test_core
testImplementation ComponentsDependencies.androidx_test_junit
diff --git a/mobile/android/android-components/components/feature/media/build.gradle b/mobile/android/android-components/components/feature/media/build.gradle
index 650288778f..ee649638c8 100644
--- a/mobile/android/android-components/components/feature/media/build.gradle
+++ b/mobile/android/android-components/components/feature/media/build.gradle
@@ -44,6 +44,7 @@ dependencies {
implementation project(':support-utils')
implementation ComponentsDependencies.kotlin_coroutines
+ implementation ComponentsDependencies.androidx_core_ktx
implementation ComponentsDependencies.androidx_media
testImplementation project(':support-test')
diff --git a/mobile/android/android-components/components/feature/media/src/main/res/values-br/strings.xml b/mobile/android/android-components/components/feature/media/src/main/res/values-br/strings.xml
index 58beef7ee1..6cc864bb28 100644
--- a/mobile/android/android-components/components/feature/media/src/main/res/values-br/strings.xml
+++ b/mobile/android/android-components/components/feature/media/src/main/res/values-br/strings.xml
@@ -11,6 +11,25 @@
<string name="mozac_feature_media_sharing_camera_and_microphone">Gweredekaet eo ar cʼhamera hag ar glevell</string>
+ <!-- Text of notification shown when the device's camera is shared with a website (WebRTC) -->
+ <string name="mozac_feature_media_sharing_camera_text">Stokit evit digeriñ an ivinell a zo oc’h implij ho kamera.</string>
+ <!-- Text of notification shown when the device's microphone is shared with a website (WebRTC) -->
+ <string name="mozac_feature_media_sharing_microphone_text">Stokit evit digeriñ an ivinell a zo oc’h implij ho klevell.</string>
+ <!-- Text of notification shown when the device's camera and microphone is shared with a website (WebRTC) -->
+ <string name="mozac_feature_media_sharing_camera_and_microphone_text">Stokit evit digeriñ an ivinell a zo oc’h implij ho klevell hag ho kamera.</string>
+
+
+ <!-- Text of reminder notification shown when the device's camera is shared with a website (WebRTC). %1$s is a placeholder that will be replaced by the app name-->
+ <string name="mozac_feature_media_sharing_camera_reminder_text">Adc\'halv: Emañ %1$s oc’h implij ho kamera atav. Stokit evit digeriñ an ivinell.</string>
+ <!-- Text of reminder notification shown when the device's microphone is shared with a website (WebRTC) %1$s is a placeholder that will be replaced by the app name-->
+ <string name="mozac_feature_media_sharing_microphone_reminder_text" moz:RemovedIn="124" tools:ignore="UnusedResources">Adc\'halv: Emañ %1$s oc’h implij ho klevell atav. Stokit evit digeriñ an ivinell</string>
+ <!-- Text of reminder notification shown when the device's microphone is shared with a website (WebRTC) %1$s is a placeholder that will be replaced by the app name-->
+ <string name="mozac_feature_media_sharing_microphone_reminder_text_2">Adc’halv: %1$s a implij ho klevell c’hoazh. Stokit da zigeriñ an ivinell.</string>
+ <!-- Text of reminder notification shown when the device's camera and microphone is shared with a website (WebRTC) %1$s is a placeholder that will be replaced by the app name-->
+ <string name="mozac_feature_media_sharing_camera_and_microphone_reminder_text" moz:RemovedIn="124" tools:ignore="UnusedResources">Adc\'halv: Emañ %1$s oc’h implij ho klevell hag ho kamera atav. Stokit evit digeriñ an ivinell</string>
+ <!-- Text of reminder notification shown when the device's camera and microphone is shared with a website (WebRTC) %1$s is a placeholder that will be replaced by the app name-->
+ <string name="mozac_feature_media_sharing_camera_and_microphone_reminder_text_2">Adc\'halv: Emañ %1$s oc’h implij ho klevell hag ho kamera atav. Stokit evit digeriñ an ivinell</string>
+
<!--This is the title of the "play" action media shown in the media notification while web content is playing media. Clicking it will resume playing paused media. On most modern Android system only an icon is visible. But screen readers may read this title. -->
<string name="mozac_feature_media_notification_action_play">Lenn</string>
diff --git a/mobile/android/android-components/components/feature/media/src/main/res/values-nn-rNO/strings.xml b/mobile/android/android-components/components/feature/media/src/main/res/values-nn-rNO/strings.xml
index 54a2f5bb49..ecb0bf9ee5 100644
--- a/mobile/android/android-components/components/feature/media/src/main/res/values-nn-rNO/strings.xml
+++ b/mobile/android/android-components/components/feature/media/src/main/res/values-nn-rNO/strings.xml
@@ -27,6 +27,12 @@
<!-- Text of reminder notification shown when the device's microphone is shared with a website (WebRTC) %1$s is a placeholder that will be replaced by the app name-->
<string name="mozac_feature_media_sharing_microphone_reminder_text_2">Påminning: %1$s brukar framleis mikrofonen din. Trykk for å opne fana.</string>
+ <!-- Text of reminder notification shown when the device's camera and microphone is shared with a website (WebRTC) %1$s is a placeholder that will be replaced by the app name-->
+ <string name="mozac_feature_media_sharing_camera_and_microphone_reminder_text" moz:RemovedIn="124" tools:ignore="UnusedResources">Påminning: %1$s brukar framleis mikrofonen og kameraet ditt. Trykk for å opne fana</string>
+
+ <!-- Text of reminder notification shown when the device's camera and microphone is shared with a website (WebRTC) %1$s is a placeholder that will be replaced by the app name-->
+ <string name="mozac_feature_media_sharing_camera_and_microphone_reminder_text_2">Påminning: %1$s brukar framleis mikrofonen og kameraet ditt. Trykk for å opne fana.</string>
+
<!--This is the title of the "play" action media shown in the media notification while web content is playing media. Clicking it will resume playing paused media. On most modern Android system only an icon is visible. But screen readers may read this title. -->
<string name="mozac_feature_media_notification_action_play">Spel av</string>
diff --git a/mobile/android/android-components/components/feature/media/src/main/res/values-su/strings.xml b/mobile/android/android-components/components/feature/media/src/main/res/values-su/strings.xml
index 36d6141e58..f5ecda93ad 100644
--- a/mobile/android/android-components/components/feature/media/src/main/res/values-su/strings.xml
+++ b/mobile/android/android-components/components/feature/media/src/main/res/values-su/strings.xml
@@ -22,9 +22,14 @@
<!-- Text of reminder notification shown when the device's camera is shared with a website (WebRTC). %1$s is a placeholder that will be replaced by the app name-->
<string name="mozac_feature_media_sharing_camera_reminder_text">Panginget: %1$s maké kénéh kaméra anjeun. Toél pikeun muka tabna.</string>
<!-- Text of reminder notification shown when the device's microphone is shared with a website (WebRTC) %1$s is a placeholder that will be replaced by the app name-->
- <string name="mozac_feature_media_sharing_microphone_reminder_text">Panginget: %1$s maké kénéh mikropon anjeun. Toél pikeun muka tabna</string>
+ <string name="mozac_feature_media_sharing_microphone_reminder_text" moz:RemovedIn="124" tools:ignore="UnusedResources">Panginget: %1$s maké kénéh mikropon anjeun. Toél pikeun muka tabna</string>
+ <!-- Text of reminder notification shown when the device's microphone is shared with a website (WebRTC) %1$s is a placeholder that will be replaced by the app name-->
+ <string name="mozac_feature_media_sharing_microphone_reminder_text_2">Panginget: %1$s maké mikrofon anjeun kénéh. Pencét pikeun muka tab.</string>
+ <!-- Text of reminder notification shown when the device's camera and microphone is shared with a website (WebRTC) %1$s is a placeholder that will be replaced by the app name-->
+ <string name="mozac_feature_media_sharing_camera_and_microphone_reminder_text" moz:RemovedIn="124" tools:ignore="UnusedResources">Panginget: %1$s maké kénéh mikropon jeung kaméra anjeun. Toél pikeun muka tabna</string>
+
<!-- Text of reminder notification shown when the device's camera and microphone is shared with a website (WebRTC) %1$s is a placeholder that will be replaced by the app name-->
- <string name="mozac_feature_media_sharing_camera_and_microphone_reminder_text">Panginget: %1$s maké kénéh mikropon jeung kaméra anjeun. Toél pikeun muka tabna</string>
+ <string name="mozac_feature_media_sharing_camera_and_microphone_reminder_text_2">Panginget: %1$s maké kénéh mikropon jeung kaméra anjeun. Toél pikeun muka tabna</string>
<!--This is the title of the "play" action media shown in the media notification while web content is playing media. Clicking it will resume playing paused media. On most modern Android system only an icon is visible. But screen readers may read this title. -->
<string name="mozac_feature_media_notification_action_play">Ulinkeun</string>
diff --git a/mobile/android/android-components/components/feature/prompts/src/main/java/mozilla/components/feature/prompts/PromptFeature.kt b/mobile/android/android-components/components/feature/prompts/src/main/java/mozilla/components/feature/prompts/PromptFeature.kt
index 481b0e5ce3..768fddddb9 100644
--- a/mobile/android/android-components/components/feature/prompts/src/main/java/mozilla/components/feature/prompts/PromptFeature.kt
+++ b/mobile/android/android-components/components/feature/prompts/src/main/java/mozilla/components/feature/prompts/PromptFeature.kt
@@ -17,6 +17,7 @@ import kotlinx.coroutines.flow.map
import mozilla.components.browser.state.action.ContentAction
import mozilla.components.browser.state.selector.findTabOrCustomTab
import mozilla.components.browser.state.selector.findTabOrCustomTabOrSelectedTab
+import mozilla.components.browser.state.selector.selectedTab
import mozilla.components.browser.state.state.SessionState
import mozilla.components.browser.state.store.BrowserStore
import mozilla.components.concept.engine.prompt.Choice
@@ -100,6 +101,7 @@ import mozilla.components.support.base.feature.PermissionsFeature
import mozilla.components.support.base.feature.UserInteractionHandler
import mozilla.components.support.base.log.logger.Logger
import mozilla.components.support.ktx.kotlin.ifNullOrEmpty
+import mozilla.components.support.ktx.kotlin.tryGetHostFromUrl
import mozilla.components.support.ktx.kotlinx.coroutines.flow.ifAnyChanged
import java.lang.ref.WeakReference
import java.security.InvalidParameterException
@@ -134,6 +136,8 @@ internal const val FRAGMENT_TAG = "mozac_feature_prompt_dialog"
* a dialog (fragment).
* @property shareDelegate Delegate used to display share sheet.
* @property exitFullscreenUsecase Usecase allowing to exit browser tabs' fullscreen mode.
+ * @property isLoginAutofillEnabled A callback invoked before an autofill prompt is triggered. If false,
+ * 'autofill login' prompts will not be shown.
* @property isSaveLoginEnabled A callback invoked when a login prompt is triggered. If false,
* 'save login' prompts will not be shown.
* @property isCreditCardAutofillEnabled A callback invoked when credit card fields are detected in the webpage.
@@ -171,6 +175,7 @@ class PromptFeature private constructor(
private val exitFullscreenUsecase: ExitFullScreenUseCase = SessionUseCases(store).exitFullscreen,
override val creditCardValidationDelegate: CreditCardValidationDelegate? = null,
override val loginValidationDelegate: LoginValidationDelegate? = null,
+ private val isLoginAutofillEnabled: () -> Boolean = { false },
private val isSaveLoginEnabled: () -> Boolean = { false },
private val isCreditCardAutofillEnabled: () -> Boolean = { false },
private val isAddressAutofillEnabled: () -> Boolean = { false },
@@ -219,6 +224,7 @@ class PromptFeature private constructor(
exitFullscreenUsecase: ExitFullScreenUseCase = SessionUseCases(store).exitFullscreen,
creditCardValidationDelegate: CreditCardValidationDelegate? = null,
loginValidationDelegate: LoginValidationDelegate? = null,
+ isLoginAutofillEnabled: () -> Boolean = { false },
isSaveLoginEnabled: () -> Boolean = { false },
isCreditCardAutofillEnabled: () -> Boolean = { false },
isAddressAutofillEnabled: () -> Boolean = { false },
@@ -243,6 +249,7 @@ class PromptFeature private constructor(
exitFullscreenUsecase = exitFullscreenUsecase,
creditCardValidationDelegate = creditCardValidationDelegate,
loginValidationDelegate = loginValidationDelegate,
+ isLoginAutofillEnabled = isLoginAutofillEnabled,
isSaveLoginEnabled = isSaveLoginEnabled,
isCreditCardAutofillEnabled = isCreditCardAutofillEnabled,
isAddressAutofillEnabled = isAddressAutofillEnabled,
@@ -267,6 +274,7 @@ class PromptFeature private constructor(
exitFullscreenUsecase: ExitFullScreenUseCase = SessionUseCases(store).exitFullscreen,
creditCardValidationDelegate: CreditCardValidationDelegate? = null,
loginValidationDelegate: LoginValidationDelegate? = null,
+ isLoginAutofillEnabled: () -> Boolean = { false },
isSaveLoginEnabled: () -> Boolean = { false },
isCreditCardAutofillEnabled: () -> Boolean = { false },
isAddressAutofillEnabled: () -> Boolean = { false },
@@ -290,6 +298,7 @@ class PromptFeature private constructor(
exitFullscreenUsecase = exitFullscreenUsecase,
creditCardValidationDelegate = creditCardValidationDelegate,
loginValidationDelegate = loginValidationDelegate,
+ isLoginAutofillEnabled = isLoginAutofillEnabled,
isSaveLoginEnabled = isSaveLoginEnabled,
isCreditCardAutofillEnabled = isCreditCardAutofillEnabled,
isAddressAutofillEnabled = isAddressAutofillEnabled,
@@ -436,12 +445,12 @@ class PromptFeature private constructor(
}
}
- // Dismiss all prompts when page URL or session id changes. See Fenix#5326
+ // Dismiss all prompts when page host or session id changes. See Fenix#5326
dismissPromptScope = store.flowScoped { flow ->
flow.ifAnyChanged { state ->
arrayOf(
state.selectedTabId,
- state.findTabOrCustomTabOrSelectedTab(customTabId)?.content?.url,
+ state.findTabOrCustomTabOrSelectedTab(customTabId)?.content?.url?.tryGetHostFromUrl(),
)
}.collect {
dismissSelectPrompts()
@@ -559,17 +568,18 @@ class PromptFeature private constructor(
}
is SelectLoginPrompt -> {
- if (promptRequest.logins.isEmpty()) {
- if (isSuggestStrongPasswordEnabled) {
- val currentUrl =
- store.state.findTabOrCustomTabOrSelectedTab(customTabId)?.content?.url
- if (currentUrl != null) {
- strongPasswordPromptViewListener?.handleSuggestStrongPasswordRequest(
- promptRequest,
- currentUrl,
- onSaveLoginWithStrongPassword,
- )
- }
+ if (!isLoginAutofillEnabled()) {
+ return
+ }
+ if (promptRequest.generatedPassword != null && isSuggestStrongPasswordEnabled) {
+ val currentUrl =
+ store.state.findTabOrCustomTabOrSelectedTab(customTabId)?.content?.url
+ if (currentUrl != null) {
+ strongPasswordPromptViewListener?.handleSuggestStrongPasswordRequest(
+ promptRequest,
+ currentUrl,
+ onSaveLoginWithStrongPassword,
+ )
}
} else {
loginPicker?.handleSelectLoginRequest(promptRequest)
@@ -872,6 +882,7 @@ class PromptFeature private constructor(
inputLabel,
inputValue,
promptAbuserDetector.areDialogsBeingAbused(),
+ store.state.selectedTab?.content?.private == true,
)
}
}
diff --git a/mobile/android/android-components/components/feature/prompts/src/main/java/mozilla/components/feature/prompts/dialog/TextPromptDialogFragment.kt b/mobile/android/android-components/components/feature/prompts/src/main/java/mozilla/components/feature/prompts/dialog/TextPromptDialogFragment.kt
index 01492e96e4..41aeca796c 100644
--- a/mobile/android/android-components/components/feature/prompts/src/main/java/mozilla/components/feature/prompts/dialog/TextPromptDialogFragment.kt
+++ b/mobile/android/android-components/components/feature/prompts/src/main/java/mozilla/components/feature/prompts/dialog/TextPromptDialogFragment.kt
@@ -11,15 +11,18 @@ import android.os.Bundle
import android.text.Editable
import android.text.TextWatcher
import android.view.LayoutInflater
+import android.view.inputmethod.EditorInfo.IME_NULL
import android.widget.EditText
import android.widget.TextView
import androidx.appcompat.app.AlertDialog
+import androidx.core.view.inputmethod.EditorInfoCompat.IME_FLAG_NO_PERSONALIZED_LEARNING
import mozilla.components.feature.prompts.R
import mozilla.components.ui.widgets.withCenterAlignedButtons
private const val KEY_USER_EDIT_TEXT = "KEY_USER_EDIT_TEXT"
private const val KEY_LABEL_INPUT = "KEY_LABEL_INPUT"
private const val KEY_DEFAULT_INPUT_VALUE = "KEY_DEFAULT_INPUT_VALUE"
+private const val KEY_PRIVATE = "KEY_PRIVATE"
/**
* [androidx.fragment.app.DialogFragment] implementation to display a
@@ -38,6 +41,11 @@ internal class TextPromptDialogFragment : AbstractPromptTextDialogFragment(), Te
*/
internal val labelInput: String? by lazy { safeArguments.getString(KEY_LABEL_INPUT) }
+ /**
+ * Tells if the Dialog is shown from private browsing
+ */
+ internal val private: Boolean? by lazy { safeArguments.getBoolean(KEY_PRIVATE) }
+
private var userSelectionEditText: String
get() = safeArguments.getString(KEY_USER_EDIT_TEXT, defaultInputValue)
set(value) {
@@ -73,6 +81,7 @@ internal class TextPromptDialogFragment : AbstractPromptTextDialogFragment(), Te
label.text = labelInput
editText.setText(defaultInputValue)
editText.addTextChangedListener(this)
+ editText.imeOptions = if (private == true) IME_FLAG_NO_PERSONALIZED_LEARNING else IME_NULL
addCheckBoxIfNeeded(view)
@@ -100,7 +109,9 @@ internal class TextPromptDialogFragment : AbstractPromptTextDialogFragment(), Te
* @param hasShownManyDialogs tells if this [sessionId] has shown many dialogs
* in a short period of time, if is true a checkbox will be part of the dialog, for the user
* to choose if wants to prevent this [sessionId] continuing showing dialogs.
+ * @param private tells if this dialog is triggered from private browsing
*/
+ @Suppress("complexity:LongParameterList")
fun newInstance(
sessionId: String,
promptRequestUID: String,
@@ -109,6 +120,7 @@ internal class TextPromptDialogFragment : AbstractPromptTextDialogFragment(), Te
inputLabel: String,
defaultInputValue: String,
hasShownManyDialogs: Boolean,
+ private: Boolean,
): TextPromptDialogFragment {
val fragment = TextPromptDialogFragment()
val arguments = fragment.arguments ?: Bundle()
@@ -121,6 +133,7 @@ internal class TextPromptDialogFragment : AbstractPromptTextDialogFragment(), Te
putString(KEY_LABEL_INPUT, inputLabel)
putString(KEY_DEFAULT_INPUT_VALUE, defaultInputValue)
putBoolean(KEY_MANY_ALERTS, hasShownManyDialogs)
+ putBoolean(KEY_PRIVATE, private)
}
fragment.arguments = arguments
diff --git a/mobile/android/android-components/components/feature/prompts/src/main/res/values-br/strings.xml b/mobile/android/android-components/components/feature/prompts/src/main/res/values-br/strings.xml
index ee06036029..f7833ace0f 100644
--- a/mobile/android/android-components/components/feature/prompts/src/main/res/values-br/strings.xml
+++ b/mobile/android/android-components/components/feature/prompts/src/main/res/values-br/strings.xml
@@ -17,9 +17,9 @@
<!-- Text for password field in an authentication dialog. -->
<string name="mozac_feature_prompt_password_hint">Ger-tremen</string>
<!-- Negative confirmation that we should not save the new or updated login -->
- <string name="mozac_feature_prompt_dont_save">Na enrollañ</string>
+ <string name="mozac_feature_prompt_dont_save" moz:removedIn="125" tools:ignore="UnusedResources">Na enrollañ</string>
<!-- Negative confirmation that we should not save the new or updated login -->
- <string name="mozac_feature_prompt_dont_save_2" tools:ignore="UnusedResources">Diwezhatoc’h</string>
+ <string name="mozac_feature_prompt_dont_save_2">Diwezhatoc’h</string>
<!-- Negative confirmation that we should never save a login for this site -->
<string name="mozac_feature_prompt_never_save">Na enrollañ biken</string>
<!-- Negative confirmation that we should not save a credit card for this site -->
@@ -27,27 +27,27 @@
<!-- Positive confirmation that we should save the new or updated login -->
<string name="mozac_feature_prompt_save_confirmation">Enrollañ</string>
<!-- Negative confirmation that we should not save the updated login -->
- <string name="mozac_feature_prompt_dont_update">Na hizivaat</string>
+ <string name="mozac_feature_prompt_dont_update" moz:removedIn="125" tools:ignore="UnusedResources">Na hizivaat</string>
<!-- Negative confirmation that we should not save the updated login -->
- <string name="mozac_feature_prompt_dont_update_2" tools:ignore="UnusedResources">Diwezhatoc’h</string>
+ <string name="mozac_feature_prompt_dont_update_2">Diwezhatoc’h</string>
<!-- Positive confirmation that we should save the updated login -->
<string name="mozac_feature_prompt_update_confirmation">Hizivaat</string>
<!-- Error text displayed underneath the password field when it is in an error case -->
- <string name="mozac_feature_prompt_error_empty_password">Ar vaezienn ger-tremen a rank bezañ leuniet</string>
+ <string name="mozac_feature_prompt_error_empty_password" moz:removedIn="125" tools:ignore="UnusedResources">Ar vaezienn ger-tremen a rank bezañ leuniet</string>
<!-- Error text displayed underneath the password field when it is in an error case -->
- <string name="mozac_feature_prompt_error_empty_password_2" tools:ignore="UnusedResources">Enankit ur ger-tremen</string>
+ <string name="mozac_feature_prompt_error_empty_password_2">Enankit ur ger-tremen</string>
<!-- Error text displayed underneath the login field when it is in an error case -->
- <string name="mozac_feature_prompt_error_unknown_cause">Ne cʼhaller ket enrollañ an titour kennaskañ</string>
+ <string name="mozac_feature_prompt_error_unknown_cause" moz:removedIn="125" tools:ignore="UnusedResources">Ne cʼhaller ket enrollañ an titour kennaskañ</string>
<!-- Error text displayed underneath the password field when it is in an error case -->
- <string name="mozac_feature_prompt_error_unknown_cause_2" tools:ignore="UnusedResources">N’haller ket enrollañ ar ger-tremen</string>
+ <string name="mozac_feature_prompt_error_unknown_cause_2">N’haller ket enrollañ ar ger-tremen</string>
<!-- Prompt message displayed when app detects a user has entered a new username and password and user decides if app should save the new login. -->
- <string name="mozac_feature_prompt_login_save_headline">Enrollañ an titour kennaskañ-mañ?</string>
+ <string name="mozac_feature_prompt_login_save_headline" moz:removedIn="125" tools:ignore="UnusedResources">Enrollañ an titour kennaskañ-mañ?</string>
<!-- Prompt message displayed when app detects a user has entered a new username and password and user decides if app should save the new password. -->
- <string name="mozac_feature_prompt_login_save_headline_2" tools:ignore="UnusedResources">Enrollañ ar ger-tremen?</string>
+ <string name="mozac_feature_prompt_login_save_headline_2">Enrollañ ar ger-tremen?</string>
<!-- Prompt message displayed when app detects a user has entered a new password for an existing login and user decides if app should update the login. -->
- <string name="mozac_feature_prompt_login_update_headline">Hizivaat an titour kennaskañ-mañ?</string>
+ <string name="mozac_feature_prompt_login_update_headline" moz:removedIn="125" tools:ignore="UnusedResources">Hizivaat an titour kennaskañ-mañ?</string>
<!-- Prompt message displayed when app detects a user has entered a new password for an existing login and user decides if app should update the password. -->
- <string name="mozac_feature_prompt_login_update_headline_2" tools:ignore="UnusedResources">Hizivaat ar ger-tremen?</string>
+ <string name="mozac_feature_prompt_login_update_headline_2">Hizivaat ar ger-tremen?</string>
<!-- Prompt message displayed when app detects a user has entered a username for an existing login without a username and user decides if app should update the login. -->
<string name="mozac_feature_prompt_login_add_username_headline">Ouzhpennañ an anv arveriad dʼar gerioù-tremen enrollet?</string>
<!-- Text for a label for the field when prompt requesting a text is shown. -->
@@ -96,22 +96,29 @@
<!-- Title of the time picker dialog. -->
<string name="mozac_feature_prompts_set_time">Dibab an eur</string>
<!-- Option in expanded select login prompt that links to login settings -->
- <string name="mozac_feature_prompts_manage_logins">Ardoer titouroù kennaskañ</string>
+ <string name="mozac_feature_prompts_manage_logins" moz:removedIn="125" tools:ignore="UnusedResources">Ardoer titouroù kennaskañ</string>
<!-- Option in expanded select password prompt that links to password settings -->
- <string name="mozac_feature_prompts_manage_logins_2" tools:ignore="UnusedResources">Merañ ar gerioù-tremen</string>
+ <string name="mozac_feature_prompts_manage_logins_2">Merañ ar gerioù-tremen</string>
<!-- Content description for expanding the saved logins options in the select login prompt -->
- <string name="mozac_feature_prompts_expand_logins_content_description">Brasaat an titouroù kennaskañ aliet</string>
+ <string name="mozac_feature_prompts_expand_logins_content_description" moz:removedIn="125" tools:ignore="UnusedResources">Brasaat an titouroù kennaskañ aliet</string>
<!-- Content description for expanding the saved passwords options in the select password prompt -->
- <string name="mozac_feature_prompts_expand_logins_content_description_2" tools:ignore="UnusedResources">Dispakañ ar gerioù-tremen enrollet</string>
+ <string name="mozac_feature_prompts_expand_logins_content_description_2">Dispakañ ar gerioù-tremen enrollet</string>
<!-- Content description for collapsing the saved logins options in the select login prompt -->
- <string name="mozac_feature_prompts_collapse_logins_content_description">Berraat an titouroù kennaskañ aliet</string>
+ <string name="mozac_feature_prompts_collapse_logins_content_description" moz:removedIn="125" tools:ignore="UnusedResources">Berraat an titouroù kennaskañ aliet</string>
<!-- Content description for collapsing the saved passwords options in the select password prompt -->
- <string name="mozac_feature_prompts_collapse_logins_content_description_2" tools:ignore="UnusedResources">Kuzhat ar gerioù-tremen enrollet</string>
+ <string name="mozac_feature_prompts_collapse_logins_content_description_2">Kuzhat ar gerioù-tremen enrollet</string>
<!-- Header for the select login prompt to allow users to fill a form with a saved login -->
- <string name="mozac_feature_prompts_saved_logins">Titouroù kennaskañ aliet</string>
+ <string name="mozac_feature_prompts_saved_logins" moz:removedIn="125" tools:ignore="UnusedResources">Titouroù kennaskañ aliet</string>
<!-- Header for the select password prompt to allow users to fill a form with a saved password -->
- <string name="mozac_feature_prompts_saved_logins_2" tools:ignore="UnusedResources">Gerioù-tremen enrollet</string>
+ <string name="mozac_feature_prompts_saved_logins_2">Gerioù-tremen enrollet</string>
+
+ <!-- Content description for the suggest strong password prompt to allow users to fill a form with a suggested strong password -->
+ <string name="mozac_feature_prompts_suggest_strong_password_content_description">Kinnig ur ger-tremen kreñv</string>
+ <!-- Header for the suggest strong password prompt to allow users to fill a form with a suggested strong password -->
+ <string name="mozac_feature_prompts_suggest_strong_password">Kinnig ur ger-tremen kreñv</string>
+ <!-- Title for using the suggest strong password confirmation dialog. %1$s will be replaced with the generated password -->
+ <string name="mozac_feature_prompts_suggest_strong_password_message">Implij ur ger-tremen kreñv: %1$s</string>
<!-- Strings shown in a dialog that appear when users try to refresh a certain kind of webpages -->
<string name="mozac_feature_prompt_repost_title">Kas roadennoù en-dro d’al lec’hienn?</string>
@@ -123,38 +130,43 @@
<!-- Credit Card Autofill -->
<!-- Header for the select credit card prompt to allow users to fill a form with a saved credit card. -->
- <string name="mozac_feature_prompts_select_credit_card">Diuzañ ur gartenn gred</string>
+ <string name="mozac_feature_prompts_select_credit_card" moz:removedIn="125" tools:ignore="UnusedResources">Diuzañ ur gartenn gred</string>
+ <!-- Header for the select card prompt to allow users to fill a form with a saved card. -->
+ <string name="mozac_feature_prompts_select_credit_card_2">Ober gant ur gartenn enrollet</string>
<!-- Content description for expanding the select credit card options in the select credit card prompt. -->
- <string name="mozac_feature_prompts_expand_credit_cards_content_description">Astenn ar cʼhartennoù kred kinniget</string>
+ <string name="mozac_feature_prompts_expand_credit_cards_content_description" moz:removedIn="125" tools:ignore="UnusedResources">Astenn ar cʼhartennoù kred kinniget</string>
<!-- Content description for expanding the saved card options in the select card prompt. -->
- <string name="mozac_feature_prompts_expand_credit_cards_content_description_2" tools:ignore="UnusedResources">Dispakañ ar c’hartennoù enrollet</string>
+ <string name="mozac_feature_prompts_expand_credit_cards_content_description_2">Dispakañ ar c’hartennoù enrollet</string>
<!-- Content description for collapsing the select credit card options in the select credit prompt. -->
- <string name="mozac_feature_prompts_collapse_credit_cards_content_description">Bihanaat ar cʼhartennoù kred kinniget</string>
+ <string name="mozac_feature_prompts_collapse_credit_cards_content_description" moz:removedIn="125" tools:ignore="UnusedResources">Bihanaat ar cʼhartennoù kred kinniget</string>
<!-- Content description for collapsing the saved card options in the select prompt. -->
- <string name="mozac_feature_prompts_collapse_credit_cards_content_description_2" tools:ignore="UnusedResources">Kuzhat ar c’hartennoù enrollet</string>
+ <string name="mozac_feature_prompts_collapse_credit_cards_content_description_2">Kuzhat ar c’hartennoù enrollet</string>
<!-- Option in the expanded select credit card prompt that links to credit cards settings. -->
- <string name="mozac_feature_prompts_manage_credit_cards">Merañ ar cʼhartennoù kred</string>
+ <string name="mozac_feature_prompts_manage_credit_cards" moz:removedIn="125" tools:ignore="UnusedResources">Merañ ar cʼhartennoù kred</string>
<!-- Option in the expanded select card prompt that links to cards settings. -->
- <string name="mozac_feature_prompts_manage_credit_cards_2" tools:ignore="UnusedResources">Merañ ar c’hartennoù</string>
+ <string name="mozac_feature_prompts_manage_credit_cards_2">Merañ ar c’hartennoù</string>
<!-- Text for the title of a save credit card dialog. -->
<string name="mozac_feature_prompts_save_credit_card_prompt_title">Enrollañ ar gartenn-mañ en surentez?</string>
<!-- Text for the title of an update credit card dialog. -->
<string name="mozac_feature_prompts_update_credit_card_prompt_title">Hizivaat deiziad termen ar gartenn?</string>
<!-- Subtitle text displayed under the title of the save credit card dialog. -->
- <string name="mozac_feature_prompts_save_credit_card_prompt_body">Enrigenet e vo niverenn ar gartenn. Ne vo ket enrollet ar c’hod surentez.</string>
+ <string name="mozac_feature_prompts_save_credit_card_prompt_body" moz:removedIn="125" tools:ignore="UnusedResources">Enrigenet e vo niverenn ar gartenn. Ne vo ket enrollet ar c’hod surentez.</string>
+
+ <!-- Subtitle text displayed under the title of the saved card dialog. Parameter will be replaced by app name-->
+ <string name="mozac_feature_prompts_save_credit_card_prompt_body_2">%s a enrinego ho niverenn gartenn. Ne vo ket enrollet ho poneg surentez.</string>
<!-- Address Autofill -->
<!-- Header for the select address prompt to allow users to fill a form with a saved address. -->
<string name="mozac_feature_prompts_select_address_2">Dibab ur chomlec’h</string>
<!-- Content description for expanding the select addresses options in the select address prompt. -->
- <string name="mozac_feature_prompts_expand_address_content_description">Displegañ ar chomlec’hioù kinniget</string>
+ <string name="mozac_feature_prompts_expand_address_content_description" moz:removedIn="125" tools:ignore="UnusedResources">Displegañ ar chomlec’hioù kinniget</string>
<!-- Content description for expanding the saved addresses options in the select address prompt. -->
- <string name="mozac_feature_prompts_expand_address_content_description_2" tools:ignore="UnusedResources">Dispakañ ar chomlec’hioù enrollet</string>
+ <string name="mozac_feature_prompts_expand_address_content_description_2">Dispakañ ar chomlec’hioù enrollet</string>
<!-- Content description for collapsing the select address options in the select address prompt. -->
- <string name="mozac_feature_prompts_collapse_address_content_description">Plegañ ar chomlec’hioù kinniget</string>
+ <string name="mozac_feature_prompts_collapse_address_content_description" moz:removedIn="125" tools:ignore="UnusedResources">Plegañ ar chomlec’hioù kinniget</string>
<!-- Content description for collapsing the saved address options in the select address prompt. -->
- <string name="mozac_feature_prompts_collapse_address_content_description_2" tools:ignore="UnusedResources">Kuzhat ar chomlec’hioù enrollet</string>
+ <string name="mozac_feature_prompts_collapse_address_content_description_2">Kuzhat ar chomlec’hioù enrollet</string>
<!-- Text for the manage addresses button. -->
<string name="mozac_feature_prompts_manage_address">Merañ ar chomlec’hioù</string>
diff --git a/mobile/android/android-components/components/feature/prompts/src/main/res/values-kab/strings.xml b/mobile/android/android-components/components/feature/prompts/src/main/res/values-kab/strings.xml
index dc9067b13a..595f0075a4 100644
--- a/mobile/android/android-components/components/feature/prompts/src/main/res/values-kab/strings.xml
+++ b/mobile/android/android-components/components/feature/prompts/src/main/res/values-kab/strings.xml
@@ -103,6 +103,8 @@
<string name="mozac_feature_prompts_expand_logins_content_description" moz:removedIn="125" tools:ignore="UnusedResources">Sken-d inekcam isumar</string>
<!-- Content description for collapsing the saved logins options in the select login prompt -->
<string name="mozac_feature_prompts_collapse_logins_content_description" moz:removedIn="125" tools:ignore="UnusedResources">Ffer inekcam isumar</string>
+ <!-- Content description for collapsing the saved passwords options in the select password prompt -->
+ <string name="mozac_feature_prompts_collapse_logins_content_description_2">Fneḍ awalen n uεeddi i yettwaskelsen</string>
<!-- Header for the select login prompt to allow users to fill a form with a saved login -->
<string name="mozac_feature_prompts_saved_logins" moz:removedIn="125" tools:ignore="UnusedResources">Inekcam yettwasumren</string>
diff --git a/mobile/android/android-components/components/feature/prompts/src/main/res/values-nn-rNO/strings.xml b/mobile/android/android-components/components/feature/prompts/src/main/res/values-nn-rNO/strings.xml
index 6266243205..15d975b4eb 100644
--- a/mobile/android/android-components/components/feature/prompts/src/main/res/values-nn-rNO/strings.xml
+++ b/mobile/android/android-components/components/feature/prompts/src/main/res/values-nn-rNO/strings.xml
@@ -38,6 +38,8 @@
<string name="mozac_feature_prompt_error_empty_password_2">Skriv inn passord</string>
<!-- Error text displayed underneath the login field when it is in an error case -->
<string name="mozac_feature_prompt_error_unknown_cause" moz:removedIn="125" tools:ignore="UnusedResources">Klarte ikkje å lagre innlogginga</string>
+ <!-- Error text displayed underneath the password field when it is in an error case -->
+ <string name="mozac_feature_prompt_error_unknown_cause_2">Kan ikkje lagre passordet</string>
<!-- Prompt message displayed when app detects a user has entered a new username and password and user decides if app should save the new login. -->
<string name="mozac_feature_prompt_login_save_headline" moz:removedIn="125" tools:ignore="UnusedResources">Lagre denne innlogginga?</string>
<!-- Prompt message displayed when app detects a user has entered a new username and password and user decides if app should save the new password. -->
@@ -103,6 +105,8 @@
<string name="mozac_feature_prompts_expand_logins_content_description_2">Utvid lagra passord</string>
<!-- Content description for collapsing the saved logins options in the select login prompt -->
<string name="mozac_feature_prompts_collapse_logins_content_description" moz:removedIn="125" tools:ignore="UnusedResources">Slå saman føreslåtte innloggingar</string>
+ <!-- Content description for collapsing the saved passwords options in the select password prompt -->
+ <string name="mozac_feature_prompts_collapse_logins_content_description_2">Skjul lagra passord</string>
<!-- Header for the select login prompt to allow users to fill a form with a saved login -->
<string name="mozac_feature_prompts_saved_logins" moz:removedIn="125" tools:ignore="UnusedResources">Føreslåtte innloggingar</string>
@@ -131,8 +135,12 @@
<string name="mozac_feature_prompts_select_credit_card_2">Bruk lagra kort</string>
<!-- Content description for expanding the select credit card options in the select credit card prompt. -->
<string name="mozac_feature_prompts_expand_credit_cards_content_description" moz:removedIn="125" tools:ignore="UnusedResources">Utvid føreslått betalingskort</string>
+ <!-- Content description for expanding the saved card options in the select card prompt. -->
+ <string name="mozac_feature_prompts_expand_credit_cards_content_description_2">Utvid lagra passord</string>
<!-- Content description for collapsing the select credit card options in the select credit prompt. -->
<string name="mozac_feature_prompts_collapse_credit_cards_content_description" moz:removedIn="125" tools:ignore="UnusedResources">Minimer føreslått betalingskort</string>
+ <!-- Content description for collapsing the saved card options in the select prompt. -->
+ <string name="mozac_feature_prompts_collapse_credit_cards_content_description_2">Skjul lagra kort</string>
<!-- Option in the expanded select credit card prompt that links to credit cards settings. -->
<string name="mozac_feature_prompts_manage_credit_cards" moz:removedIn="125" tools:ignore="UnusedResources">Handsam betalingskort</string>
<!-- Option in the expanded select card prompt that links to cards settings. -->
@@ -144,6 +152,9 @@
<!-- Subtitle text displayed under the title of the save credit card dialog. -->
<string name="mozac_feature_prompts_save_credit_card_prompt_body" moz:removedIn="125" tools:ignore="UnusedResources">Kortnummeret vil bli kryptert. Tryggingskoden vert ikkje lagra.</string>
+ <!-- Subtitle text displayed under the title of the saved card dialog. Parameter will be replaced by app name-->
+ <string name="mozac_feature_prompts_save_credit_card_prompt_body_2">%s krypterer kortnummeret ditt. Sikkerheitskoden din vert ikkje lagra.</string>
+
<!-- Address Autofill -->
<!-- Header for the select address prompt to allow users to fill a form with a saved address. -->
<string name="mozac_feature_prompts_select_address_2">Vel adresse</string>
@@ -153,6 +164,8 @@
<string name="mozac_feature_prompts_expand_address_content_description_2">Utvid lagra adresser</string>
<!-- Content description for collapsing the select address options in the select address prompt. -->
<string name="mozac_feature_prompts_collapse_address_content_description" moz:removedIn="125" tools:ignore="UnusedResources">Slå saman føreslåtte adresser</string>
+ <!-- Content description for collapsing the saved address options in the select address prompt. -->
+ <string name="mozac_feature_prompts_collapse_address_content_description_2">Skjul lagra adresser</string>
<!-- Text for the manage addresses button. -->
<string name="mozac_feature_prompts_manage_address">Handsam adresser</string>
diff --git a/mobile/android/android-components/components/feature/prompts/src/main/res/values-sc/strings.xml b/mobile/android/android-components/components/feature/prompts/src/main/res/values-sc/strings.xml
index e4dd91d8c6..74d17b4a10 100644
--- a/mobile/android/android-components/components/feature/prompts/src/main/res/values-sc/strings.xml
+++ b/mobile/android/android-components/components/feature/prompts/src/main/res/values-sc/strings.xml
@@ -17,9 +17,9 @@
<!-- Text for password field in an authentication dialog. -->
<string name="mozac_feature_prompt_password_hint">Crae</string>
<!-- Negative confirmation that we should not save the new or updated login -->
- <string name="mozac_feature_prompt_dont_save">Non sarves</string>
+ <string name="mozac_feature_prompt_dont_save" moz:removedIn="125" tools:ignore="UnusedResources">Non sarves</string>
<!-- Negative confirmation that we should not save the new or updated login -->
- <string name="mozac_feature_prompt_dont_save_2" tools:ignore="UnusedResources">Immoe nono</string>
+ <string name="mozac_feature_prompt_dont_save_2">Immoe nono</string>
<!-- Negative confirmation that we should never save a login for this site -->
<string name="mozac_feature_prompt_never_save">Non sarves mai</string>
<!-- Negative confirmation that we should not save a credit card for this site -->
@@ -27,27 +27,27 @@
<!-- Positive confirmation that we should save the new or updated login -->
<string name="mozac_feature_prompt_save_confirmation">Sarva</string>
<!-- Negative confirmation that we should not save the updated login -->
- <string name="mozac_feature_prompt_dont_update">No atualizes</string>
+ <string name="mozac_feature_prompt_dont_update" moz:removedIn="125" tools:ignore="UnusedResources">No atualizes</string>
<!-- Negative confirmation that we should not save the updated login -->
- <string name="mozac_feature_prompt_dont_update_2" tools:ignore="UnusedResources">Immoe nono</string>
+ <string name="mozac_feature_prompt_dont_update_2">Immoe nono</string>
<!-- Positive confirmation that we should save the updated login -->
<string name="mozac_feature_prompt_update_confirmation">Atualiza</string>
<!-- Error text displayed underneath the password field when it is in an error case -->
- <string name="mozac_feature_prompt_error_empty_password">Sa crae non podet èssere bòida</string>
+ <string name="mozac_feature_prompt_error_empty_password" moz:removedIn="125" tools:ignore="UnusedResources">Sa crae non podet èssere bòida</string>
<!-- Error text displayed underneath the password field when it is in an error case -->
- <string name="mozac_feature_prompt_error_empty_password_2" tools:ignore="UnusedResources">Inserta una crae</string>
+ <string name="mozac_feature_prompt_error_empty_password_2">Inserta una crae</string>
<!-- Error text displayed underneath the login field when it is in an error case -->
- <string name="mozac_feature_prompt_error_unknown_cause">Impossìbile sarvare is credentziales</string>
+ <string name="mozac_feature_prompt_error_unknown_cause" moz:removedIn="125" tools:ignore="UnusedResources">Impossìbile sarvare is credentziales</string>
<!-- Error text displayed underneath the password field when it is in an error case -->
- <string name="mozac_feature_prompt_error_unknown_cause_2" tools:ignore="UnusedResources">Impossìbile sarvare sa crae</string>
+ <string name="mozac_feature_prompt_error_unknown_cause_2">Impossìbile sarvare sa crae</string>
<!-- Prompt message displayed when app detects a user has entered a new username and password and user decides if app should save the new login. -->
- <string name="mozac_feature_prompt_login_save_headline">Boles sarvare custa credentziale?</string>
+ <string name="mozac_feature_prompt_login_save_headline" moz:removedIn="125" tools:ignore="UnusedResources">Boles sarvare custa credentziale?</string>
<!-- Prompt message displayed when app detects a user has entered a new username and password and user decides if app should save the new password. -->
- <string name="mozac_feature_prompt_login_save_headline_2" tools:ignore="UnusedResources">Boles sarvare sa crae?</string>
+ <string name="mozac_feature_prompt_login_save_headline_2">Boles sarvare sa crae?</string>
<!-- Prompt message displayed when app detects a user has entered a new password for an existing login and user decides if app should update the login. -->
- <string name="mozac_feature_prompt_login_update_headline">Boles atualizare custa credentziale?</string>
+ <string name="mozac_feature_prompt_login_update_headline" moz:removedIn="125" tools:ignore="UnusedResources">Boles atualizare custa credentziale?</string>
<!-- Prompt message displayed when app detects a user has entered a new password for an existing login and user decides if app should update the password. -->
- <string name="mozac_feature_prompt_login_update_headline_2" tools:ignore="UnusedResources">Boles atualizare sa crae?</string>
+ <string name="mozac_feature_prompt_login_update_headline_2">Boles atualizare sa crae?</string>
<!-- Prompt message displayed when app detects a user has entered a username for an existing login without a username and user decides if app should update the login. -->
<string name="mozac_feature_prompt_login_add_username_headline">Boles agiùnghere su nòmine de utente a sa crae sarvada?</string>
<!-- Text for a label for the field when prompt requesting a text is shown. -->
@@ -97,18 +97,22 @@
<!-- Title of the time picker dialog. -->
<string name="mozac_feature_prompts_set_time">Cunfigura s’ora</string>
<!-- Option in expanded select login prompt that links to login settings -->
- <string name="mozac_feature_prompts_manage_logins">Gesti is credentziales</string>
+ <string name="mozac_feature_prompts_manage_logins" moz:removedIn="125" tools:ignore="UnusedResources">Gesti is credentziales</string>
<!-- Option in expanded select password prompt that links to password settings -->
- <string name="mozac_feature_prompts_manage_logins_2" tools:ignore="UnusedResources">Gesti is craes</string>
+ <string name="mozac_feature_prompts_manage_logins_2">Gesti is craes</string>
<!-- Content description for expanding the saved logins options in the select login prompt -->
- <string name="mozac_feature_prompts_expand_logins_content_description">Ismànnia is credentziales cussigiadas</string>
+ <string name="mozac_feature_prompts_expand_logins_content_description" moz:removedIn="125" tools:ignore="UnusedResources">Ismànnia is credentziales cussigiadas</string>
+ <!-- Content description for expanding the saved passwords options in the select password prompt -->
+ <string name="mozac_feature_prompts_expand_logins_content_description_2">Ismànnia is craes sarvadas</string>
<!-- Content description for collapsing the saved logins options in the select login prompt -->
- <string name="mozac_feature_prompts_collapse_logins_content_description">Mìnima is credentziales cussigiadas</string>
+ <string name="mozac_feature_prompts_collapse_logins_content_description" moz:removedIn="125" tools:ignore="UnusedResources">Mìnima is credentziales cussigiadas</string>
+ <!-- Content description for collapsing the saved passwords options in the select password prompt -->
+ <string name="mozac_feature_prompts_collapse_logins_content_description_2">Mìnima is craes sarvadas</string>
<!-- Header for the select login prompt to allow users to fill a form with a saved login -->
- <string name="mozac_feature_prompts_saved_logins">Credentziales cussigiadas</string>
+ <string name="mozac_feature_prompts_saved_logins" moz:removedIn="125" tools:ignore="UnusedResources">Credentziales cussigiadas</string>
<!-- Header for the select password prompt to allow users to fill a form with a saved password -->
- <string name="mozac_feature_prompts_saved_logins_2" tools:ignore="UnusedResources">Craes sarvadas</string>
+ <string name="mozac_feature_prompts_saved_logins_2">Craes sarvadas</string>
<!-- Content description for the suggest strong password prompt to allow users to fill a form with a suggested strong password -->
<string name="mozac_feature_prompts_suggest_strong_password_content_description">Cussìgia una crae segura</string>
@@ -126,35 +130,43 @@
<!-- Credit Card Autofill -->
<!-- Header for the select credit card prompt to allow users to fill a form with a saved credit card. -->
- <string name="mozac_feature_prompts_select_credit_card">Seletziona una carta de crèditu</string>
+ <string name="mozac_feature_prompts_select_credit_card" moz:removedIn="125" tools:ignore="UnusedResources">Seletziona una carta de crèditu</string>
<!-- Header for the select card prompt to allow users to fill a form with a saved card. -->
- <string name="mozac_feature_prompts_select_credit_card_2" tools:ignore="UnusedResources">Imprea una carta sarvada</string>
+ <string name="mozac_feature_prompts_select_credit_card_2">Imprea una carta sarvada</string>
<!-- Content description for expanding the select credit card options in the select credit card prompt. -->
- <string name="mozac_feature_prompts_expand_credit_cards_content_description">Ismànnia is cartas de crèditu cussigiadas</string>
+ <string name="mozac_feature_prompts_expand_credit_cards_content_description" moz:removedIn="125" tools:ignore="UnusedResources">Ismànnia is cartas de crèditu cussigiadas</string>
+ <!-- Content description for expanding the saved card options in the select card prompt. -->
+ <string name="mozac_feature_prompts_expand_credit_cards_content_description_2">Ismànnia is cartas sarvadas</string>
<!-- Content description for collapsing the select credit card options in the select credit prompt. -->
- <string name="mozac_feature_prompts_collapse_credit_cards_content_description">Mìnima is cartas de crèditu cussigiadas</string>
+ <string name="mozac_feature_prompts_collapse_credit_cards_content_description" moz:removedIn="125" tools:ignore="UnusedResources">Mìnima is cartas de crèditu cussigiadas</string>
+ <!-- Content description for collapsing the saved card options in the select prompt. -->
+ <string name="mozac_feature_prompts_collapse_credit_cards_content_description_2">Mìnima is cartas sarvadas</string>
<!-- Option in the expanded select credit card prompt that links to credit cards settings. -->
- <string name="mozac_feature_prompts_manage_credit_cards">Gesti is cartas de crèditu</string>
+ <string name="mozac_feature_prompts_manage_credit_cards" moz:removedIn="125" tools:ignore="UnusedResources">Gesti is cartas de crèditu</string>
<!-- Option in the expanded select card prompt that links to cards settings. -->
- <string name="mozac_feature_prompts_manage_credit_cards_2" tools:ignore="UnusedResources">Gesti is cartas</string>
+ <string name="mozac_feature_prompts_manage_credit_cards_2">Gesti is cartas</string>
<!-- Text for the title of a save credit card dialog. -->
<string name="mozac_feature_prompts_save_credit_card_prompt_title">Boles sarvare custa carta cun seguresa?</string>
<!-- Text for the title of an update credit card dialog. -->
<string name="mozac_feature_prompts_update_credit_card_prompt_title">Boles atualizare sa data de iscadèntzia de sa carta?</string>
<!-- Subtitle text displayed under the title of the save credit card dialog. -->
- <string name="mozac_feature_prompts_save_credit_card_prompt_body">Su nùmeru de carta at a èssere tzifradu. Su còdighe de seguresa no at a èssere sarvadu.</string>
+ <string name="mozac_feature_prompts_save_credit_card_prompt_body" moz:removedIn="125" tools:ignore="UnusedResources">Su nùmeru de carta at a èssere tzifradu. Su còdighe de seguresa no at a èssere sarvadu.</string>
<!-- Subtitle text displayed under the title of the saved card dialog. Parameter will be replaced by app name-->
- <string name="mozac_feature_prompts_save_credit_card_prompt_body_2" tools:ignore="UnusedResources">%s tzifrat su nùmeru de sa carta tua. Su còdighe de seguresa no at a èssere sarvadu.</string>
+ <string name="mozac_feature_prompts_save_credit_card_prompt_body_2">%s tzifrat su nùmeru de sa carta tua. Su còdighe de seguresa no at a èssere sarvadu.</string>
<!-- Address Autofill -->
<!-- Header for the select address prompt to allow users to fill a form with a saved address. -->
<string name="mozac_feature_prompts_select_address_2">Seletziona un’indiritzu</string>
<!-- Content description for expanding the select addresses options in the select address prompt. -->
- <string name="mozac_feature_prompts_expand_address_content_description">Ismànnia is indiritzos cussigiados</string>
+ <string name="mozac_feature_prompts_expand_address_content_description" moz:removedIn="125" tools:ignore="UnusedResources">Ismànnia is indiritzos cussigiados</string>
+ <!-- Content description for expanding the saved addresses options in the select address prompt. -->
+ <string name="mozac_feature_prompts_expand_address_content_description_2">Ismànnia is indiritzos sarvados</string>
<!-- Content description for collapsing the select address options in the select address prompt. -->
- <string name="mozac_feature_prompts_collapse_address_content_description">Mìnima is indiritzos cussigiados</string>
+ <string name="mozac_feature_prompts_collapse_address_content_description" moz:removedIn="125" tools:ignore="UnusedResources">Mìnima is indiritzos cussigiados</string>
+ <!-- Content description for collapsing the saved address options in the select address prompt. -->
+ <string name="mozac_feature_prompts_collapse_address_content_description_2">Mìnima is indiritzos sarvados</string>
<!-- Text for the manage addresses button. -->
<string name="mozac_feature_prompts_manage_address">Gesti is indiritzos</string>
diff --git a/mobile/android/android-components/components/feature/prompts/src/main/res/values-sl/strings.xml b/mobile/android/android-components/components/feature/prompts/src/main/res/values-sl/strings.xml
index dec932c1c5..afe0f515ca 100644
--- a/mobile/android/android-components/components/feature/prompts/src/main/res/values-sl/strings.xml
+++ b/mobile/android/android-components/components/feature/prompts/src/main/res/values-sl/strings.xml
@@ -17,9 +17,9 @@
<!-- Text for password field in an authentication dialog. -->
<string name="mozac_feature_prompt_password_hint">Geslo</string>
<!-- Negative confirmation that we should not save the new or updated login -->
- <string name="mozac_feature_prompt_dont_save">Ne shrani</string>
+ <string name="mozac_feature_prompt_dont_save" moz:removedIn="125" tools:ignore="UnusedResources">Ne shrani</string>
<!-- Negative confirmation that we should not save the new or updated login -->
- <string name="mozac_feature_prompt_dont_save_2" tools:ignore="UnusedResources">Ne zdaj</string>
+ <string name="mozac_feature_prompt_dont_save_2">Ne zdaj</string>
<!-- Negative confirmation that we should never save a login for this site -->
<string name="mozac_feature_prompt_never_save">Nikoli ne shranjuj</string>
<!-- Negative confirmation that we should not save a credit card for this site -->
@@ -27,23 +27,27 @@
<!-- Positive confirmation that we should save the new or updated login -->
<string name="mozac_feature_prompt_save_confirmation">Shrani</string>
<!-- Negative confirmation that we should not save the updated login -->
- <string name="mozac_feature_prompt_dont_update">Ne posodobi</string>
+ <string name="mozac_feature_prompt_dont_update" moz:removedIn="125" tools:ignore="UnusedResources">Ne posodobi</string>
<!-- Negative confirmation that we should not save the updated login -->
- <string name="mozac_feature_prompt_dont_update_2" tools:ignore="UnusedResources">Ne zdaj</string>
+ <string name="mozac_feature_prompt_dont_update_2">Ne zdaj</string>
<!-- Positive confirmation that we should save the updated login -->
<string name="mozac_feature_prompt_update_confirmation">Posodobi</string>
<!-- Error text displayed underneath the password field when it is in an error case -->
- <string name="mozac_feature_prompt_error_empty_password">Polje za geslo ne sme biti prazno</string>
+ <string name="mozac_feature_prompt_error_empty_password" moz:removedIn="125" tools:ignore="UnusedResources">Polje za geslo ne sme biti prazno</string>
<!-- Error text displayed underneath the password field when it is in an error case -->
- <string name="mozac_feature_prompt_error_empty_password_2" tools:ignore="UnusedResources">Vnesite geslo</string>
+ <string name="mozac_feature_prompt_error_empty_password_2">Vnesite geslo</string>
<!-- Error text displayed underneath the login field when it is in an error case -->
- <string name="mozac_feature_prompt_error_unknown_cause">Ni mogoče shraniti povezave</string>
+ <string name="mozac_feature_prompt_error_unknown_cause" moz:removedIn="125" tools:ignore="UnusedResources">Ni mogoče shraniti povezave</string>
<!-- Error text displayed underneath the password field when it is in an error case -->
- <string name="mozac_feature_prompt_error_unknown_cause_2" tools:ignore="UnusedResources">Gesla ni mogoče shraniti</string>
+ <string name="mozac_feature_prompt_error_unknown_cause_2">Gesla ni mogoče shraniti</string>
<!-- Prompt message displayed when app detects a user has entered a new username and password and user decides if app should save the new login. -->
- <string name="mozac_feature_prompt_login_save_headline">Shranim to prijavo?</string>
+ <string name="mozac_feature_prompt_login_save_headline" moz:removedIn="125" tools:ignore="UnusedResources">Shranim to prijavo?</string>
+ <!-- Prompt message displayed when app detects a user has entered a new username and password and user decides if app should save the new password. -->
+ <string name="mozac_feature_prompt_login_save_headline_2">Shranim geslo?</string>
<!-- Prompt message displayed when app detects a user has entered a new password for an existing login and user decides if app should update the login. -->
- <string name="mozac_feature_prompt_login_update_headline">Posodobim to prijavo?</string>
+ <string name="mozac_feature_prompt_login_update_headline" moz:removedIn="125" tools:ignore="UnusedResources">Posodobim to prijavo?</string>
+ <!-- Prompt message displayed when app detects a user has entered a new password for an existing login and user decides if app should update the password. -->
+ <string name="mozac_feature_prompt_login_update_headline_2">Posodobim geslo?</string>
<!-- Prompt message displayed when app detects a user has entered a username for an existing login without a username and user decides if app should update the login. -->
<string name="mozac_feature_prompt_login_add_username_headline">Dodaj shranjenemu geslu uporabniško ime?</string>
<!-- Text for a label for the field when prompt requesting a text is shown. -->
@@ -92,22 +96,22 @@
<!-- Title of the time picker dialog. -->
<string name="mozac_feature_prompts_set_time">Nastavi čas</string>
<!-- Option in expanded select login prompt that links to login settings -->
- <string name="mozac_feature_prompts_manage_logins">Upravljanje prijav</string>
+ <string name="mozac_feature_prompts_manage_logins" moz:removedIn="125" tools:ignore="UnusedResources">Upravljanje prijav</string>
<!-- Option in expanded select password prompt that links to password settings -->
- <string name="mozac_feature_prompts_manage_logins_2" tools:ignore="UnusedResources">Upravljanje gesel</string>
+ <string name="mozac_feature_prompts_manage_logins_2">Upravljanje gesel</string>
<!-- Content description for expanding the saved logins options in the select login prompt -->
- <string name="mozac_feature_prompts_expand_logins_content_description">Razširi predlagane prijave</string>
+ <string name="mozac_feature_prompts_expand_logins_content_description" moz:removedIn="125" tools:ignore="UnusedResources">Razširi predlagane prijave</string>
<!-- Content description for expanding the saved passwords options in the select password prompt -->
- <string name="mozac_feature_prompts_expand_logins_content_description_2" tools:ignore="UnusedResources">Prikaži shranjena gesla</string>
+ <string name="mozac_feature_prompts_expand_logins_content_description_2">Prikaži shranjena gesla</string>
<!-- Content description for collapsing the saved logins options in the select login prompt -->
- <string name="mozac_feature_prompts_collapse_logins_content_description">Strni predlagane prijave</string>
+ <string name="mozac_feature_prompts_collapse_logins_content_description" moz:removedIn="125" tools:ignore="UnusedResources">Strni predlagane prijave</string>
<!-- Content description for collapsing the saved passwords options in the select password prompt -->
- <string name="mozac_feature_prompts_collapse_logins_content_description_2" tools:ignore="UnusedResources">Skrij shranjena gesla</string>
+ <string name="mozac_feature_prompts_collapse_logins_content_description_2">Skrij shranjena gesla</string>
<!-- Header for the select login prompt to allow users to fill a form with a saved login -->
- <string name="mozac_feature_prompts_saved_logins">Predlagane prijave</string>
+ <string name="mozac_feature_prompts_saved_logins" moz:removedIn="125" tools:ignore="UnusedResources">Predlagane prijave</string>
<!-- Header for the select password prompt to allow users to fill a form with a saved password -->
- <string name="mozac_feature_prompts_saved_logins_2" tools:ignore="UnusedResources">Shranjena gesla</string>
+ <string name="mozac_feature_prompts_saved_logins_2">Shranjena gesla</string>
<!-- Content description for the suggest strong password prompt to allow users to fill a form with a suggested strong password -->
<string name="mozac_feature_prompts_suggest_strong_password_content_description">Predlagaj močno geslo</string>
@@ -126,42 +130,42 @@
<!-- Credit Card Autofill -->
<!-- Header for the select credit card prompt to allow users to fill a form with a saved credit card. -->
- <string name="mozac_feature_prompts_select_credit_card">Izberite kreditno kartico</string>
+ <string name="mozac_feature_prompts_select_credit_card" moz:removedIn="125" tools:ignore="UnusedResources">Izberite kreditno kartico</string>
<!-- Header for the select card prompt to allow users to fill a form with a saved card. -->
- <string name="mozac_feature_prompts_select_credit_card_2" tools:ignore="UnusedResources">Uporabi shranjeno kartico</string>
+ <string name="mozac_feature_prompts_select_credit_card_2">Uporabi shranjeno kartico</string>
<!-- Content description for expanding the select credit card options in the select credit card prompt. -->
- <string name="mozac_feature_prompts_expand_credit_cards_content_description">Razširi predlagane kreditne kartice</string>
+ <string name="mozac_feature_prompts_expand_credit_cards_content_description" moz:removedIn="125" tools:ignore="UnusedResources">Razširi predlagane kreditne kartice</string>
<!-- Content description for expanding the saved card options in the select card prompt. -->
- <string name="mozac_feature_prompts_expand_credit_cards_content_description_2" tools:ignore="UnusedResources">Prikaži shranjene kartice</string>
+ <string name="mozac_feature_prompts_expand_credit_cards_content_description_2">Prikaži shranjene kartice</string>
<!-- Content description for collapsing the select credit card options in the select credit prompt. -->
- <string name="mozac_feature_prompts_collapse_credit_cards_content_description">Strni predlagane kreditne kartice</string>
+ <string name="mozac_feature_prompts_collapse_credit_cards_content_description" moz:removedIn="125" tools:ignore="UnusedResources">Strni predlagane kreditne kartice</string>
<!-- Content description for collapsing the saved card options in the select prompt. -->
- <string name="mozac_feature_prompts_collapse_credit_cards_content_description_2" tools:ignore="UnusedResources">Skrij shranjene kartice</string>
+ <string name="mozac_feature_prompts_collapse_credit_cards_content_description_2">Skrij shranjene kartice</string>
<!-- Option in the expanded select credit card prompt that links to credit cards settings. -->
- <string name="mozac_feature_prompts_manage_credit_cards">Upravljanje kreditnih kartic</string>
+ <string name="mozac_feature_prompts_manage_credit_cards" moz:removedIn="125" tools:ignore="UnusedResources">Upravljanje kreditnih kartic</string>
<!-- Option in the expanded select card prompt that links to cards settings. -->
- <string name="mozac_feature_prompts_manage_credit_cards_2" tools:ignore="UnusedResources">Upravljanje kartic</string>
+ <string name="mozac_feature_prompts_manage_credit_cards_2">Upravljanje kartic</string>
<!-- Text for the title of a save credit card dialog. -->
<string name="mozac_feature_prompts_save_credit_card_prompt_title">Želite varno shraniti to kartico?</string>
<!-- Text for the title of an update credit card dialog. -->
<string name="mozac_feature_prompts_update_credit_card_prompt_title">Posodobi datum poteka veljavnosti kartice?</string>
<!-- Subtitle text displayed under the title of the save credit card dialog. -->
- <string name="mozac_feature_prompts_save_credit_card_prompt_body">Številka kartice bo šifrirana. Varnostna koda ne bo shranjena.</string>
+ <string name="mozac_feature_prompts_save_credit_card_prompt_body" moz:removedIn="125" tools:ignore="UnusedResources">Številka kartice bo šifrirana. Varnostna koda ne bo shranjena.</string>
<!-- Subtitle text displayed under the title of the saved card dialog. Parameter will be replaced by app name-->
- <string name="mozac_feature_prompts_save_credit_card_prompt_body_2" tools:ignore="UnusedResources">%s šifrira številko vaše kartice. Varnostna koda se ne bo shranila.</string>
+ <string name="mozac_feature_prompts_save_credit_card_prompt_body_2">%s šifrira številko vaše kartice. Varnostna koda se ne bo shranila.</string>
<!-- Address Autofill -->
<!-- Header for the select address prompt to allow users to fill a form with a saved address. -->
<string name="mozac_feature_prompts_select_address_2">Izbira naslova</string>
<!-- Content description for expanding the select addresses options in the select address prompt. -->
- <string name="mozac_feature_prompts_expand_address_content_description">Razširi predlagane naslove</string>
+ <string name="mozac_feature_prompts_expand_address_content_description" moz:removedIn="125" tools:ignore="UnusedResources">Razširi predlagane naslove</string>
<!-- Content description for expanding the saved addresses options in the select address prompt. -->
- <string name="mozac_feature_prompts_expand_address_content_description_2" tools:ignore="UnusedResources">Prikaži shranjene naslove</string>
+ <string name="mozac_feature_prompts_expand_address_content_description_2">Prikaži shranjene naslove</string>
<!-- Content description for collapsing the select address options in the select address prompt. -->
- <string name="mozac_feature_prompts_collapse_address_content_description">Strni predlagane naslove</string>
+ <string name="mozac_feature_prompts_collapse_address_content_description" moz:removedIn="125" tools:ignore="UnusedResources">Strni predlagane naslove</string>
<!-- Content description for collapsing the saved address options in the select address prompt. -->
- <string name="mozac_feature_prompts_collapse_address_content_description_2" tools:ignore="UnusedResources">Skrij shranjene naslove</string>
+ <string name="mozac_feature_prompts_collapse_address_content_description_2">Skrij shranjene naslove</string>
<!-- Text for the manage addresses button. -->
<string name="mozac_feature_prompts_manage_address">Upravljanje naslovov</string>
diff --git a/mobile/android/android-components/components/feature/prompts/src/main/res/values-su/strings.xml b/mobile/android/android-components/components/feature/prompts/src/main/res/values-su/strings.xml
index 8069cf1b66..d0bf44fd5e 100644
--- a/mobile/android/android-components/components/feature/prompts/src/main/res/values-su/strings.xml
+++ b/mobile/android/android-components/components/feature/prompts/src/main/res/values-su/strings.xml
@@ -17,7 +17,9 @@
<!-- Text for password field in an authentication dialog. -->
<string name="mozac_feature_prompt_password_hint">Kecap sandi</string>
<!-- Negative confirmation that we should not save the new or updated login -->
- <string name="mozac_feature_prompt_dont_save">Ulah diteundeun</string>
+ <string name="mozac_feature_prompt_dont_save" moz:removedIn="125" tools:ignore="UnusedResources">Ulah diteundeun</string>
+ <!-- Negative confirmation that we should not save the new or updated login -->
+ <string name="mozac_feature_prompt_dont_save_2">Moal waka</string>
<!-- Negative confirmation that we should never save a login for this site -->
<string name="mozac_feature_prompt_never_save">Ulah diteundeun</string>
<!-- Negative confirmation that we should not save a credit card for this site -->
@@ -25,17 +27,27 @@
<!-- Positive confirmation that we should save the new or updated login -->
<string name="mozac_feature_prompt_save_confirmation">Teundeun</string>
<!-- Negative confirmation that we should not save the updated login -->
- <string name="mozac_feature_prompt_dont_update">Ulah ngapdét</string>
+ <string name="mozac_feature_prompt_dont_update" moz:removedIn="125" tools:ignore="UnusedResources">Ulah ngapdét</string>
+ <!-- Negative confirmation that we should not save the updated login -->
+ <string name="mozac_feature_prompt_dont_update_2">Moal waka</string>
<!-- Positive confirmation that we should save the updated login -->
<string name="mozac_feature_prompt_update_confirmation">Apdét</string>
<!-- Error text displayed underneath the password field when it is in an error case -->
- <string name="mozac_feature_prompt_error_empty_password">Widang kecap sandi henteu kaci kosong</string>
+ <string name="mozac_feature_prompt_error_empty_password" moz:removedIn="125" tools:ignore="UnusedResources">Widang kecap sandi henteu kaci kosong</string>
+ <!-- Error text displayed underneath the password field when it is in an error case -->
+ <string name="mozac_feature_prompt_error_empty_password_2">Asupkeun sandi</string>
+ <!-- Error text displayed underneath the login field when it is in an error case -->
+ <string name="mozac_feature_prompt_error_unknown_cause" moz:removedIn="125" tools:ignore="UnusedResources">Teu bisa neundeun login</string>
<!-- Error text displayed underneath the password field when it is in an error case -->
- <string name="mozac_feature_prompt_error_unknown_cause">Teu bisa neundeun login</string>
+ <string name="mozac_feature_prompt_error_unknown_cause_2">Teu bisa nyimpen santi</string>
<!-- Prompt message displayed when app detects a user has entered a new username and password and user decides if app should save the new login. -->
- <string name="mozac_feature_prompt_login_save_headline">Teundeun ieu login?</string>
+ <string name="mozac_feature_prompt_login_save_headline" moz:removedIn="125" tools:ignore="UnusedResources">Teundeun ieu login?</string>
+ <!-- Prompt message displayed when app detects a user has entered a new username and password and user decides if app should save the new password. -->
+ <string name="mozac_feature_prompt_login_save_headline_2">Simpen sandi?</string>
<!-- Prompt message displayed when app detects a user has entered a new password for an existing login and user decides if app should update the login. -->
- <string name="mozac_feature_prompt_login_update_headline">Apdét ieu login?</string>
+ <string name="mozac_feature_prompt_login_update_headline" moz:removedIn="125" tools:ignore="UnusedResources">Apdét ieu login?</string>
+ <!-- Prompt message displayed when app detects a user has entered a new password for an existing login and user decides if app should update the password. -->
+ <string name="mozac_feature_prompt_login_update_headline_2">Anyarkeun sandi?</string>
<!-- Prompt message displayed when app detects a user has entered a username for an existing login without a username and user decides if app should update the login. -->
<string name="mozac_feature_prompt_login_add_username_headline">Tambahkeun sandiasma kana kecap sandi anu diteundeun?</string>
<!-- Text for a label for the field when prompt requesting a text is shown. -->
@@ -84,13 +96,22 @@
<!-- Title of the time picker dialog. -->
<string name="mozac_feature_prompts_set_time">Setél wanci</string>
<!-- Option in expanded select login prompt that links to login settings -->
- <string name="mozac_feature_prompts_manage_logins">Kokolakeun login</string>
+ <string name="mozac_feature_prompts_manage_logins" moz:removedIn="125" tools:ignore="UnusedResources">Kokolakeun login</string>
+ <!-- Option in expanded select password prompt that links to password settings -->
+ <string name="mozac_feature_prompts_manage_logins_2">Atur sandi</string>
<!-- Content description for expanding the saved logins options in the select login prompt -->
- <string name="mozac_feature_prompts_expand_logins_content_description">Legaan saran login</string>
+ <string name="mozac_feature_prompts_expand_logins_content_description" moz:removedIn="125" tools:ignore="UnusedResources">Legaan saran login</string>
+ <!-- Content description for expanding the saved passwords options in the select password prompt -->
+ <string name="mozac_feature_prompts_expand_logins_content_description_2">Legaan sandi anu disimpen</string>
<!-- Content description for collapsing the saved logins options in the select login prompt -->
- <string name="mozac_feature_prompts_collapse_logins_content_description">Leutikan saran login</string>
+ <string name="mozac_feature_prompts_collapse_logins_content_description" moz:removedIn="125" tools:ignore="UnusedResources">Leutikan saran login</string>
+ <!-- Content description for collapsing the saved passwords options in the select password prompt -->
+ <string name="mozac_feature_prompts_collapse_logins_content_description_2">Heureutan sandi nu disimpen</string>
<!-- Header for the select login prompt to allow users to fill a form with a saved login -->
- <string name="mozac_feature_prompts_saved_logins">Saran login</string>
+ <string name="mozac_feature_prompts_saved_logins" moz:removedIn="125" tools:ignore="UnusedResources">Saran login</string>
+
+ <!-- Header for the select password prompt to allow users to fill a form with a saved password -->
+ <string name="mozac_feature_prompts_saved_logins_2">Sandi nu disimpen</string>
<!-- Content description for the suggest strong password prompt to allow users to fill a form with a suggested strong password -->
<string name="mozac_feature_prompts_suggest_strong_password_content_description">Usulkeun kecap sandi anu wedel</string>
@@ -109,27 +130,42 @@
<!-- Credit Card Autofill -->
<!-- Header for the select credit card prompt to allow users to fill a form with a saved credit card. -->
- <string name="mozac_feature_prompts_select_credit_card">Pilih kartu kiridit</string>
+ <string name="mozac_feature_prompts_select_credit_card" moz:removedIn="125" tools:ignore="UnusedResources">Pilih kartu kiridit</string>
+ <!-- Header for the select card prompt to allow users to fill a form with a saved card. -->
+ <string name="mozac_feature_prompts_select_credit_card_2">Paké kartu nu disimpen</string>
<!-- Content description for expanding the select credit card options in the select credit card prompt. -->
- <string name="mozac_feature_prompts_expand_credit_cards_content_description">Legaan kartu kiridit anu disarankeun</string>
+ <string name="mozac_feature_prompts_expand_credit_cards_content_description" moz:removedIn="125" tools:ignore="UnusedResources">Legaan kartu kiridit anu disarankeun</string>
+ <!-- Content description for expanding the saved card options in the select card prompt. -->
+ <string name="mozac_feature_prompts_expand_credit_cards_content_description_2">Legaan kartu nu disimpen</string>
<!-- Content description for collapsing the select credit card options in the select credit prompt. -->
- <string name="mozac_feature_prompts_collapse_credit_cards_content_description">Tilep saran kartu kiridit</string>
+ <string name="mozac_feature_prompts_collapse_credit_cards_content_description" moz:removedIn="125" tools:ignore="UnusedResources">Tilep saran kartu kiridit</string>
+ <!-- Content description for collapsing the saved card options in the select prompt. -->
+ <string name="mozac_feature_prompts_collapse_credit_cards_content_description_2">Heureutan kartu nu disimpen</string>
<!-- Option in the expanded select credit card prompt that links to credit cards settings. -->
- <string name="mozac_feature_prompts_manage_credit_cards">Kokolakeun kartu kiridit</string>
+ <string name="mozac_feature_prompts_manage_credit_cards" moz:removedIn="125" tools:ignore="UnusedResources">Kokolakeun kartu kiridit</string>
+ <!-- Option in the expanded select card prompt that links to cards settings. -->
+ <string name="mozac_feature_prompts_manage_credit_cards_2">Atur kartu</string>
<!-- Text for the title of a save credit card dialog. -->
<string name="mozac_feature_prompts_save_credit_card_prompt_title">Teundeun ieu kartu sacara aman?</string>
<!-- Text for the title of an update credit card dialog. -->
<string name="mozac_feature_prompts_update_credit_card_prompt_title">Mutahirkeun titimangsa kadaluwarsa kartu?</string>
<!-- Subtitle text displayed under the title of the save credit card dialog. -->
- <string name="mozac_feature_prompts_save_credit_card_prompt_body">Nomer kartu bakal diénkrip. Kode kaamanan moal diteundeun.</string>
+ <string name="mozac_feature_prompts_save_credit_card_prompt_body" moz:removedIn="125" tools:ignore="UnusedResources">Nomer kartu bakal diénkrip. Kode kaamanan moal diteundeun.</string>
+
+ <!-- Subtitle text displayed under the title of the saved card dialog. Parameter will be replaced by app name-->
+ <string name="mozac_feature_prompts_save_credit_card_prompt_body_2">%s énkripsi nomer kartu anjeun. Kode kaamanan anjeun moal disimpen.</string>
<!-- Address Autofill -->
<!-- Header for the select address prompt to allow users to fill a form with a saved address. -->
<string name="mozac_feature_prompts_select_address_2">Pilih alamat</string>
<!-- Content description for expanding the select addresses options in the select address prompt. -->
- <string name="mozac_feature_prompts_expand_address_content_description">Legaan saran alamat</string>
+ <string name="mozac_feature_prompts_expand_address_content_description" moz:removedIn="125" tools:ignore="UnusedResources">Legaan saran alamat</string>
+ <!-- Content description for expanding the saved addresses options in the select address prompt. -->
+ <string name="mozac_feature_prompts_expand_address_content_description_2">Legaan alamat nu disimpen</string>
<!-- Content description for collapsing the select address options in the select address prompt. -->
- <string name="mozac_feature_prompts_collapse_address_content_description">Leutikan saran alamat</string>
+ <string name="mozac_feature_prompts_collapse_address_content_description" moz:removedIn="125" tools:ignore="UnusedResources">Leutikan saran alamat</string>
+ <!-- Content description for collapsing the saved address options in the select address prompt. -->
+ <string name="mozac_feature_prompts_collapse_address_content_description_2">Heureutan alamat nu disimpen</string>
<!-- Text for the manage addresses button. -->
<string name="mozac_feature_prompts_manage_address">Kokolakeun alamat</string>
diff --git a/mobile/android/android-components/components/feature/prompts/src/main/res/values/quarantined_strings.xml b/mobile/android/android-components/components/feature/prompts/src/main/res/values/quarantined_strings.xml
index 5943e14165..1564be16e2 100644
--- a/mobile/android/android-components/components/feature/prompts/src/main/res/values/quarantined_strings.xml
+++ b/mobile/android/android-components/components/feature/prompts/src/main/res/values/quarantined_strings.xml
@@ -5,5 +5,5 @@
<!-- Strings in this file are not yet ready for localization. -->
<resources>
<!-- Text of the title of a dialog when a page is requesting to open a new window. -->
- <string name="mozac_feature_prompts_popup_dialog_title">Prevent this site from opening a pop-up window?</string>
+ <string name="mozac_feature_prompts_popup_dialog_title">Allow this site to open?</string>
</resources>
diff --git a/mobile/android/android-components/components/feature/prompts/src/test/java/mozilla/components/feature/prompts/PromptFeatureTest.kt b/mobile/android/android-components/components/feature/prompts/src/test/java/mozilla/components/feature/prompts/PromptFeatureTest.kt
index 3c1cfba67c..7f8157bf0d 100644
--- a/mobile/android/android-components/components/feature/prompts/src/test/java/mozilla/components/feature/prompts/PromptFeatureTest.kt
+++ b/mobile/android/android-components/components/feature/prompts/src/test/java/mozilla/components/feature/prompts/PromptFeatureTest.kt
@@ -1805,6 +1805,74 @@ class PromptFeatureTest {
}
@Test
+ fun `WHEN login autofill is enabled THEN the select login prompt is shown`() {
+ val loginPickerView: SelectablePromptView<Login> = mock()
+
+ val login =
+ Login(guid = "A", origin = "origin", username = "user123", password = "password123")
+
+ val feature =
+ PromptFeature(
+ activity = mock<Activity>(),
+ store = store,
+ fileUploadsDirCleaner = mock(),
+ tabsUseCases = mock(),
+ fragmentManager = fragmentManager,
+ exitFullscreenUsecase = mock(),
+ loginDelegate = object : LoginDelegate {
+ override val loginPickerView = loginPickerView
+ override val onManageLogins = {}
+ },
+ isLoginAutofillEnabled = { true },
+ ) { }
+ feature.loginPicker = loginPicker
+ val onLoginDismiss: () -> Unit = {}
+ val onLoginConfirm: (Login) -> Unit = {}
+
+ val selectLoginRequest =
+ PromptRequest.SelectLoginPrompt(listOf(login), null, onLoginConfirm, onLoginDismiss)
+
+ feature.start()
+ store.dispatch(ContentAction.UpdatePromptRequestAction(tabId, selectLoginRequest))
+ .joinBlocking()
+
+ verify(loginPicker).handleSelectLoginRequest(selectLoginRequest)
+ }
+
+ @Test
+ fun `WHEN login autofill is disabled THEN the select login prompt is not shown`() {
+ val loginPickerView: SelectablePromptView<Login> = mock()
+
+ val login =
+ Login(guid = "A", origin = "origin", username = "user123", password = "password123")
+
+ val feature =
+ PromptFeature(
+ activity = mock<Activity>(),
+ store = store,
+ fileUploadsDirCleaner = mock(),
+ tabsUseCases = mock(),
+ fragmentManager = fragmentManager,
+ exitFullscreenUsecase = mock(),
+ loginDelegate = object : LoginDelegate {
+ override val loginPickerView = loginPickerView
+ override val onManageLogins = {}
+ },
+ ) { }
+ feature.loginPicker = loginPicker
+ val onLoginDismiss: () -> Unit = {}
+ val onLoginConfirm: (Login) -> Unit = {}
+
+ val selectLoginRequest =
+ PromptRequest.SelectLoginPrompt(listOf(login), null, onLoginConfirm, onLoginDismiss)
+
+ feature.start()
+ store.dispatch(ContentAction.UpdatePromptRequestAction(tabId, selectLoginRequest))
+ .joinBlocking()
+ verify(loginPicker, never()).handleSelectLoginRequest(selectLoginRequest)
+ }
+
+ @Test
fun `When page is refreshed login dialog is dismissed`() {
val loginPickerView: SelectablePromptView<Login> = mock()
val feature =
@@ -1819,6 +1887,7 @@ class PromptFeatureTest {
override val loginPickerView = loginPickerView
override val onManageLogins = {}
},
+ isLoginAutofillEnabled = { true },
) { }
feature.loginPicker = loginPicker
val onLoginDismiss: () -> Unit = {}
@@ -2348,6 +2417,70 @@ class PromptFeatureTest {
}
@Test
+ fun `GIVEN saveLoginDialog is visible WHEN host doesn't change THEN keep saveLoginDialog visible`() {
+ val newUrlSameDomain = "https://www.mozilla.org/en-GB/firefox/browsers/mobile/android/"
+ val promptRequest = PromptRequest.Share(
+ data = mock(),
+ onSuccess = {},
+ onFailure = {},
+ onDismiss = {},
+ )
+ val saveLoginPrompt: SaveLoginDialogFragment = mock()
+
+ val feature = spy(
+ PromptFeature(
+ mock<Activity>(),
+ store = store,
+ tabsUseCases = mock(),
+ fragmentManager = fragmentManager,
+ fileUploadsDirCleaner = mock(),
+ exitFullscreenUsecase = mock(),
+ isSaveLoginEnabled = { true },
+ loginValidationDelegate = mock(),
+ ) { },
+ )
+ feature.start()
+
+ store.dispatch(ContentAction.UpdatePromptRequestAction(tabId, promptRequest)).joinBlocking()
+ feature.activePrompt = WeakReference(saveLoginPrompt)
+
+ store.dispatch(ContentAction.UpdateUrlAction(tabId, newUrlSameDomain)).joinBlocking()
+ verify(saveLoginPrompt, never()).dismiss()
+ }
+
+ @Test
+ fun `GIVEN saveLoginDialog is visible WHEN host changes THEN dismiss saveLoginDialog`() {
+ val newUrlDifferentDomain = "https://www.android.com/new-features-on-android/"
+ val promptRequest = PromptRequest.Share(
+ data = mock(),
+ onSuccess = {},
+ onFailure = {},
+ onDismiss = {},
+ )
+ val saveLoginPrompt: SaveLoginDialogFragment = mock()
+
+ val feature = spy(
+ PromptFeature(
+ activity = mock(),
+ store = store,
+ tabsUseCases = mock(),
+ fragmentManager = fragmentManager,
+ fileUploadsDirCleaner = mock(),
+ exitFullscreenUsecase = mock(),
+ isSaveLoginEnabled = { true },
+ shareDelegate = mock(),
+ ) { },
+ )
+ feature.start()
+
+ store.dispatch(ContentAction.UpdatePromptRequestAction(tabId, promptRequest)).joinBlocking()
+ feature.activePrompt = WeakReference(saveLoginPrompt)
+
+ store.dispatch(ContentAction.UpdateUrlAction(tabId, newUrlDifferentDomain)).joinBlocking()
+ verify(saveLoginPrompt, times(1)).dismiss()
+ }
+
+ @Test
fun `prompt will always start the save login dialog with an icon`() {
val feature = PromptFeature(
activity = mock(),
diff --git a/mobile/android/android-components/components/feature/prompts/src/test/java/mozilla/components/feature/prompts/dialog/TextPromptDialogFragmentTest.kt b/mobile/android/android-components/components/feature/prompts/src/test/java/mozilla/components/feature/prompts/dialog/TextPromptDialogFragmentTest.kt
index b0fee5f9a1..df8aba7705 100644
--- a/mobile/android/android-components/components/feature/prompts/src/test/java/mozilla/components/feature/prompts/dialog/TextPromptDialogFragmentTest.kt
+++ b/mobile/android/android-components/components/feature/prompts/src/test/java/mozilla/components/feature/prompts/dialog/TextPromptDialogFragmentTest.kt
@@ -6,9 +6,11 @@ package mozilla.components.feature.prompts.dialog
import android.content.DialogInterface.BUTTON_POSITIVE
import android.os.Looper.getMainLooper
+import android.view.inputmethod.EditorInfo.IME_NULL
import android.widget.CheckBox
import android.widget.TextView
import androidx.appcompat.app.AlertDialog
+import androidx.core.view.inputmethod.EditorInfoCompat
import androidx.core.view.isVisible
import androidx.test.ext.junit.runners.AndroidJUnit4
import mozilla.components.feature.prompts.R.id
@@ -41,7 +43,7 @@ class TextPromptDialogFragmentTest {
@Test
fun `build dialog`() {
val fragment = spy(
- TextPromptDialogFragment.newInstance("sessionId", "uid", true, "title", "label", "defaultValue", true),
+ TextPromptDialogFragment.newInstance("sessionId", "uid", true, "title", "label", "defaultValue", true, false),
)
doReturn(appCompatContext).`when`(fragment).requireContext()
@@ -73,12 +75,14 @@ class TextPromptDialogFragmentTest {
inputValue.text = "NewValue"
assertEquals(inputValue.text.toString(), "NewValue")
+
+ assertEquals(IME_NULL, inputValue.imeOptions)
}
@Test
fun `TextPrompt with hasShownManyDialogs equals false should not have a checkbox`() {
val fragment = spy(
- TextPromptDialogFragment.newInstance("sessionId", "uid", false, "title", "label", "defaultValue", false),
+ TextPromptDialogFragment.newInstance("sessionId", "uid", false, "title", "label", "defaultValue", false, false),
)
doReturn(appCompatContext).`when`(fragment).requireContext()
@@ -95,7 +99,7 @@ class TextPromptDialogFragmentTest {
@Test
fun `Clicking on positive button notifies the feature`() {
val fragment = spy(
- TextPromptDialogFragment.newInstance("sessionId", "uid", true, "title", "label", "defaultValue", false),
+ TextPromptDialogFragment.newInstance("sessionId", "uid", true, "title", "label", "defaultValue", false, false),
)
fragment.feature = mockFeature
@@ -115,7 +119,7 @@ class TextPromptDialogFragmentTest {
@Test
fun `After checking no more dialogs checkbox feature onNoMoreDialogsChecked must be called`() {
val fragment = spy(
- TextPromptDialogFragment.newInstance("sessionId", "uid", false, "title", "label", "defaultValue", true),
+ TextPromptDialogFragment.newInstance("sessionId", "uid", false, "title", "label", "defaultValue", true, false),
)
fragment.feature = mockFeature
@@ -139,7 +143,7 @@ class TextPromptDialogFragmentTest {
@Test
fun `touching outside of the dialog must notify the feature onCancel`() {
val fragment = spy(
- TextPromptDialogFragment.newInstance("sessionId", "uid", true, "title", "label", "defaultValue", true),
+ TextPromptDialogFragment.newInstance("sessionId", "uid", true, "title", "label", "defaultValue", true, false),
)
fragment.feature = mockFeature
@@ -150,4 +154,19 @@ class TextPromptDialogFragmentTest {
verify(mockFeature).onCancel("sessionId", "uid")
}
+
+ @Test
+ fun `when TextPromptDialogFragment is created in private mode then keyboard is in private mode`() {
+ val fragment = spy(
+ TextPromptDialogFragment.newInstance("sessionId", "uid", true, "title", "label", "defaultValue", true, true),
+ )
+
+ fragment.feature = mockFeature
+ doReturn(appCompatContext).`when`(fragment).requireContext()
+
+ val dialog = fragment.onCreateDialog(null).also { it.show() }
+ val editText = dialog.findViewById<TextView>(id.input_value)
+
+ assertEquals(EditorInfoCompat.IME_FLAG_NO_PERSONALIZED_LEARNING, editText.imeOptions)
+ }
}
diff --git a/mobile/android/android-components/components/feature/pwa/src/main/java/mozilla/components/feature/pwa/WebAppShortcutManager.kt b/mobile/android/android-components/components/feature/pwa/src/main/java/mozilla/components/feature/pwa/WebAppShortcutManager.kt
index a97b3b8415..e754e89c60 100644
--- a/mobile/android/android-components/components/feature/pwa/src/main/java/mozilla/components/feature/pwa/WebAppShortcutManager.kt
+++ b/mobile/android/android-components/components/feature/pwa/src/main/java/mozilla/components/feature/pwa/WebAppShortcutManager.kt
@@ -26,6 +26,7 @@ import mozilla.components.browser.icons.decoder.ICOIconDecoder
import mozilla.components.browser.icons.extension.toIconRequest
import mozilla.components.browser.icons.generator.DefaultIconGenerator
import mozilla.components.browser.icons.loader.DataUriIconLoader
+import mozilla.components.browser.icons.loader.DefaultMemoryInfoProvider
import mozilla.components.browser.icons.loader.HttpIconLoader
import mozilla.components.browser.icons.loader.MemoryIconLoader
import mozilla.components.browser.icons.preparer.MemoryIconPreparer
@@ -271,7 +272,7 @@ private fun webAppIcons(
),
loaders = listOf(
MemoryIconLoader(pwaIconMemoryCache),
- HttpIconLoader(httpClient),
+ HttpIconLoader(httpClient, DefaultMemoryInfoProvider(context)),
DataUriIconLoader(),
),
decoders = listOf(
diff --git a/mobile/android/android-components/components/feature/qr/build.gradle b/mobile/android/android-components/components/feature/qr/build.gradle
index f491a3e0a8..beebfcd1f5 100644
--- a/mobile/android/android-components/components/feature/qr/build.gradle
+++ b/mobile/android/android-components/components/feature/qr/build.gradle
@@ -28,6 +28,7 @@ dependencies {
implementation ComponentsDependencies.kotlin_coroutines
implementation ComponentsDependencies.androidx_appcompat
+ implementation ComponentsDependencies.androidx_core_ktx
implementation project(':support-ktx')
implementation project(':support-base')
diff --git a/mobile/android/android-components/components/feature/readerview/src/main/assets/extensions/readerview/manifest.template.json b/mobile/android/android-components/components/feature/readerview/src/main/assets/extensions/readerview/manifest.template.json
index 616b2036eb..7eb8d17589 100644
--- a/mobile/android/android-components/components/feature/readerview/src/main/assets/extensions/readerview/manifest.template.json
+++ b/mobile/android/android-components/components/feature/readerview/src/main/assets/extensions/readerview/manifest.template.json
@@ -10,7 +10,10 @@
"content_scripts": [
{
"matches": ["<all_urls>"],
- "js": ["readability/readability-readerable-0.4.2.js", "readerview-content.js"],
+ "js": [
+ "readability/readability-readerable-0.4.2.js",
+ "readerview-content.js"
+ ],
"run_at": "document_idle"
}
],
diff --git a/mobile/android/android-components/components/feature/readerview/src/main/assets/extensions/readerview/readerview-background.js b/mobile/android/android-components/components/feature/readerview/src/main/assets/extensions/readerview/readerview-background.js
index 136e5e40e3..41e7b1f538 100644
--- a/mobile/android/android-components/components/feature/readerview/src/main/assets/extensions/readerview/readerview-background.js
+++ b/mobile/android/android-components/components/feature/readerview/src/main/assets/extensions/readerview/readerview-background.js
@@ -7,16 +7,16 @@
browser.runtime.onMessage.addListener(message => {
switch (message.action) {
- case 'addSerializedDoc':
- browser.storage.session.set({ [message.id]: message.doc });
- return Promise.resolve();
- case 'getSerializedDoc':
- return (async () => {
- let doc = await browser.storage.session.get(message.id);
- browser.storage.session.remove(message.id);
- return doc[message.id];
- })();
- default:
- console.error(`Received unsupported action ${message.action}`);
- }
+ case "addSerializedDoc":
+ browser.storage.session.set({ [message.id]: message.doc });
+ return Promise.resolve();
+ case "getSerializedDoc":
+ return (async () => {
+ let doc = await browser.storage.session.get(message.id);
+ browser.storage.session.remove(message.id);
+ return doc[message.id];
+ })();
+ default:
+ console.error(`Received unsupported action ${message.action}`);
+ }
});
diff --git a/mobile/android/android-components/components/feature/readerview/src/main/assets/extensions/readerview/readerview-content.js b/mobile/android/android-components/components/feature/readerview/src/main/assets/extensions/readerview/readerview-content.js
index 1d5859e793..cdcbe0434c 100644
--- a/mobile/android/android-components/components/feature/readerview/src/main/assets/extensions/readerview/readerview-content.js
+++ b/mobile/android/android-components/components/feature/readerview/src/main/assets/extensions/readerview/readerview-content.js
@@ -17,43 +17,53 @@ const blockedHosts = [
"pinterest.com",
"reddit.com",
"twitter.com",
- "youtube.com"
+ "youtube.com",
];
function isReaderable() {
- if (!supportedProtocols.includes(location.protocol)) {
- return false;
- }
+ if (!supportedProtocols.includes(location.protocol)) {
+ return false;
+ }
- if (blockedHosts.some(blockedHost => location.hostname.endsWith(blockedHost))) {
- return false;
- }
+ if (
+ blockedHosts.some(blockedHost => location.hostname.endsWith(blockedHost))
+ ) {
+ return false;
+ }
- if (location.pathname == "/") {
- return false;
- }
+ if (location.pathname == "/") {
+ return false;
+ }
- return isProbablyReaderable(document, _isNodeVisible);
+ return isProbablyReaderable(document, _isNodeVisible);
}
function _isNodeVisible(node) {
- return node.clientHeight > 0 && node.clientWidth > 0;
+ return node.clientHeight > 0 && node.clientWidth > 0;
}
function connectNativePort() {
let port = browser.runtime.connectNative("mozacReaderview");
- port.onMessage.addListener((message) => {
- switch (message.action) {
- case 'cachePage':
- let serializedDoc = new XMLSerializer().serializeToString(document);
- browser.runtime.sendMessage({action: "addSerializedDoc", doc: serializedDoc, id: message.id});
- break;
- case 'checkReaderState':
- port.postMessage({type: 'checkReaderState', baseUrl: browser.runtime.getURL("/"), readerable: isReaderable()});
- break;
- default:
- console.error(`Received unsupported action ${message.action}`);
- }
+ port.onMessage.addListener(message => {
+ switch (message.action) {
+ case "cachePage":
+ let serializedDoc = new XMLSerializer().serializeToString(document);
+ browser.runtime.sendMessage({
+ action: "addSerializedDoc",
+ doc: serializedDoc,
+ id: message.id,
+ });
+ break;
+ case "checkReaderState":
+ port.postMessage({
+ type: "checkReaderState",
+ baseUrl: browser.runtime.getURL("/"),
+ readerable: isReaderable(),
+ });
+ break;
+ default:
+ console.error(`Received unsupported action ${message.action}`);
+ }
});
return port;
@@ -65,11 +75,11 @@ let port = connectNativePort();
// do want to connect a new native port to trigger a new readerable check and
// apply the same logic (as on page load) in our feature class (e.g. updating the
// toolbar etc.)
-window.addEventListener("pageshow", (event) => {
- port = (port != null)? port : connectNativePort();
+window.addEventListener("pageshow", event => {
+ port = port != null ? port : connectNativePort();
});
-window.addEventListener("pagehide", (event) => {
+window.addEventListener("pagehide", event => {
port.disconnect();
port = null;
});
diff --git a/mobile/android/android-components/components/feature/readerview/src/main/assets/extensions/readerview/readerview.html b/mobile/android/android-components/components/feature/readerview/src/main/assets/extensions/readerview/readerview.html
index b09deb7811..99afab71a4 100644
--- a/mobile/android/android-components/components/feature/readerview/src/main/assets/extensions/readerview/readerview.html
+++ b/mobile/android/android-components/components/feature/readerview/src/main/assets/extensions/readerview/readerview.html
@@ -4,14 +4,14 @@
<html>
<head>
- <meta content="text/html; charset=UTF-8" http-equiv="content-type" />
- <meta name="viewport" content="width=device-width; user-scalable=0" />
- <meta http-equiv="cache-control" content="no-store" />
+ <meta content="text/html; charset=UTF-8" http-equiv="content-type" />
+ <meta name="viewport" content="width=device-width; user-scalable=0" />
+ <meta http-equiv="cache-control" content="no-store" />
- <link rel="stylesheet" href="readerview.css" />
+ <link rel="stylesheet" href="readerview.css" />
- <script src="readability/JSDOMParser-0.4.2.js"></script>
- <script src="readability/readability-0.4.2.js"></script>
- <script src="readerview.js"></script>
+ <script src="readability/JSDOMParser-0.4.2.js"></script>
+ <script src="readability/readability-0.4.2.js"></script>
+ <script src="readerview.js"></script>
</head>
</html>
diff --git a/mobile/android/android-components/components/feature/readerview/src/main/assets/extensions/readerview/readerview.js b/mobile/android/android-components/components/feature/readerview/src/main/assets/extensions/readerview/readerview.js
index 23b1f35250..ddea9218b0 100644
--- a/mobile/android/android-components/components/feature/readerview/src/main/assets/extensions/readerview/readerview.js
+++ b/mobile/android/android-components/components/feature/readerview/src/main/assets/extensions/readerview/readerview.js
@@ -15,11 +15,10 @@ const preservedClasses = [
"visuallyhidden",
"wp-caption",
"wp-caption-text",
- "wp-smiley"
+ "wp-smiley",
];
class ReaderView {
-
static get MIN_FONT_SIZE() {
return 1;
}
@@ -37,18 +36,24 @@ class ReaderView {
* @param url the url of the article.
* @param options the fontSize, fontType and colorScheme to use.
*/
- show(doc, url, options = {fontSize: 4, fontType: "sans-serif", colorScheme: "light"}) {
- let result = new Readability(doc, {classesToPreserve: preservedClasses}).parse();
+ show(
+ doc,
+ url,
+ options = { fontSize: 4, fontType: "sans-serif", colorScheme: "light" }
+ ) {
+ let result = new Readability(doc, {
+ classesToPreserve: preservedClasses,
+ }).parse();
result.language = doc.documentElement.lang;
document.title = result.title;
let article = Object.assign(
result,
- {url: new URL(url)},
- {readingTime: this.getReadingTime(result.length, result.language)},
- {byline: this.getByline(result)},
- {dir: this.getTextDirection(result)},
- {title: this.getTitle(result)}
+ { url: new URL(url) },
+ { readingTime: this.getReadingTime(result.length, result.language) },
+ { byline: this.getByline(result) },
+ { dir: this.getTextDirection(result) },
+ { title: this.getTitle(result) }
);
document.body.outerHTML = this.createHtmlBody(article);
@@ -57,7 +62,7 @@ class ReaderView {
this.setFontType(options.fontType);
this.setColorScheme(options.colorScheme);
if (options.scrollY) {
- window.scrollTo({top: options.scrollY, left: 0, behavior: "instant"});
+ window.scrollTo({ top: options.scrollY, left: 0, behavior: "instant" });
}
}
@@ -68,7 +73,10 @@ class ReaderView {
* @param changeAmount e.g. +1, or -1.
*/
changeFontSize(changeAmount) {
- var size = Math.max(ReaderView.MIN_FONT_SIZE, Math.min(ReaderView.MAX_FONT_SIZE, this.fontSize + changeAmount));
+ var size = Math.max(
+ ReaderView.MIN_FONT_SIZE,
+ Math.min(ReaderView.MAX_FONT_SIZE, this.fontSize + changeAmount)
+ );
this.setFontSize(size);
}
@@ -79,7 +87,7 @@ class ReaderView {
* and ReaderView.MAX_FONT_SIZE.
*/
setFontSize(fontSize) {
- let size = (10 + 2 * fontSize) + "px";
+ let size = 10 + 2 * fontSize + "px";
let readerView = document.getElementById("mozac-readerview-container");
readerView.style.setProperty("font-size", size);
this.fontSize = fontSize;
@@ -108,8 +116,8 @@ class ReaderView {
* or sepia.
*/
setColorScheme(colorScheme) {
- if(!['light', 'sepia', 'dark'].includes(colorScheme)) {
- console.error(`Invalid color scheme specified: ${colorScheme}`)
+ if (!["light", "sepia", "dark"].includes(colorScheme)) {
+ console.error(`Invalid color scheme specified: ${colorScheme}`);
return;
}
@@ -152,7 +160,7 @@ class ReaderView {
</div>
</div>
</body>
- `
+ `;
}
/**
@@ -162,17 +170,21 @@ class ReaderView {
* @param optional language of the article, defaults to en.
*/
getReadingTime(length, lang = "en") {
- const [readingSpeed, readingSpeedLang] = this.getReadingSpeedForLanguage(lang);
+ const [readingSpeed, readingSpeedLang] =
+ this.getReadingSpeedForLanguage(lang);
const charactersPerMinuteLow = readingSpeed.cpm - readingSpeed.variance;
const charactersPerMinuteHigh = readingSpeed.cpm + readingSpeed.variance;
const readingTimeMinsSlow = Math.ceil(length / charactersPerMinuteLow);
- const readingTimeMinsFast = Math.ceil(length / charactersPerMinuteHigh);
+ const readingTimeMinsFast = Math.ceil(length / charactersPerMinuteHigh);
// Construct a localized and "humanized" reading time in minutes.
// If we have both a fast and slow reading time we'll show both e.g.
// "2 - 4 minutes", otherwise we'll just show "4 minutes".
try {
- var parts = new Intl.RelativeTimeFormat(readingSpeedLang).formatToParts(readingTimeMinsSlow, 'minute');
+ var parts = new Intl.RelativeTimeFormat(readingSpeedLang).formatToParts(
+ readingTimeMinsSlow,
+ "minute"
+ );
if (parts.length == 3) {
// No need to use part[0] which represents the literal "in".
var readingTime = parts[1].value; // reading time in minutes
@@ -183,8 +195,7 @@ class ReaderView {
}
return readingTimeString;
}
- }
- catch(error) {
+ } catch (error) {
console.error(`Failed to format reading time: ${error}`);
}
@@ -202,60 +213,62 @@ class ReaderView {
*/
getReadingSpeedForLanguage(lang) {
const readingSpeed = new Map([
- [ "en", {cpm: 987, variance: 118 } ],
- [ "ar", {cpm: 612, variance: 88 } ],
- [ "de", {cpm: 920, variance: 86 } ],
- [ "es", {cpm: 1025, variance: 127 } ],
- [ "fi", {cpm: 1078, variance: 121 } ],
- [ "fr", {cpm: 998, variance: 126 } ],
- [ "he", {cpm: 833, variance: 130 } ],
- [ "it", {cpm: 950, variance: 140 } ],
- [ "jw", {cpm: 357, variance: 56 } ],
- [ "nl", {cpm: 978, variance: 143 } ],
- [ "pl", {cpm: 916, variance: 126 } ],
- [ "pt", {cpm: 913, variance: 145 } ],
- [ "ru", {cpm: 986, variance: 175 } ],
- [ "sk", {cpm: 885, variance: 145 } ],
- [ "sv", {cpm: 917, variance: 156 } ],
- [ "tr", {cpm: 1054, variance: 156 } ],
- [ "zh", {cpm: 255, variance: 29 } ],
+ ["en", { cpm: 987, variance: 118 }],
+ ["ar", { cpm: 612, variance: 88 }],
+ ["de", { cpm: 920, variance: 86 }],
+ ["es", { cpm: 1025, variance: 127 }],
+ ["fi", { cpm: 1078, variance: 121 }],
+ ["fr", { cpm: 998, variance: 126 }],
+ ["he", { cpm: 833, variance: 130 }],
+ ["it", { cpm: 950, variance: 140 }],
+ ["jw", { cpm: 357, variance: 56 }],
+ ["nl", { cpm: 978, variance: 143 }],
+ ["pl", { cpm: 916, variance: 126 }],
+ ["pt", { cpm: 913, variance: 145 }],
+ ["ru", { cpm: 986, variance: 175 }],
+ ["sk", { cpm: 885, variance: 145 }],
+ ["sv", { cpm: 917, variance: 156 }],
+ ["tr", { cpm: 1054, variance: 156 }],
+ ["zh", { cpm: 255, variance: 29 }],
]);
- return readingSpeed.has(lang) ? [readingSpeed.get(lang), lang] : [readingSpeed.get("en"), "en"];
- }
-
- getByline(article) {
- return article.byline || "";
- }
-
- /**
- * Attempts to read the optional text direction from the article and uses
- * language mapping to detect rtl, if missing.
- */
- getTextDirection(article) {
- if (article.dir) {
- return article.dir;
- }
-
- if (["ar", "fa", "he", "ug", "ur"].includes(article.language)) {
- return "rtl";
- }
-
- return "ltr";
- }
-
- getTitle(article) {
- return article.title || "";
- }
-
- escapeHTML(text) {
- return text
- .replace(/\&/g, "&amp;")
- .replace(/\</g, "&lt;")
- .replace(/\>/g, "&gt;")
- .replace(/\"/g, "&quot;")
- .replace(/\'/g, "&#039;");
- }
+ return readingSpeed.has(lang)
+ ? [readingSpeed.get(lang), lang]
+ : [readingSpeed.get("en"), "en"];
+ }
+
+ getByline(article) {
+ return article.byline || "";
+ }
+
+ /**
+ * Attempts to read the optional text direction from the article and uses
+ * language mapping to detect rtl, if missing.
+ */
+ getTextDirection(article) {
+ if (article.dir) {
+ return article.dir;
+ }
+
+ if (["ar", "fa", "he", "ug", "ur"].includes(article.language)) {
+ return "rtl";
+ }
+
+ return "ltr";
+ }
+
+ getTitle(article) {
+ return article.title || "";
+ }
+
+ escapeHTML(text) {
+ return text
+ .replace(/\&/g, "&amp;")
+ .replace(/\</g, "&lt;")
+ .replace(/\>/g, "&gt;")
+ .replace(/\"/g, "&quot;")
+ .replace(/\'/g, "&#039;");
+ }
}
function fetchDocument(url) {
@@ -282,16 +295,16 @@ function fetchDocument(url) {
function getPreparedDocument(id, url) {
return new Promise((resolve, reject) => {
-
- browser.runtime.sendMessage({action: "getSerializedDoc", id: id}).then((serializedDoc) => {
+ browser.runtime
+ .sendMessage({ action: "getSerializedDoc", id: id })
+ .then(serializedDoc => {
if (serializedDoc) {
let doc = new JSDOMParser().parse(serializedDoc, url);
resolve(doc);
} else {
reject();
}
- }
- );
+ });
});
}
@@ -306,23 +319,26 @@ function connectNativePort() {
let baseUrl = browser.runtime.getURL("/");
let port = browser.runtime.connectNative("mozacReaderviewActive");
- port.onMessage.addListener((message) => {
+ port.onMessage.addListener(message => {
switch (message.action) {
- case 'show':
+ case "show":
async function showAsync(options) {
try {
let doc;
if (typeof Promise.any === "function") {
- doc = await Promise.any([fetchDocument(articleUrl), getPreparedDocument(id, articleUrl)]);
+ doc = await Promise.any([
+ fetchDocument(articleUrl),
+ getPreparedDocument(id, articleUrl),
+ ]);
} else {
try {
doc = await getPreparedDocument(id, articleUrl);
- } catch(e) {
+ } catch (e) {
doc = await fetchDocument(articleUrl);
}
}
readerView.show(doc, articleUrl, options);
- } catch(e) {
+ } catch (e) {
console.log(e);
// We weren't able to find the prepared document and also
// failed to fetch it. Let's load the original page which
@@ -332,19 +348,23 @@ function connectNativePort() {
}
showAsync(message.value);
break;
- case 'hide':
+ case "hide":
window.location.href = articleUrl;
- case 'setColorScheme':
+ case "setColorScheme":
readerView.setColorScheme(message.value.toLowerCase());
break;
- case 'changeFontSize':
+ case "changeFontSize":
readerView.changeFontSize(message.value);
break;
- case 'setFontType':
+ case "setFontType":
readerView.setFontType(message.value.toLowerCase());
break;
- case 'checkReaderState':
- port.postMessage({baseUrl: baseUrl, activeUrl: articleUrl, readerable: true});
+ case "checkReaderState":
+ port.postMessage({
+ baseUrl: baseUrl,
+ activeUrl: articleUrl,
+ readerable: true,
+ });
break;
default:
console.error(`Received invalid action ${message.action}`);
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
index 65bf306835..0778799326 100644
--- 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
@@ -10,12 +10,12 @@
* to the native application.
*/
function sendCurrentState() {
- let message = {
- 'url': document.location.href,
- 'urls': getLinks(),
- 'cookies': getCookies()
- };
- browser.runtime.sendNativeMessage("MozacBrowserAdsMessage", message);
+ let message = {
+ url: document.location.href,
+ urls: getLinks(),
+ cookies: getCookies(),
+ };
+ browser.runtime.sendNativeMessage("MozacBrowserAdsMessage", message);
}
/**
@@ -24,17 +24,17 @@ function sendCurrentState() {
* @return {Array<string>} containing all current links in the current page.
*/
function getLinks() {
- let urls = [];
+ let urls = [];
- let anchors = document.getElementsByTagName("a");
- for (let anchor of anchors) {
- if (!anchor.href) {
- continue;
- }
- urls.push(anchor.href);
+ let anchors = document.getElementsByTagName("a");
+ for (let anchor of anchors) {
+ if (!anchor.href) {
+ continue;
}
+ urls.push(anchor.href);
+ }
- return urls;
+ return urls;
}
/**
@@ -43,40 +43,38 @@ function getLinks() {
* @return {Array<{name: string, value: string}>} containing all cookies.
*/
function getCookies() {
- let cookiesList = document.cookie.split("; ");
- let result = [];
+ 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("=")
+ 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
- });
+ result.push({
+ name: name,
+ value: value,
});
+ });
- return result;
+ 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) {
+ switch (event.type) {
case "load":
- sendCurrentState();
- break;
+ sendCurrentState();
+ break;
case "pageshow":
- if (event.persisted) {
- sendCurrentState();
- }
- break;
+ if (event.persisted) {
+ sendCurrentState();
+ }
+ break;
default:
- console.log('Event:', event.type);
- }
+ console.log("Event:", event.type);
+ }
};
-events.forEach(eventName =>
- window.addEventListener(eventName, eventLogger)
-);
+events.forEach(eventName => window.addEventListener(eventName, eventLogger));
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
index 3199335fdf..355f378b9c 100644
--- 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
@@ -9,11 +9,11 @@
* to the native application.
*/
function sendCurrentState() {
- let message = {
- 'url': document.location.href,
- 'cookies': getCookies()
- };
- browser.runtime.sendNativeMessage("MozacBrowserSearchMessage", message);
+ let message = {
+ url: document.location.href,
+ cookies: getCookies(),
+ };
+ browser.runtime.sendNativeMessage("MozacBrowserSearchMessage", message);
}
/**
@@ -22,40 +22,38 @@ function sendCurrentState() {
* @return {Array<{name: string, value: string}>} containing all cookies.
*/
function getCookies() {
- let cookiesList = document.cookie.split("; ");
- let result = [];
+ 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("=");
+ 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
- });
+ result.push({
+ name: name,
+ value: value,
});
+ });
- return result;
+ 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) {
+ switch (event.type) {
case "load":
- sendCurrentState();
- break;
+ sendCurrentState();
+ break;
case "pageshow":
- if (event.persisted) {
- sendCurrentState();
- }
- break;
+ if (event.persisted) {
+ sendCurrentState();
+ }
+ break;
default:
- console.log('Event:', event.type);
- }
+ console.log("Event:", event.type);
+ }
};
-events.forEach(eventName =>
- window.addEventListener(eventName, eventLogger)
-);
+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
index b2bb3d4698..5bd6349fe5 100644
--- 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
@@ -2,9 +2,7 @@
"default": {
"searchDefault": "Google",
"searchOrder": ["Google", "Bing"],
- "visibleDefaultEngines": [
- "google-b-m", "bing", "amazondotcom", "ddg", "wikipedia"
- ]
+ "visibleDefaultEngines": ["google-b-m", "bing", "ddg", "wikipedia"]
},
"regionOverrides": {
"US": {
@@ -14,898 +12,1038 @@
"locales": {
"ach": {
"default": {
- "visibleDefaultEngines": [
- "google-b-m", "bing", "ddg", "wikipedia"
- ]
+ "visibleDefaultEngines": ["google-b-m", "bing", "ddg", "wikipedia"]
}
},
"an": {
"default": {
"visibleDefaultEngines": [
- "google-b-m", "bing", "ddg", "ebay-es","wikipedia-an"
+ "google-b-m",
+ "bing",
+ "ddg",
+ "ebay-es",
+ "wikipedia-an"
]
}
},
"ar": {
"default": {
- "visibleDefaultEngines": [
- "google-b-m", "bing", "amazondotcom", "ddg", "wikipedia-ar"
- ]
+ "visibleDefaultEngines": ["google-b-m", "bing", "ddg", "wikipedia-ar"]
}
},
"as": {
"default": {
- "visibleDefaultEngines": [
- "google-b-m", "bing", "amazon-in", "ddg", "wikipedia-as"
- ]
+ "visibleDefaultEngines": ["google-b-m", "bing", "ddg", "wikipedia-as"]
}
},
"ast": {
"default": {
"visibleDefaultEngines": [
- "google-b-m", "bing", "amazondotcom", "ddg", "ebay-es", "wikipedia-ast"
+ "google-b-m",
+ "bing",
+ "ddg",
+ "ebay-es",
+ "wikipedia-ast"
]
}
},
"az": {
"default": {
"visibleDefaultEngines": [
- "google-b-m", "bing", "amazondotcom", "ddg", "azerdict", "wikipedia-az"
+ "google-b-m",
+ "bing",
+ "ddg",
+ "azerdict",
+ "wikipedia-az"
]
}
},
"be": {
"default": {
- "visibleDefaultEngines": [
- "google-b-m", "bing", "ddg", "wikipedia-be"
- ]
+ "visibleDefaultEngines": ["google-b-m", "bing", "ddg", "wikipedia-be"]
},
"BY": {
"visibleDefaultEngines": [
- "google-com-nocodes", "bing", "ddg", "wikipedia-be"
+ "google-com-nocodes",
+ "bing",
+ "ddg",
+ "wikipedia-be"
]
},
"KZ": {
"visibleDefaultEngines": [
- "google-com-nocodes", "bing", "ddg", "wikipedia-be"
+ "google-com-nocodes",
+ "bing",
+ "ddg",
+ "wikipedia-be"
]
},
"RU": {
"visibleDefaultEngines": [
- "google-com-nocodes", "bing", "ddg", "wikipedia-be"
+ "google-com-nocodes",
+ "bing",
+ "ddg",
+ "wikipedia-be"
]
},
"TR": {
"visibleDefaultEngines": [
- "google-com-nocodes", "bing", "ddg", "wikipedia-be"
+ "google-com-nocodes",
+ "bing",
+ "ddg",
+ "wikipedia-be"
]
}
},
"bg": {
"default": {
"visibleDefaultEngines": [
- "google-b-m", "bing", "ddg", "pazaruvaj", "wikipedia-bg"
+ "google-b-m",
+ "bing",
+ "ddg",
+ "pazaruvaj",
+ "wikipedia-bg"
]
}
},
"bn": {
"default": {
- "visibleDefaultEngines": [
- "google-b-m", "bing", "ddg", "wikipedia-bn"
- ]
+ "visibleDefaultEngines": ["google-b-m", "bing", "ddg", "wikipedia-bn"]
}
},
"bn-BD": {
"default": {
- "visibleDefaultEngines": [
- "google-b-m", "bing", "ddg", "wikipedia-bn"
- ]
+ "visibleDefaultEngines": ["google-b-m", "bing", "ddg", "wikipedia-bn"]
}
},
"bn-IN": {
"default": {
- "visibleDefaultEngines": [
- "google-b-m", "bing", "amazondotcom", "ddg", "wikipedia-bn"
- ]
+ "visibleDefaultEngines": ["google-b-m", "bing", "ddg", "wikipedia-bn"]
}
},
"br": {
"default": {
- "visibleDefaultEngines": [
- "google-b-m", "bing", "ddg", "wikipedia-br"
- ]
+ "visibleDefaultEngines": ["google-b-m", "bing", "ddg", "wikipedia-br"]
}
},
"bs": {
"default": {
- "visibleDefaultEngines": [
- "google-b-m", "bing", "ddg", "wikipedia-bs"
- ]
+ "visibleDefaultEngines": ["google-b-m", "bing", "ddg", "wikipedia-bs"]
}
},
"ca": {
"default": {
"visibleDefaultEngines": [
- "google-b-m", "bing", "ddg", "ebay-es", "wikipedia-ca"
+ "google-b-m",
+ "bing",
+ "ddg",
+ "ebay-es",
+ "wikipedia-ca"
]
}
},
"cak": {
"default": {
- "visibleDefaultEngines": [
- "google-b-m", "bing", "amazondotcom", "ddg", "wikipedia-es"
- ]
+ "visibleDefaultEngines": ["google-b-m", "bing", "ddg", "wikipedia-es"]
}
},
"cs": {
"default": {
"visibleDefaultEngines": [
- "google-b-m", "bing", "ddg", "mapy-cz", "seznam-cz", "wikipedia-cz"
+ "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"
+ "google-b-m",
+ "bing",
+ "ddg",
+ "ebay-co-uk",
+ "wikipedia-cy"
]
}
},
"da": {
"default": {
- "visibleDefaultEngines": [
- "google-b-m", "amazon-co-uk", "bing", "ddg", "wikipedia-da"
- ]
+ "visibleDefaultEngines": ["google-b-m", "bing", "ddg", "wikipedia-da"]
}
},
"de": {
"default": {
"visibleDefaultEngines": [
- "google-b-m", "bing", "amazon-de", "ddg", "ecosia", "qwant", "wikipedia-de", "ebay-de"
+ "google-b-m",
+ "bing",
+ "ddg",
+ "ecosia",
+ "qwant",
+ "wikipedia-de",
+ "ebay-de"
]
}
},
"de-AT": {
"default": {
"visibleDefaultEngines": [
- "google-b-m", "bing", "amazon-de", "ddg", "ecosia", "qwant", "wikipedia-de", "ebay-at"
+ "google-b-m",
+ "bing",
+ "ddg",
+ "ecosia",
+ "qwant",
+ "wikipedia-de",
+ "ebay-at"
]
}
},
"dsb": {
"default": {
"visibleDefaultEngines": [
- "google-b-m", "bing", "amazon-de", "ddg", "wikipedia-dsb", "ebay-de"
+ "google-b-m",
+ "bing",
+ "ddg",
+ "wikipedia-dsb",
+ "ebay-de"
]
}
},
"el": {
"default": {
- "visibleDefaultEngines": [
- "google-b-m", "bing", "ddg", "wikipedia-el"
- ]
+ "visibleDefaultEngines": ["google-b-m", "bing", "ddg", "wikipedia-el"]
}
},
"en-AU": {
"default": {
"visibleDefaultEngines": [
- "google-b-m", "bing", "amazon-au", "ddg", "wikipedia", "ebay-au"
+ "google-b-m",
+ "bing",
+ "ddg",
+ "wikipedia",
+ "ebay-au"
]
}
},
"en-CA": {
"default": {
"visibleDefaultEngines": [
- "google-b-m", "bing", "amazon-ca", "ddg", "wikipedia", "ebay-ca"
+ "google-b-m",
+ "bing",
+ "ddg",
+ "wikipedia",
+ "ebay-ca"
]
}
},
"en-IE": {
"default": {
"visibleDefaultEngines": [
- "google-b-m", "bing", "amazon-co-uk", "ddg", "qwant", "wikipedia", "ebay-ie"
+ "google-b-m",
+ "bing",
+ "ddg",
+ "qwant",
+ "wikipedia",
+ "ebay-ie"
]
}
},
"en-GB": {
"default": {
"visibleDefaultEngines": [
- "google-b-m", "bing", "amazon-co-uk", "ddg", "qwant", "wikipedia", "ebay-co-uk"
+ "google-b-m",
+ "bing",
+ "ddg",
+ "qwant",
+ "wikipedia",
+ "ebay-co-uk"
]
},
"BY": {
"visibleDefaultEngines": [
- "google-com-nocodes", "bing", "amazon-co-uk", "ddg", "qwant", "wikipedia"
+ "google-com-nocodes",
+ "bing",
+ "ddg",
+ "qwant",
+ "wikipedia"
]
},
"KZ": {
"visibleDefaultEngines": [
- "google-com-nocodes", "bing", "amazon-co-uk", "ddg", "qwant", "wikipedia"
+ "google-com-nocodes",
+ "bing",
+ "ddg",
+ "qwant",
+ "wikipedia"
]
},
"RU": {
"visibleDefaultEngines": [
- "google-com-nocodes", "bing", "amazon-co-uk", "ddg", "qwant", "wikipedia"
+ "google-com-nocodes",
+ "bing",
+ "ddg",
+ "qwant",
+ "wikipedia"
]
},
"TR": {
"visibleDefaultEngines": [
- "google-com-nocodes", "bing", "amazon-co-uk", "ddg", "qwant", "wikipedia"
+ "google-com-nocodes",
+ "bing",
+ "ddg",
+ "qwant",
+ "wikipedia"
]
}
},
"en-US": {
"default": {
"visibleDefaultEngines": [
- "google-b-m", "bing", "amazondotcom", "ddg", "ebay", "wikipedia"
+ "google-b-m",
+ "bing",
+ "ddg",
+ "ebay",
+ "wikipedia"
]
},
"BY": {
"visibleDefaultEngines": [
- "google-com-nocodes", "bing", "amazondotcom", "ddg", "wikipedia"
+ "google-com-nocodes",
+ "bing",
+ "ddg",
+ "wikipedia"
]
},
"KZ": {
"visibleDefaultEngines": [
- "google-com-nocodes", "bing", "amazondotcom", "ddg", "wikipedia"
+ "google-com-nocodes",
+ "bing",
+ "ddg",
+ "wikipedia"
]
},
"RU": {
"visibleDefaultEngines": [
- "google-com-nocodes", "bing", "amazondotcom", "ddg", "wikipedia"
+ "google-com-nocodes",
+ "bing",
+ "ddg",
+ "wikipedia"
]
},
"TR": {
"visibleDefaultEngines": [
- "google-com-nocodes", "bing", "amazondotcom", "ddg", "wikipedia"
+ "google-com-nocodes",
+ "bing",
+ "ddg",
+ "wikipedia"
]
}
},
"en-ZA": {
"default": {
- "visibleDefaultEngines": [
- "google-b-m", "ddg", "wikipedia"
- ]
+ "visibleDefaultEngines": ["google-b-m", "ddg", "wikipedia"]
}
},
"eo": {
"default": {
- "visibleDefaultEngines": [
- "google-b-m", "bing", "ddg", "wikipedia-eo"
- ]
+ "visibleDefaultEngines": ["google-b-m", "bing", "ddg", "wikipedia-eo"]
}
},
"es-AR": {
"default": {
"visibleDefaultEngines": [
- "google-b-m", "ddg", "mercadolibre-ar", "wikipedia-es"
+ "google-b-m",
+ "ddg",
+ "mercadolibre-ar",
+ "wikipedia-es"
]
}
},
"es-CL": {
"default": {
"visibleDefaultEngines": [
- "google-b-m", "bing", "ddg", "mercadolibre-cl", "wikipedia-es"
+ "google-b-m",
+ "bing",
+ "ddg",
+ "mercadolibre-cl",
+ "wikipedia-es"
]
}
},
"es-ES": {
"default": {
"visibleDefaultEngines": [
- "google-b-m", "bing", "ddg", "wikipedia-es", "amazon-es", "ebay-es"
+ "google-b-m",
+ "bing",
+ "ddg",
+ "wikipedia-es",
+ "ebay-es"
]
}
},
"es-MX": {
"default": {
"visibleDefaultEngines": [
- "google-b-m", "bing", "amazondotcom", "ddg", "mercadolibre-mx", "wikipedia-es"
+ "google-b-m",
+ "bing",
+ "ddg",
+ "mercadolibre-mx",
+ "wikipedia-es"
]
}
},
"et": {
"default": {
- "visibleDefaultEngines": [
- "google-b-m", "amazon-co-uk", "ddg", "wikipedia-et"
- ]
+ "visibleDefaultEngines": ["google-b-m", "ddg", "wikipedia-et"]
}
},
"eu": {
"default": {
"visibleDefaultEngines": [
- "google-b-m", "bing", "ddg", "ebay-es", "wikipedia-eu"
+ "google-b-m",
+ "bing",
+ "ddg",
+ "ebay-es",
+ "wikipedia-eu"
]
}
},
"fa": {
"default": {
- "visibleDefaultEngines": [
- "google-b-m", "bing", "ddg", "wikipedia-fa"
- ]
+ "visibleDefaultEngines": ["google-b-m", "bing", "ddg", "wikipedia-fa"]
}
},
"ff": {
"default": {
- "visibleDefaultEngines": [
- "google-b-m", "bing", "amazon-fr", "ddg", "wikipedia-fr"
- ]
+ "visibleDefaultEngines": ["google-b-m", "bing", "ddg", "wikipedia-fr"]
}
},
"fi": {
"default": {
- "visibleDefaultEngines": [
- "google-b-m", "amazondotcom", "bing", "ddg", "wikipedia-fi"
- ]
+ "visibleDefaultEngines": ["google-b-m", "bing", "ddg", "wikipedia-fi"]
}
},
"fr-BE": {
"default": {
"visibleDefaultEngines": [
- "google-b-m", "bing", "ddg", "qwant", "wikipedia-fr", "ebay-befr"
+ "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"
+ "google-b-m",
+ "bing",
+ "ddg",
+ "wikipedia-fr",
+ "ebay-ca"
]
}
},
"fr-FR": {
"default": {
"visibleDefaultEngines": [
- "google-b-m", "bing", "ddg", "qwant", "wikipedia-fr", "amazon-fr", "ebay-fr"
+ "google-b-m",
+ "bing",
+ "ddg",
+ "qwant",
+ "wikipedia-fr",
+ "ebay-fr"
]
}
},
"fr": {
"default": {
"visibleDefaultEngines": [
- "google-b-m", "bing", "ddg", "ebay-fr", "qwant", "wikipedia-fr"
+ "google-b-m",
+ "bing",
+ "ddg",
+ "ebay-fr",
+ "qwant",
+ "wikipedia-fr"
]
}
},
"fy-NL": {
"default": {
"visibleDefaultEngines": [
- "google-b-m", "bing", "ddg", "ebay-nl", "wikipedia-fy-NL"
+ "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"
+ "google-b-m",
+ "ddg",
+ "ebay-ie",
+ "wikipedia-ga-IE"
]
}
},
"gd": {
"default": {
"visibleDefaultEngines": [
- "google-b-m", "bing", "ddg", "ebay-co-uk", "faclair-beag", "wikipedia-gd"
+ "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"
+ "google-b-m",
+ "bing",
+ "ddg",
+ "ebay-es",
+ "wikipedia-gl"
]
}
},
"gn": {
"default": {
- "visibleDefaultEngines": [
- "google-b-m", "bing", "amazondotcom", "ddg", "wikipedia-gn"
- ]
+ "visibleDefaultEngines": ["google-b-m", "bing", "ddg", "wikipedia-gn"]
}
},
"gu-IN": {
"default": {
- "visibleDefaultEngines": [
- "google-b-m", "bing", "amazon-in", "ddg", "wikipedia-gu"
- ]
+ "visibleDefaultEngines": ["google-b-m", "bing", "ddg", "wikipedia-gu"]
}
},
"he": {
"default": {
- "visibleDefaultEngines": [
- "google-b-m", "bing", "amazondotcom", "ddg", "wikipedia-he"
- ]
+ "visibleDefaultEngines": ["google-b-m", "bing", "ddg", "wikipedia-he"]
}
},
"hi-IN": {
"default": {
- "visibleDefaultEngines": [
- "google-b-m", "bing", "amazon-in", "ddg", "wikipedia-hi"
- ]
+ "visibleDefaultEngines": ["google-b-m", "bing", "ddg", "wikipedia-hi"]
}
},
"hr": {
"default": {
- "visibleDefaultEngines": [
- "google-b-m", "bing", "amazon-co-uk", "ddg", "wikipedia-hr"
- ]
+ "visibleDefaultEngines": ["google-b-m", "bing", "ddg", "wikipedia-hr"]
}
},
"hsb": {
"default": {
"visibleDefaultEngines": [
- "google-b-m", "bing", "amazon-de", "ddg", "wikipedia-hsb", "ebay-de"
+ "google-b-m",
+ "bing",
+ "ddg",
+ "wikipedia-hsb",
+ "ebay-de"
]
}
},
"hu": {
"default": {
- "visibleDefaultEngines": [
- "google-b-m", "ddg", "vatera", "wikipedia-hu"
- ]
+ "visibleDefaultEngines": ["google-b-m", "ddg", "vatera", "wikipedia-hu"]
}
},
"hy-AM": {
"default": {
"visibleDefaultEngines": [
- "google-b-m", "bing", "amazondotcom", "ddg", "wikipedia-hy-AM"
+ "google-b-m",
+ "bing",
+ "ddg",
+ "wikipedia-hy-AM"
]
}
},
"ia": {
"default": {
- "visibleDefaultEngines": [
- "google-b-m", "bing", "amazondotcom", "ddg", "wikipedia-ia"
- ]
+ "visibleDefaultEngines": ["google-b-m", "bing", "ddg", "wikipedia-ia"]
}
},
"id": {
"default": {
- "visibleDefaultEngines": [
- "google-b-m", "bing", "ddg", "wikipedia-id"
- ]
+ "visibleDefaultEngines": ["google-b-m", "bing", "ddg", "wikipedia-id"]
}
},
"is": {
"default": {
- "visibleDefaultEngines": [
- "google-b-m", "bing", "amazondotcom", "ddg", "wikipedia-is"
- ]
+ "visibleDefaultEngines": ["google-b-m", "bing", "ddg", "wikipedia-is"]
}
},
"it": {
"default": {
"visibleDefaultEngines": [
- "google-b-m", "bing", "ddg", "wikipedia-it", "amazon-it", "ebay-it"
+ "google-b-m",
+ "bing",
+ "ddg",
+ "wikipedia-it",
+ "ebay-it"
]
}
},
"ja": {
"default": {
"visibleDefaultEngines": [
- "google-b-m", "amazon-jp", "bing", "ddg", "rakuten", "wikipedia-ja", "yahoo-jp", "yahoo-jp-auctions"
+ "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"
- ]
+ "visibleDefaultEngines": ["google-b-m", "bing", "ddg", "wikipedia-ka"]
}
},
"kab": {
"default": {
- "visibleDefaultEngines": [
- "google-b-m", "bing", "ddg", "wikipedia-kab"
- ]
+ "visibleDefaultEngines": ["google-b-m", "bing", "ddg", "wikipedia-kab"]
}
},
"kk": {
"default": {
- "visibleDefaultEngines": [
- "google-b-m", "bing", "ddg", "wikipedia-kk"
- ]
+ "visibleDefaultEngines": ["google-b-m", "bing", "ddg", "wikipedia-kk"]
},
"KZ": {
"visibleDefaultEngines": [
- "google-com-nocodes", "bing", "ddg", "wikipedia-kk"
+ "google-com-nocodes",
+ "bing",
+ "ddg",
+ "wikipedia-kk"
]
},
"BY": {
"visibleDefaultEngines": [
- "google-com-nocodes", "bing", "ddg", "wikipedia-kk"
+ "google-com-nocodes",
+ "bing",
+ "ddg",
+ "wikipedia-kk"
]
},
"RU": {
"visibleDefaultEngines": [
- "google-com-nocodes", "bing", "ddg", "wikipedia-kk"
+ "google-com-nocodes",
+ "bing",
+ "ddg",
+ "wikipedia-kk"
]
},
"TR": {
"visibleDefaultEngines": [
- "google-com-nocodes", "bing", "ddg", "wikipedia-kk"
+ "google-com-nocodes",
+ "bing",
+ "ddg",
+ "wikipedia-kk"
]
}
},
"km": {
"default": {
- "visibleDefaultEngines": [
- "google-b-m", "bing", "amazondotcom", "ddg", "wikipedia-km"
- ]
+ "visibleDefaultEngines": ["google-b-m", "bing", "ddg", "wikipedia-km"]
}
},
"kn": {
"default": {
"visibleDefaultEngines": [
- "google-b-m", "bing", "amazon-in", "ddg", "wikipedia-kn", "wiktionary-kn"
+ "google-b-m",
+ "bing",
+ "ddg",
+ "wikipedia-kn",
+ "wiktionary-kn"
]
}
},
"ko": {
"default": {
- "visibleDefaultEngines": [
- "google-b-m", "ddg", "daum-kr"
- ]
+ "visibleDefaultEngines": ["google-b-m", "ddg", "daum-kr"]
}
},
"lij": {
"default": {
"visibleDefaultEngines": [
- "google-b-m", "bing", "amazon-it", "ddg", "wikipedia-lij", "ebay-it"
+ "google-b-m",
+ "bing",
+ "ddg",
+ "wikipedia-lij",
+ "ebay-it"
]
}
},
"lo": {
"default": {
- "visibleDefaultEngines": [
- "google-b-m", "bing", "ddg", "wikipedia-lo"
- ]
+ "visibleDefaultEngines": ["google-b-m", "bing", "ddg", "wikipedia-lo"]
}
},
"lt": {
"default": {
- "visibleDefaultEngines": [
- "google-b-m", "bing", "ddg", "wikipedia-lt"
- ]
+ "visibleDefaultEngines": ["google-b-m", "bing", "ddg", "wikipedia-lt"]
}
},
"ltg": {
"default": {
- "visibleDefaultEngines": [
- "google-b-m", "bing", "amazon-co-uk", "wikipedia-ltg"
- ]
+ "visibleDefaultEngines": ["google-b-m", "bing", "wikipedia-ltg"]
}
},
"lv": {
"default": {
"visibleDefaultEngines": [
- "google-b-m", "ddg", "salidzinilv", "wikipedia-lv"
+ "google-b-m",
+ "ddg",
+ "salidzinilv",
+ "wikipedia-lv"
]
}
},
"mai": {
"default": {
- "visibleDefaultEngines": [
- "google-b-m", "bing", "amazon-in", "ddg", "wikipedia-hi"
- ]
+ "visibleDefaultEngines": ["google-b-m", "bing", "ddg", "wikipedia-hi"]
}
},
"meh": {
"default": {
- "visibleDefaultEngines": [
- "google-b-m", "bing", "amazondotcom", "ddg", "wikipedia-es"
- ]
+ "visibleDefaultEngines": ["google-b-m", "bing", "ddg", "wikipedia-es"]
}
},
"mix": {
"default": {
- "visibleDefaultEngines": [
- "google-b-m", "bing", "amazondotcom", "ddg", "wikipedia-es"
- ]
+ "visibleDefaultEngines": ["google-b-m", "bing", "ddg", "wikipedia-es"]
}
},
"ml": {
"default": {
- "visibleDefaultEngines": [
- "google-b-m", "bing", "ddg", "wikipedia-ml"
- ]
+ "visibleDefaultEngines": ["google-b-m", "bing", "ddg", "wikipedia-ml"]
}
},
"mr": {
"default": {
- "visibleDefaultEngines": [
- "google-b-m", "bing", "amazon-in", "ddg", "wikipedia-mr"
- ]
+ "visibleDefaultEngines": ["google-b-m", "bing", "ddg", "wikipedia-mr"]
}
},
"ms": {
"default": {
- "visibleDefaultEngines": [
- "google-b-m", "bing", "amazondotcom", "ddg", "wikipedia-ms"
- ]
+ "visibleDefaultEngines": ["google-b-m", "bing", "ddg", "wikipedia-ms"]
}
},
"my": {
"default": {
- "visibleDefaultEngines": [
- "google-b-m", "bing", "amazondotcom", "ddg", "wikipedia-my"
- ]
+ "visibleDefaultEngines": ["google-b-m", "bing", "ddg", "wikipedia-my"]
}
},
"nb-NO": {
"default": {
"visibleDefaultEngines": [
- "google-b-m", "bing", "ddg", "gulesider-mobile-NO", "wikipedia-NO"
+ "google-b-m",
+ "bing",
+ "ddg",
+ "gulesider-mobile-NO",
+ "wikipedia-NO"
]
}
},
"ne-NP": {
"default": {
- "visibleDefaultEngines": [
- "google-b-m", "bing", "ddg", "wikipedia-ne"
- ]
+ "visibleDefaultEngines": ["google-b-m", "bing", "ddg", "wikipedia-ne"]
}
},
"nl-NL": {
"default": {
"visibleDefaultEngines": [
- "google-b-m", "bing", "ddg", "wikipedia-nl", "amazon-nl", "ebay-nl"
+ "google-b-m",
+ "bing",
+ "ddg",
+ "wikipedia-nl",
+ "ebay-nl"
]
}
},
"nl": {
"default": {
"visibleDefaultEngines": [
- "google-b-m", "bing", "ddg", "ebay-nl", "wikipedia-nl"
+ "google-b-m",
+ "bing",
+ "ddg",
+ "ebay-nl",
+ "wikipedia-nl"
]
}
},
"nn-NO": {
"default": {
"visibleDefaultEngines": [
- "google-b-m", "bing", "ddg", "gulesider-mobile-NO", "wikipedia-NN"
+ "google-b-m",
+ "bing",
+ "ddg",
+ "gulesider-mobile-NO",
+ "wikipedia-NN"
]
}
},
"oc": {
"default": {
"visibleDefaultEngines": [
- "google-b-m", "bing", "ddg", "wikipedia-oc", "wiktionary-oc"
+ "google-b-m",
+ "bing",
+ "ddg",
+ "wikipedia-oc",
+ "wiktionary-oc"
]
}
},
"or": {
"default": {
"visibleDefaultEngines": [
- "google-b-m", "bing", "amazon-in", "ddg", "wikipedia-or", "wiktionary-or"
+ "google-b-m",
+ "bing",
+ "ddg",
+ "wikipedia-or",
+ "wiktionary-or"
]
}
},
"pa-IN": {
"default": {
- "visibleDefaultEngines": [
- "google-b-m", "bing", "ddg", "wikipedia-pa"
- ]
+ "visibleDefaultEngines": ["google-b-m", "bing", "ddg", "wikipedia-pa"]
}
},
"pl": {
"default": {
"visibleDefaultEngines": [
- "google-b-m", "bing", "ddg", "wikipedia-pl", "ebay-pl"
+ "google-b-m",
+ "bing",
+ "ddg",
+ "wikipedia-pl",
+ "ebay-pl"
]
}
},
"pt-BR": {
"default": {
- "visibleDefaultEngines": [
- "google-b-m", "bing", "ddg", "wikipedia-pt"
- ]
+ "visibleDefaultEngines": ["google-b-m", "bing", "ddg", "wikipedia-pt"]
}
},
"pt-PT": {
"default": {
- "visibleDefaultEngines": [
- "google-b-m", "ddg", "wikipedia-pt"
- ]
+ "visibleDefaultEngines": ["google-b-m", "ddg", "wikipedia-pt"]
}
},
"rm": {
"default": {
"visibleDefaultEngines": [
- "google-b-m", "bing", "ddg", "ebay-ch", "leo_ende_de", "wikipedia-rm"
+ "google-b-m",
+ "bing",
+ "ddg",
+ "ebay-ch",
+ "leo_ende_de",
+ "wikipedia-rm"
]
}
},
"ro": {
"default": {
- "visibleDefaultEngines": [
- "google-b-m", "bing", "ddg", "wikipedia-ro"
- ]
+ "visibleDefaultEngines": ["google-b-m", "bing", "ddg", "wikipedia-ro"]
}
},
"ru": {
"default": {
- "visibleDefaultEngines": [
- "google-b-m", "ddg", "wikipedia-ru"
- ]
+ "visibleDefaultEngines": ["google-b-m", "ddg", "wikipedia-ru"]
},
"RU": {
- "visibleDefaultEngines": [
- "google-com-nocodes", "ddg", "wikipedia-ru"
- ]
+ "visibleDefaultEngines": ["google-com-nocodes", "ddg", "wikipedia-ru"]
},
"BY": {
- "visibleDefaultEngines": [
- "google-com-nocodes", "ddg", "wikipedia-ru"
- ]
+ "visibleDefaultEngines": ["google-com-nocodes", "ddg", "wikipedia-ru"]
},
"KZ": {
- "visibleDefaultEngines": [
- "google-com-nocodes", "ddg", "wikipedia-ru"
- ]
+ "visibleDefaultEngines": ["google-com-nocodes", "ddg", "wikipedia-ru"]
},
"TR": {
- "visibleDefaultEngines": [
- "google-com-nocodes", "ddg", "wikipedia-ru"
- ]
+ "visibleDefaultEngines": ["google-com-nocodes", "ddg", "wikipedia-ru"]
}
},
"sk": {
"default": {
- "visibleDefaultEngines": [
- "google-b-m", "ddg", "wikipedia-sk"
- ]
+ "visibleDefaultEngines": ["google-b-m", "ddg", "wikipedia-sk"]
}
},
"sl": {
"default": {
"visibleDefaultEngines": [
- "google-b-m", "ddg", "ceneje", "odpiralni", "wikipedia-sl"
+ "google-b-m",
+ "ddg",
+ "ceneje",
+ "odpiralni",
+ "wikipedia-sl"
]
}
},
"son": {
"default": {
- "visibleDefaultEngines": [
- "google-b-m", "ddg", "bing", "amazon-fr", "wikipedia-fr"
- ]
+ "visibleDefaultEngines": ["google-b-m", "ddg", "bing", "wikipedia-fr"]
}
},
"sq": {
"default": {
- "visibleDefaultEngines": [
- "google-b-m", "bing", "amazon-co-uk", "ddg", "wikipedia-sq"
- ]
+ "visibleDefaultEngines": ["google-b-m", "bing", "ddg", "wikipedia-sq"]
}
},
"sr": {
"default": {
- "visibleDefaultEngines": [
- "google-b-m", "bing", "ddg", "wikipedia-sr"
- ]
+ "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"
+ "google-b-m",
+ "bing",
+ "prisjakt-sv-SE",
+ "ddg",
+ "wikipedia-sv-SE",
+ "ebay-ch"
]
}
},
"ta": {
"default": {
"visibleDefaultEngines": [
- "google-b-m", "bing", "amazon-in", "ddg", "wikipedia-ta", "wiktionary-ta"
+ "google-b-m",
+ "bing",
+ "ddg",
+ "wikipedia-ta",
+ "wiktionary-ta"
]
}
},
"te": {
"default": {
"visibleDefaultEngines": [
- "google-b-m", "bing", "amazon-in", "ddg", "wikipedia-te", "wiktionary-te"
+ "google-b-m",
+ "bing",
+ "ddg",
+ "wikipedia-te",
+ "wiktionary-te"
]
}
},
"th": {
"default": {
- "visibleDefaultEngines": [
- "google-b-m", "bing", "ddg", "wikipedia-th"
- ]
+ "visibleDefaultEngines": ["google-b-m", "bing", "ddg", "wikipedia-th"]
}
},
"tl": {
"default": {
- "visibleDefaultEngines": [
- "google-b-m", "bing", "amazondotcom", "ddg"
- ]
+ "visibleDefaultEngines": ["google-b-m", "bing", "ddg"]
}
},
"tr": {
"default": {
- "visibleDefaultEngines": [
- "google-b-m", "bing", "ddg", "wikipedia-tr"
- ]
+ "visibleDefaultEngines": ["google-b-m", "bing", "ddg", "wikipedia-tr"]
},
"TR": {
"visibleDefaultEngines": [
- "google-com-nocodes", "ddg", "bing", "wikipedia-tr"
+ "google-com-nocodes",
+ "ddg",
+ "bing",
+ "wikipedia-tr"
]
},
"BY": {
"visibleDefaultEngines": [
- "google-com-nocodes", "ddg", "bing", "wikipedia-tr"
+ "google-com-nocodes",
+ "ddg",
+ "bing",
+ "wikipedia-tr"
]
},
"KZ": {
"visibleDefaultEngines": [
- "google-com-nocodes", "ddg", "bing", "wikipedia-tr"
+ "google-com-nocodes",
+ "ddg",
+ "bing",
+ "wikipedia-tr"
]
},
"RU": {
"visibleDefaultEngines": [
- "google-com-nocodes", "ddg", "bing", "wikipedia-tr"
+ "google-com-nocodes",
+ "ddg",
+ "bing",
+ "wikipedia-tr"
]
}
},
"trs": {
"default": {
- "visibleDefaultEngines": [
- "google-b-m", "bing", "amazondotcom", "ddg", "wikipedia-es"
- ]
+ "visibleDefaultEngines": ["google-b-m", "bing", "ddg", "wikipedia-es"]
}
},
"uk": {
"default": {
- "visibleDefaultEngines": [
- "google-b-m", "bing", "ddg", "wikipedia-uk"
- ]
+ "visibleDefaultEngines": ["google-b-m", "bing", "ddg", "wikipedia-uk"]
}
},
"ur": {
"default": {
- "visibleDefaultEngines": [
- "google-b-m", "bing", "amazon-in", "ddg", "wikipedia-ur"
- ]
+ "visibleDefaultEngines": ["google-b-m", "bing", "ddg", "wikipedia-ur"]
}
},
"uz": {
"default": {
- "visibleDefaultEngines": [
- "google-b-m", "bing", "amazondotcom", "ddg", "wikipedia-uz"
- ]
+ "visibleDefaultEngines": ["google-b-m", "bing", "ddg", "wikipedia-uz"]
}
},
"vi": {
"default": {
- "visibleDefaultEngines": [
- "google-b-m", "coccoc", "ddg", "wikipedia-vi"
- ]
+ "visibleDefaultEngines": ["google-b-m", "coccoc", "ddg", "wikipedia-vi"]
}
},
"wo": {
"default": {
"visibleDefaultEngines": [
- "google-b-m", "bing", "ddg", "ebay-fr", "wikipedia-wo"
+ "google-b-m",
+ "bing",
+ "ddg",
+ "ebay-fr",
+ "wikipedia-wo"
]
}
},
"xh": {
"default": {
- "visibleDefaultEngines": [
- "google-b-m", "bing", "ddg", "wikipedia"
- ]
+ "visibleDefaultEngines": ["google-b-m", "bing", "ddg", "wikipedia"]
}
},
"zam": {
"default": {
- "visibleDefaultEngines": [
- "google-b-m", "bing", "ddg", "wikipedia-es"
- ]
+ "visibleDefaultEngines": ["google-b-m", "bing", "ddg", "wikipedia-es"]
}
},
"zh-CN": {
"default": {
"visibleDefaultEngines": [
- "google-b-m", "baidu", "bing", "ddg", "wikipedia-zh-CN"
+ "google-b-m",
+ "baidu",
+ "bing",
+ "ddg",
+ "wikipedia-zh-CN"
]
},
"CN": {
@@ -915,7 +1053,10 @@
"zh-TW": {
"default": {
"visibleDefaultEngines": [
- "google-b-m", "bing", "ddg", "wikipedia-zh-TW"
+ "google-b-m",
+ "bing",
+ "ddg",
+ "wikipedia-zh-TW"
]
}
}
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
deleted file mode 100644
index 6e8801d893..0000000000
--- a/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/amazon-au.xml
+++ /dev/null
@@ -1,12 +0,0 @@
-<!-- This Source Code Form is subject to the terms of the Mozilla Public
- - License, v. 2.0. If a copy of the MPL was not distributed with this
- - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
-
-<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
deleted file mode 100644
index 932f62b276..0000000000
--- a/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/amazon-ca.xml
+++ /dev/null
@@ -1,13 +0,0 @@
-<!-- This Source Code Form is subject to the terms of the Mozilla Public
- - License, v. 2.0. If a copy of the MPL was not distributed with this
- - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
-
-<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
deleted file mode 100644
index 5ff238cc73..0000000000
--- a/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/amazon-co-uk.xml
+++ /dev/null
@@ -1,13 +0,0 @@
-<!-- This Source Code Form is subject to the terms of the Mozilla Public
- - License, v. 2.0. If a copy of the MPL was not distributed with this
- - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
-
-<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
deleted file mode 100644
index 137abd4b94..0000000000
--- a/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/amazon-de.xml
+++ /dev/null
@@ -1,13 +0,0 @@
-<!-- This Source Code Form is subject to the terms of the Mozilla Public
- - License, v. 2.0. If a copy of the MPL was not distributed with this
- - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
-
-<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
deleted file mode 100644
index c989b9f361..0000000000
--- a/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/amazon-es.xml
+++ /dev/null
@@ -1,13 +0,0 @@
-<!-- This Source Code Form is subject to the terms of the Mozilla Public
- - License, v. 2.0. If a copy of the MPL was not distributed with this
- - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
-
-<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
deleted file mode 100644
index abfb75bee5..0000000000
--- a/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/amazon-fr.xml
+++ /dev/null
@@ -1,13 +0,0 @@
-<!-- This Source Code Form is subject to the terms of the Mozilla Public
- - License, v. 2.0. If a copy of the MPL was not distributed with this
- - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
-
-<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
deleted file mode 100644
index 2c1be1f73a..0000000000
--- a/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/amazon-in.xml
+++ /dev/null
@@ -1,13 +0,0 @@
-<!-- This Source Code Form is subject to the terms of the Mozilla Public
- - License, v. 2.0. If a copy of the MPL was not distributed with this
- - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
-
-<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
deleted file mode 100644
index 805bbf0af2..0000000000
--- a/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/amazon-it.xml
+++ /dev/null
@@ -1,13 +0,0 @@
-<!-- This Source Code Form is subject to the terms of the Mozilla Public
- - License, v. 2.0. If a copy of the MPL was not distributed with this
- - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
-
-<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-nl.xml b/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/amazon-nl.xml
deleted file mode 100644
index 75530332cc..0000000000
--- a/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/amazon-nl.xml
+++ /dev/null
@@ -1,13 +0,0 @@
-<!-- This Source Code Form is subject to the terms of the Mozilla Public
- - License, v. 2.0. If a copy of the MPL was not distributed with this
- - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
-
-<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
deleted file mode 100644
index 98f7b2d35a..0000000000
--- a/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/amazon-se.xml
+++ /dev/null
@@ -1,13 +0,0 @@
-<!-- This Source Code Form is subject to the terms of the Mozilla Public
- - License, v. 2.0. If a copy of the MPL was not distributed with this
- - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
-
-<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
deleted file mode 100644
index 2af84b936c..0000000000
--- a/mobile/android/android-components/components/feature/search/src/main/assets/searchplugins/amazondotcom.xml
+++ /dev/null
@@ -1,13 +0,0 @@
-<!-- This Source Code Form is subject to the terms of the Mozilla Public
- - License, v. 2.0. If a copy of the MPL was not distributed with this
- - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
-
-<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/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
index 9fc9f61dd5..40eec1a13c 100644
--- 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
@@ -17,10 +17,8 @@ import java.util.Locale
// be inconsistent between Kotlin versions. So to be safe we avoid this completely by
// constructing the strings manually.
-// Parameters copied from nsSearchService.js
+// Parameters copied from SearchEngine.sys.mjs on desktop.
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
@@ -66,8 +64,6 @@ private fun paramSubstitution(template: String, query: String, inputEncoding: St
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)
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
index a93a6e1700..78b4e53e51 100644
--- 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
@@ -222,14 +222,13 @@ class SearchMiddlewareTest {
assertTrue(store.state.search.additionalAvailableSearchEngines.isEmpty())
assertTrue(store.state.search.additionalSearchEngines.isEmpty())
- assertEquals(6, store.state.search.regionSearchEngines.size)
+ assertEquals(5, 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("DuckDuckGo", store.state.search.regionSearchEngines[2].name)
+ assertEquals("eBay", store.state.search.regionSearchEngines[3].name)
+ assertEquals("Wicipedia (cy)", store.state.search.regionSearchEngines[4].name)
assertEquals("Google", store.state.search.selectedOrDefaultSearchEngine!!.name)
}
@@ -299,14 +298,13 @@ class SearchMiddlewareTest {
assertTrue(store.state.search.additionalAvailableSearchEngines.isEmpty())
assertTrue(store.state.search.additionalSearchEngines.isEmpty())
- assertEquals(6, store.state.search.regionSearchEngines.size)
+ assertEquals(5, 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("DuckDuckGo", store.state.search.regionSearchEngines[2].name)
+ assertEquals("Wikipedia", store.state.search.regionSearchEngines[3].name)
+ assertEquals("eBay", store.state.search.regionSearchEngines[4].name)
assertEquals("Google", store.state.search.selectedOrDefaultSearchEngine!!.name)
}
@@ -338,15 +336,14 @@ class SearchMiddlewareTest {
assertTrue(store.state.search.additionalAvailableSearchEngines.isEmpty())
assertTrue(store.state.search.additionalSearchEngines.isEmpty())
- assertEquals(7, store.state.search.regionSearchEngines.size)
+ 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("Qwant", store.state.search.regionSearchEngines[4].name)
- assertEquals("Wikipedia", store.state.search.regionSearchEngines[5].name)
- assertEquals("eBay", store.state.search.regionSearchEngines[6].name)
+ assertEquals("DuckDuckGo", store.state.search.regionSearchEngines[2].name)
+ assertEquals("Qwant", 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)
}
@@ -378,15 +375,14 @@ class SearchMiddlewareTest {
assertTrue(store.state.search.additionalAvailableSearchEngines.isEmpty())
assertTrue(store.state.search.additionalSearchEngines.isEmpty())
- assertEquals(7, store.state.search.regionSearchEngines.size)
+ 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("Qwant", store.state.search.regionSearchEngines[4].name)
- assertEquals("Wikipedia", store.state.search.regionSearchEngines[5].name)
- assertEquals("eBay", store.state.search.regionSearchEngines[6].name)
+ assertEquals("DuckDuckGo", store.state.search.regionSearchEngines[2].name)
+ assertEquals("Qwant", 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)
}
@@ -457,14 +453,13 @@ class SearchMiddlewareTest {
assertTrue(store.state.search.additionalAvailableSearchEngines.isEmpty())
assertTrue(store.state.search.additionalSearchEngines.isEmpty())
- assertEquals(6, store.state.search.regionSearchEngines.size)
+ assertEquals(5, 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("DuckDuckGo", store.state.search.regionSearchEngines[2].name)
+ assertEquals("Wikipédia (fr)", store.state.search.regionSearchEngines[3].name)
+ assertEquals("eBay", store.state.search.regionSearchEngines[4].name)
assertEquals("Google", store.state.search.selectedOrDefaultSearchEngine!!.name)
}
@@ -496,15 +491,14 @@ class SearchMiddlewareTest {
assertTrue(store.state.search.additionalAvailableSearchEngines.isEmpty())
assertTrue(store.state.search.additionalSearchEngines.isEmpty())
- assertEquals(7, store.state.search.regionSearchEngines.size)
+ 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("Amazon.fr", store.state.search.regionSearchEngines[5].name)
- assertEquals("eBay", store.state.search.regionSearchEngines[6].name)
+ assertEquals("eBay", store.state.search.regionSearchEngines[5].name)
assertEquals("Google", store.state.search.selectedOrDefaultSearchEngine!!.name)
}
@@ -536,15 +530,15 @@ class SearchMiddlewareTest {
assertTrue(store.state.search.additionalAvailableSearchEngines.isEmpty())
assertTrue(store.state.search.additionalSearchEngines.isEmpty())
- assertEquals(8, store.state.search.regionSearchEngines.size)
+ 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.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("DuckDuckGo", store.state.search.regionSearchEngines[2].name)
+ assertEquals("Ecosia", store.state.search.regionSearchEngines[3].name)
+ assertEquals("Qwant", store.state.search.regionSearchEngines[4].name)
+ assertEquals("Wikipedia (de)", store.state.search.regionSearchEngines[5].name)
+ assertEquals("eBay", store.state.search.regionSearchEngines[6].name)
assertEquals("Google", store.state.search.selectedOrDefaultSearchEngine!!.name)
}
@@ -576,15 +570,15 @@ class SearchMiddlewareTest {
assertTrue(store.state.search.additionalAvailableSearchEngines.isEmpty())
assertTrue(store.state.search.additionalSearchEngines.isEmpty())
- assertEquals(8, store.state.search.regionSearchEngines.size)
+ 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.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("DuckDuckGo", store.state.search.regionSearchEngines[2].name)
+ assertEquals("Ecosia", store.state.search.regionSearchEngines[3].name)
+ assertEquals("Qwant", store.state.search.regionSearchEngines[4].name)
+ assertEquals("Wikipedia (de)", store.state.search.regionSearchEngines[5].name)
+ assertEquals("eBay", store.state.search.regionSearchEngines[6].name)
assertEquals("Google", store.state.search.selectedOrDefaultSearchEngine!!.name)
}
@@ -615,13 +609,14 @@ class SearchMiddlewareTest {
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(5, 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("DuckDuckGo", store.state.search.regionSearchEngines[2].name)
+ assertEquals("Wikipedija (dsb)", store.state.search.regionSearchEngines[3].name)
+ assertEquals("eBay", store.state.search.regionSearchEngines[4].name)
assertEquals("Google", store.state.search.selectedOrDefaultSearchEngine!!.name)
}
@@ -652,13 +647,14 @@ class SearchMiddlewareTest {
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(5, 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("DuckDuckGo", store.state.search.regionSearchEngines[2].name)
+ assertEquals("Wikipedija (hsb)", store.state.search.regionSearchEngines[3].name)
+ assertEquals("eBay", store.state.search.regionSearchEngines[4].name)
assertEquals("Google", store.state.search.selectedOrDefaultSearchEngine!!.name)
}
@@ -690,14 +686,13 @@ class SearchMiddlewareTest {
assertTrue(store.state.search.additionalAvailableSearchEngines.isEmpty())
assertTrue(store.state.search.additionalSearchEngines.isEmpty())
- assertEquals(6, store.state.search.regionSearchEngines.size)
+ 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 (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("eBay", store.state.search.regionSearchEngines[4].name)
assertEquals("Google", store.state.search.selectedOrDefaultSearchEngine!!.name)
}
@@ -729,14 +724,13 @@ class SearchMiddlewareTest {
assertTrue(store.state.search.additionalAvailableSearchEngines.isEmpty())
assertTrue(store.state.search.additionalSearchEngines.isEmpty())
- assertEquals(6, store.state.search.regionSearchEngines.size)
+ 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 (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("eBay", store.state.search.regionSearchEngines[4].name)
assertEquals("Google", store.state.search.selectedOrDefaultSearchEngine!!.name)
}
@@ -768,14 +762,13 @@ class SearchMiddlewareTest {
assertTrue(store.state.search.additionalAvailableSearchEngines.isEmpty())
assertTrue(store.state.search.additionalSearchEngines.isEmpty())
- assertEquals(6, store.state.search.regionSearchEngines.size)
+ assertEquals(5, 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("DuckDuckGo", store.state.search.regionSearchEngines[2].name)
+ assertEquals("Wikipedia (lij)", store.state.search.regionSearchEngines[3].name)
+ assertEquals("eBay", store.state.search.regionSearchEngines[4].name)
assertEquals("Google", store.state.search.selectedOrDefaultSearchEngine!!.name)
}
@@ -807,15 +800,14 @@ class SearchMiddlewareTest {
assertTrue(store.state.search.additionalAvailableSearchEngines.isEmpty())
assertTrue(store.state.search.additionalSearchEngines.isEmpty())
- assertEquals(7, store.state.search.regionSearchEngines.size)
+ assertEquals(6, 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("eBay", store.state.search.regionSearchEngines[5].name)
assertEquals("Google", store.state.search.selectedOrDefaultSearchEngine!!.name)
}
@@ -1718,68 +1710,6 @@ class SearchMiddlewareTest {
}
@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,
@@ -1805,14 +1735,13 @@ class SearchMiddlewareTest {
// Verify initial state
// ///////////////////////////////////////////////////////////////////////////////////////////
- assertEquals(6, store.state.search.regionSearchEngines.size)
+ assertEquals(5, 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("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)
@@ -1832,12 +1761,11 @@ class SearchMiddlewareTest {
// Verify after hiding search engines
// ///////////////////////////////////////////////////////////////////////////////////////////
- assertEquals(4, store.state.search.regionSearchEngines.size)
+ assertEquals(3, 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("eBay", store.state.search.regionSearchEngines[1].name)
+ assertEquals("Wikipedia", store.state.search.regionSearchEngines[2].name)
assertEquals("Bing", store.state.search.selectedOrDefaultSearchEngine!!.name)
@@ -1855,14 +1783,13 @@ class SearchMiddlewareTest {
// Verify state after adding search engines back
// ///////////////////////////////////////////////////////////////////////////////////////////
- assertEquals(6, store.state.search.regionSearchEngines.size)
+ assertEquals(5, 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("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)
}
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
index bfd6691432..bea87fea9c 100644
--- 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
@@ -26,7 +26,7 @@ class BundledSearchEnginesStorageTest {
val engines = storage.load(RegionState("US", "US"), Locale("en", "US"))
val searchEngines = engines.list
- assertEquals(6, searchEngines.size)
+ assertEquals(5, searchEngines.size)
}
@Test
@@ -50,7 +50,7 @@ class BundledSearchEnginesStorageTest {
val engines = storage.load(RegionState.Default, Locale("de", "DE"))
val searchEngines = engines.list
- assertEquals(8, searchEngines.size)
+ assertEquals(7, searchEngines.size)
assertContainsSearchEngine("google-b-m", searchEngines)
assertContainsNotSearchEngine("google-2018", searchEngines)
}
@@ -60,7 +60,7 @@ class BundledSearchEnginesStorageTest {
val engines = storage.load(RegionState("US", "US"), Locale("de", "DE"))
val searchEngines = engines.list
- assertEquals(8, searchEngines.size)
+ assertEquals(7, searchEngines.size)
assertContainsSearchEngine("google-b-1-m", searchEngines)
assertContainsNotSearchEngine("google", searchEngines)
}
@@ -75,7 +75,7 @@ class BundledSearchEnginesStorageTest {
val searchEngines = engines.list
println("searchEngines = $searchEngines")
- assertEquals(6, searchEngines.size)
+ assertEquals(5, searchEngines.size)
assertContainsNotSearchEngine("yandex-en", searchEngines)
}
// With region
@@ -85,7 +85,7 @@ class BundledSearchEnginesStorageTest {
val searchEngines = engines.list
println("searchEngines = $searchEngines")
- assertEquals(5, searchEngines.size)
+ assertEquals(4, searchEngines.size)
assertContainsSearchEngine("google-com-nocodes", searchEngines)
assertContainsNotSearchEngine("yandex-en", searchEngines)
}
@@ -134,11 +134,11 @@ class BundledSearchEnginesStorageTest {
val engines = storage.load(RegionState.Default, Locale("trs", ""))
val searchEngines = engines.list
- // visibleDefaultEngines: ["google-b-m", "bing", "amazondotcom", "ddg", "wikipedia-es"]
+ // visibleDefaultEngines: ["google-b-m", "bing", "ddg", "wikipedia-es"]
// searchOrder (default): ["Google", "Bing"]
assertEquals(
- listOf("google-b-m", "bing", "amazondotcom", "ddg", "wikipedia-es"),
+ listOf("google-b-m", "bing", "ddg", "wikipedia-es"),
searchEngines.map { it.id },
)
@@ -154,7 +154,7 @@ class BundledSearchEnginesStorageTest {
val engines = storage.load(RegionState.Default, Locale("xx", "XX"))
val searchEngines = engines.list
- assertEquals(5, searchEngines.size)
+ assertEquals(4, searchEngines.size)
}
private fun assertContainsSearchEngine(identifier: String, searchEngines: List<SearchEngine>) {
@@ -181,7 +181,7 @@ class BundledSearchEnginesStorageTest {
val engines = storage.load(RegionState("US", "US"), Locale("en", "US"))
val searchEngines = engines.list
- assertEquals(6, searchEngines.size)
+ assertEquals(5, searchEngines.size)
val google = searchEngines.find { it.name == "Google" }
assertNotNull(google!!)
diff --git a/mobile/android/android-components/components/feature/session/src/main/java/mozilla/components/feature/session/SessionFeature.kt b/mobile/android/android-components/components/feature/session/src/main/java/mozilla/components/feature/session/SessionFeature.kt
index 9dae8d3aac..521c5c7b64 100644
--- a/mobile/android/android-components/components/feature/session/src/main/java/mozilla/components/feature/session/SessionFeature.kt
+++ b/mobile/android/android-components/components/feature/session/src/main/java/mozilla/components/feature/session/SessionFeature.kt
@@ -17,6 +17,7 @@ import mozilla.components.support.base.feature.UserInteractionHandler
class SessionFeature(
private val store: BrowserStore,
private val goBackUseCase: SessionUseCases.GoBackUseCase,
+ private val goForwardUseCase: SessionUseCases.GoForwardUseCase,
private val engineView: EngineView,
private val tabId: String? = null,
) : LifecycleAwareFeature, UserInteractionHandler {
@@ -49,6 +50,22 @@ class SessionFeature(
}
/**
+ * Handler for forward pressed events in activities that use this feature.
+ *
+ * @return true if the event was handled, otherwise false.
+ */
+ override fun onForwardPressed(): Boolean {
+ val tab = store.state.findTabOrCustomTabOrSelectedTab(tabId)
+
+ if (tab?.content?.canGoForward == true) {
+ goForwardUseCase(tab.id)
+ return true
+ }
+
+ return false
+ }
+
+ /**
* Stop feature: App is in the background.
*/
override fun stop() {
diff --git a/mobile/android/android-components/components/feature/session/src/main/java/mozilla/components/feature/session/SessionUseCases.kt b/mobile/android/android-components/components/feature/session/src/main/java/mozilla/components/feature/session/SessionUseCases.kt
index 565ba34632..fbe5ed9d18 100644
--- a/mobile/android/android-components/components/feature/session/src/main/java/mozilla/components/feature/session/SessionUseCases.kt
+++ b/mobile/android/android-components/components/feature/session/src/main/java/mozilla/components/feature/session/SessionUseCases.kt
@@ -89,14 +89,8 @@ class SessionUseCases(
// If we already have an engine session load Url directly to prevent
// context switches.
if (engineSession != null) {
- val parentEngineSession = if (tab is TabSessionState) {
- tab.parentId?.let { store.state.findTabOrCustomTab(it)?.engineState?.engineSession }
- } else {
- null
- }
engineSession.loadUrl(
url = url,
- parent = parentEngineSession,
flags = flags,
additionalHeaders = additionalHeaders,
)
diff --git a/mobile/android/android-components/components/feature/session/src/test/java/mozilla/components/feature/session/SessionFeatureTest.kt b/mobile/android/android-components/components/feature/session/src/test/java/mozilla/components/feature/session/SessionFeatureTest.kt
index 0192f04773..8be8db17f4 100644
--- a/mobile/android/android-components/components/feature/session/src/test/java/mozilla/components/feature/session/SessionFeatureTest.kt
+++ b/mobile/android/android-components/components/feature/session/src/test/java/mozilla/components/feature/session/SessionFeatureTest.kt
@@ -54,7 +54,7 @@ class SessionFeatureTest {
val engineSession: EngineSession = mock()
store.dispatch(EngineAction.LinkEngineSessionAction("B", engineSession)).joinBlocking()
- val feature = SessionFeature(store, mock(), view)
+ val feature = SessionFeature(store, mock(), mock(), view)
verify(view, never()).render(any())
feature.start()
@@ -74,7 +74,7 @@ class SessionFeatureTest {
val engineSession: EngineSession = mock()
store.dispatch(EngineAction.LinkEngineSessionAction("C", engineSession)).joinBlocking()
- val feature = SessionFeature(store, mock(), view, tabId = "C")
+ val feature = SessionFeature(store, mock(), mock(), view, tabId = "C")
verify(view, never()).render(any())
feature.start()
@@ -95,7 +95,7 @@ class SessionFeatureTest {
val engineSession: EngineSession = mock()
store.dispatch(EngineAction.LinkEngineSessionAction("D", engineSession)).joinBlocking()
- val feature = SessionFeature(store, mock(), view, tabId = "D")
+ val feature = SessionFeature(store, mock(), mock(), view, tabId = "D")
verify(view, never()).render(any())
feature.start()
@@ -117,7 +117,7 @@ class SessionFeatureTest {
store.dispatch(EngineAction.LinkEngineSessionAction("A", engineSessionA)).joinBlocking()
store.dispatch(EngineAction.LinkEngineSessionAction("B", engineSessionB)).joinBlocking()
- val feature = SessionFeature(store, mock(), view)
+ val feature = SessionFeature(store, mock(), mock(), view)
verify(view, never()).render(any())
feature.start()
@@ -136,7 +136,7 @@ class SessionFeatureTest {
val view: EngineView = mock()
doReturn(actualView).`when`(view).asView()
- val feature = SessionFeature(store, mock(), view)
+ val feature = SessionFeature(store, mock(), mock(), view)
verify(view, never()).render(any())
feature.start()
@@ -157,7 +157,7 @@ class SessionFeatureTest {
store.dispatch(EngineAction.LinkEngineSessionAction("A", engineSessionA)).joinBlocking()
store.dispatch(EngineAction.LinkEngineSessionAction("B", engineSessionB)).joinBlocking()
- val feature = SessionFeature(store, mock(), view)
+ val feature = SessionFeature(store, mock(), mock(), view)
verify(view, never()).render(any())
feature.start()
@@ -181,7 +181,7 @@ class SessionFeatureTest {
val engineSession: EngineSession = mock()
store.dispatch(EngineAction.LinkEngineSessionAction("B", engineSession)).joinBlocking()
- val feature = SessionFeature(store, mock(), view)
+ val feature = SessionFeature(store, mock(), mock(), view)
feature.start()
@@ -205,7 +205,7 @@ class SessionFeatureTest {
val engineSession: EngineSession = mock()
store.dispatch(EngineAction.LinkEngineSessionAction("B", engineSession)).joinBlocking()
- val feature = SessionFeature(store, mock(), view)
+ val feature = SessionFeature(store, mock(), mock(), view)
verify(view, never()).render(any())
feature.start()
@@ -233,7 +233,7 @@ class SessionFeatureTest {
val engineSession: EngineSession = mock()
store.dispatch(EngineAction.LinkEngineSessionAction("D", engineSession)).joinBlocking()
- val feature = SessionFeature(store, mock(), view, tabId = "D")
+ val feature = SessionFeature(store, mock(), mock(), view, tabId = "D")
verify(view, never()).render(any())
feature.start()
@@ -253,7 +253,7 @@ class SessionFeatureTest {
val view: EngineView = mock()
doReturn(false).`when`(view).canClearSelection()
- val feature = SessionFeature(BrowserStore(), mock(), view)
+ val feature = SessionFeature(BrowserStore(), mock(), mock(), view)
assertFalse(feature.onBackPressed())
verify(view, never()).clearSelection()
@@ -263,7 +263,7 @@ class SessionFeatureTest {
val view: EngineView = mock()
doReturn(true).`when`(view).canClearSelection()
- val feature = SessionFeature(BrowserStore(), mock(), view)
+ val feature = SessionFeature(BrowserStore(), mock(), mock(), view)
assertTrue(feature.onBackPressed())
verify(view).clearSelection()
@@ -282,7 +282,7 @@ class SessionFeatureTest {
val useCase: SessionUseCases.GoBackUseCase = mock()
- val feature = SessionFeature(store, useCase, mock())
+ val feature = SessionFeature(store, useCase, mock(), mock())
assertFalse(feature.onBackPressed())
verify(useCase, never()).invoke("A")
@@ -305,7 +305,7 @@ class SessionFeatureTest {
val useCase: SessionUseCases.GoBackUseCase = mock()
- val feature = SessionFeature(store, useCase, mock())
+ val feature = SessionFeature(store, useCase, mock(), mock())
assertTrue(feature.onBackPressed())
verify(useCase).invoke("A")
@@ -313,6 +313,48 @@ class SessionFeatureTest {
}
@Test
+ fun `onForwardPressed() invokes GoForwardUseCase if forward navigation is possible`() {
+ run {
+ val store = BrowserStore(
+ BrowserState(
+ tabs = listOf(createTab("https://www.mozilla.org", id = "A")),
+ selectedTabId = "A",
+ ),
+ )
+
+ val forwardUseCase: SessionUseCases.GoForwardUseCase = mock()
+
+ val feature = SessionFeature(store, mock(), forwardUseCase, mock())
+
+ assertFalse(feature.onForwardPressed())
+ verify(forwardUseCase, never()).invoke("A")
+ }
+
+ run {
+ val store = BrowserStore(
+ BrowserState(
+ tabs = listOf(createTab("https://www.mozilla.org", id = "A")),
+ selectedTabId = "A",
+ ),
+ )
+
+ store.dispatch(
+ ContentAction.UpdateForwardNavigationStateAction(
+ "A",
+ canGoForward = true,
+ ),
+ ).joinBlocking()
+
+ val forwardUseCase: SessionUseCases.GoForwardUseCase = mock()
+
+ val feature = SessionFeature(store, mock(), forwardUseCase, mock())
+
+ assertTrue(feature.onForwardPressed())
+ verify(forwardUseCase).invoke("A")
+ }
+ }
+
+ @Test
fun `stop releases engine view`() {
val store = prepareStore()
@@ -323,7 +365,7 @@ class SessionFeatureTest {
val engineSession: EngineSession = mock()
store.dispatch(EngineAction.LinkEngineSessionAction("D", engineSession)).joinBlocking()
- val feature = SessionFeature(store, mock(), view, tabId = "D")
+ val feature = SessionFeature(store, mock(), mock(), view, tabId = "D")
verify(view, never()).render(any())
feature.start()
@@ -347,7 +389,7 @@ class SessionFeatureTest {
val engineSession: EngineSession = mock()
store.dispatch(EngineAction.LinkEngineSessionAction("A", engineSession)).joinBlocking()
- val feature = SessionFeature(store, mock(), view, tabId = "A")
+ val feature = SessionFeature(store, mock(), mock(), view, tabId = "A")
verify(view, never()).render(any())
feature.start()
@@ -368,7 +410,7 @@ class SessionFeatureTest {
val engineSession: EngineSession = mock()
store.dispatch(EngineAction.LinkEngineSessionAction("B", engineSession)).joinBlocking()
- val feature = SessionFeature(store, mock(), view)
+ val feature = SessionFeature(store, mock(), mock(), view)
verify(view, never()).render(any())
assertEquals(0L, store.state.findTab("B")?.lastAccess)
diff --git a/mobile/android/android-components/components/feature/session/src/test/java/mozilla/components/feature/session/SessionUseCasesTest.kt b/mobile/android/android-components/components/feature/session/src/test/java/mozilla/components/feature/session/SessionUseCasesTest.kt
index 4461577d25..01db35cbc8 100644
--- a/mobile/android/android-components/components/feature/session/src/test/java/mozilla/components/feature/session/SessionUseCasesTest.kt
+++ b/mobile/android/android-components/components/feature/session/src/test/java/mozilla/components/feature/session/SessionUseCasesTest.kt
@@ -132,7 +132,6 @@ class SessionUseCasesTest {
middleware.assertNotDispatched(EngineAction.LoadUrlAction::class)
verify(childEngineSession).loadUrl(
url = "https://www.mozilla.org/en-CA/firefox/browsers/mobile/",
- parent = engineSession,
)
middleware.assertLastAction(EngineAction.OptimizedLoadUrlTriggeredAction::class) { action ->
assertEquals("bugzilla", action.tabId)
diff --git a/mobile/android/android-components/components/feature/sitepermissions/src/main/res/values-ast/strings.xml b/mobile/android/android-components/components/feature/sitepermissions/src/main/res/values-ast/strings.xml
index 1a4f8a717a..deff5834db 100644
--- a/mobile/android/android-components/components/feature/sitepermissions/src/main/res/values-ast/strings.xml
+++ b/mobile/android/android-components/components/feature/sitepermissions/src/main/res/values-ast/strings.xml
@@ -9,7 +9,7 @@
<!-- Title of a dialog for a location permission request. -->
<string name="mozac_feature_sitepermissions_location_title">¿Quies permitir a «%1$s» qu\'use la to llocalización?</string>
<!-- Title of a dialog for a camera and microphone permission request. -->
- <string name="mozac_feature_sitepermissions_camera_and_microphone">¿Quies permitir a «%1$s» qu\'use la cámara ya\'l micrófonu?</string>
+ <string name="mozac_feature_sitepermissions_camera_and_microphone">¿Quies permitir a «%1$s» qu\'use la cámara y el micrófonu?</string>
<!-- Option in a dialog for requesting a microphone permission, this option will give access to
the first microphone-->
<string name="mozac_feature_sitepermissions_option_microphone_one">Micrófonu 1</string>
@@ -40,7 +40,7 @@
<string name="mozac_feature_sitepermissions_storage_access_title">¿Quies permitir a «%1$s» qu\'use les sos cookies en «%2$s»?</string>
<!-- Message of a dialog offering more context about the cross origin storage permission.
%s is the name of the site URL (www.site1.example) trying to track the user's activity. -->
- <string name="mozac_feature_sitepermissions_storage_access_message">Si nun ta claro por qué «%s» precisa estos datos, ye probable que quieras bloquiar l\'accesu.</string>
+ <string name="mozac_feature_sitepermissions_storage_access_message">Si nun tienes claro por qué «%s» precisa estos datos, pues bloquiar l\'accesu.</string>
<!-- Text for a negative button in the storage access permission request dialog. This button will not give access to this permission. -->
<string name="mozac_feature_sitepermissions_storage_access_not_allow">Bloquiar</string>
<!-- Clickable text that will open a new tab navigating the user to online documentation about specific features. -->
diff --git a/mobile/android/android-components/components/feature/tabs/src/main/java/mozilla/components/feature/tabs/TabsUseCases.kt b/mobile/android/android-components/components/feature/tabs/src/main/java/mozilla/components/feature/tabs/TabsUseCases.kt
index 6c5fe387b1..64a7cc06f8 100644
--- a/mobile/android/android-components/components/feature/tabs/src/main/java/mozilla/components/feature/tabs/TabsUseCases.kt
+++ b/mobile/android/android-components/components/feature/tabs/src/main/java/mozilla/components/feature/tabs/TabsUseCases.kt
@@ -194,6 +194,7 @@ class TabsUseCases(
url = url,
flags = flags,
additionalHeaders = additionalHeaders,
+ includeParent = true,
),
)
}
@@ -412,6 +413,7 @@ class TabsUseCases(
tab.id,
url,
flags,
+ includeParent = true,
),
)
tab.id
diff --git a/mobile/android/android-components/components/feature/webcompat-reporter/src/main/assets/extensions/webcompat-reporter/manifest.json b/mobile/android/android-components/components/feature/webcompat-reporter/src/main/assets/extensions/webcompat-reporter/manifest.json
index 53051559e4..4663f571b8 100644
--- a/mobile/android/android-components/components/feature/webcompat-reporter/src/main/assets/extensions/webcompat-reporter/manifest.json
+++ b/mobile/android/android-components/components/feature/webcompat-reporter/src/main/assets/extensions/webcompat-reporter/manifest.json
@@ -27,18 +27,11 @@
"96": "icons/lightbulb.svg",
"128": "icons/lightbulb.svg"
},
- "permissions": [
- "geckoViewAddons",
- "nativeMessaging",
- "tabs",
- "<all_urls>"
- ],
+ "permissions": ["geckoViewAddons", "nativeMessaging", "tabs", "<all_urls>"],
"background": {
"persistent": false,
"type": "module",
- "scripts": [
- "background.js"
- ]
+ "scripts": ["background.js"]
},
"page_action": {
"browser_style": true,
diff --git a/mobile/android/android-components/components/lib/auth/build.gradle b/mobile/android/android-components/components/lib/auth/build.gradle
index 26f11505ee..9f2017267a 100644
--- a/mobile/android/android-components/components/lib/auth/build.gradle
+++ b/mobile/android/android-components/components/lib/auth/build.gradle
@@ -26,6 +26,7 @@ android {
dependencies {
implementation project(':support-base')
implementation ComponentsDependencies.androidx_biometric
+ implementation ComponentsDependencies.androidx_core_ktx
testImplementation project(':support-test')
testImplementation ComponentsDependencies.androidx_test_core
diff --git a/mobile/android/android-components/components/lib/crash/build.gradle b/mobile/android/android-components/components/lib/crash/build.gradle
index afedcf3044..133c542da2 100644
--- a/mobile/android/android-components/components/lib/crash/build.gradle
+++ b/mobile/android/android-components/components/lib/crash/build.gradle
@@ -69,6 +69,7 @@ dependencies {
implementation ComponentsDependencies.androidx_appcompat
implementation ComponentsDependencies.androidx_constraintlayout
+ implementation ComponentsDependencies.androidx_core_ktx
implementation ComponentsDependencies.androidx_recyclerview
implementation project(':support-base')
diff --git a/mobile/android/android-components/components/lib/crash/src/main/res/values-ast/strings.xml b/mobile/android/android-components/components/lib/crash/src/main/res/values-ast/strings.xml
index d4d75fadfa..a6a694e9b9 100644
--- a/mobile/android/android-components/components/lib/crash/src/main/res/values-ast/strings.xml
+++ b/mobile/android/android-components/components/lib/crash/src/main/res/values-ast/strings.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- Title of the crash reporter dialog. %1$s will be replaced with the name of the app (e.g. Firefox Focus). -->
- <string name="mozac_lib_crash_dialog_title">Sentímoslo, %1$s tuvo un problema ya cascó.</string>
+ <string name="mozac_lib_crash_dialog_title">%1$s tuvo un problema y cascó.</string>
<!-- Label of the checkbox for sending crash reports in the crash reporter dialog. %1$s will be replaced with the name of the organization (e.g. Mozilla). -->
<string name="mozac_lib_crash_dialog_checkbox">Unviar l\'informe del error a %1$s</string>
@@ -16,7 +16,7 @@
<string name="mozac_lib_crash_channel">Casques</string>
<!-- Title of the crash reporter notification for background process crashes. %1$s will be replaced with the name of the app (e.g. Firefox Focus). -->
- <string name="mozac_lib_crash_background_process_notification_title">Sentímoslo, prodúxose un problema en %1$s.</string>
+ <string name="mozac_lib_crash_background_process_notification_title">Prodúxose un problema en %1$s.</string>
<!-- Label of a notification action/button that will send the crash report to Mozilla. -->
<string name="mozac_lib_crash_notification_action_report">Informar</string>
@@ -34,7 +34,7 @@
<string name="mozac_lib_crash_activity_title">Informes de casques</string>
<!-- Text shown instead of crash list if no crashes have been submitted yet -->
- <string name="mozac_lib_crash_no_crashes">Nun s\'unvió nengún informe de casques.</string>
+ <string name="mozac_lib_crash_no_crashes">Nun s\'unvió nengún informe de casque.</string>
<!-- Text link that will show an app chooser to share a crash report with a third-party app (e.g. gmail) -->
<string name="mozac_lib_crash_share">Compartir</string>
diff --git a/mobile/android/android-components/components/lib/crash/src/main/res/values-zh-rCN/strings.xml b/mobile/android/android-components/components/lib/crash/src/main/res/values-zh-rCN/strings.xml
index 9a0bf4aadb..a71a9fc917 100644
--- a/mobile/android/android-components/components/lib/crash/src/main/res/values-zh-rCN/strings.xml
+++ b/mobile/android/android-components/components/lib/crash/src/main/res/values-zh-rCN/strings.xml
@@ -37,5 +37,5 @@
<string name="mozac_lib_crash_no_crashes">尚未提交任何崩溃报告。</string>
<!-- Text link that will show an app chooser to share a crash report with a third-party app (e.g. gmail) -->
- <string name="mozac_lib_crash_share">共享</string>
+ <string name="mozac_lib_crash_share">分享</string>
</resources>
diff --git a/mobile/android/android-components/components/lib/push-firebase/build.gradle b/mobile/android/android-components/components/lib/push-firebase/build.gradle
index c8bc41debe..cd6b6acd41 100644
--- a/mobile/android/android-components/components/lib/push-firebase/build.gradle
+++ b/mobile/android/android-components/components/lib/push-firebase/build.gradle
@@ -24,6 +24,7 @@ android {
dependencies {
implementation ComponentsDependencies.kotlin_coroutines
+ implementation ComponentsDependencies.play_services_base
implementation project(':concept-push')
implementation project(':support-base')
diff --git a/mobile/android/android-components/components/lib/push-firebase/src/main/java/mozilla/components/lib/push/firebase/AbstractFirebasePushService.kt b/mobile/android/android-components/components/lib/push-firebase/src/main/java/mozilla/components/lib/push/firebase/AbstractFirebasePushService.kt
index e378f199a3..83bdd558a2 100644
--- a/mobile/android/android-components/components/lib/push-firebase/src/main/java/mozilla/components/lib/push/firebase/AbstractFirebasePushService.kt
+++ b/mobile/android/android-components/components/lib/push-firebase/src/main/java/mozilla/components/lib/push/firebase/AbstractFirebasePushService.kt
@@ -5,9 +5,9 @@
package mozilla.components.lib.push.firebase
import android.content.Context
+import androidx.annotation.VisibleForTesting
import com.google.android.gms.common.ConnectionResult
import com.google.android.gms.common.GoogleApiAvailability
-import com.google.android.gms.common.util.VisibleForTesting
import com.google.firebase.FirebaseApp
import com.google.firebase.messaging.FirebaseMessaging
import com.google.firebase.messaging.FirebaseMessagingService
diff --git a/mobile/android/android-components/components/service/firefox-accounts/src/main/java/mozilla/components/service/fxa/AccountStorage.kt b/mobile/android/android-components/components/service/firefox-accounts/src/main/java/mozilla/components/service/fxa/AccountStorage.kt
index 37af0f5b76..e5f8a665eb 100644
--- a/mobile/android/android-components/components/service/firefox-accounts/src/main/java/mozilla/components/service/fxa/AccountStorage.kt
+++ b/mobile/android/android-components/components/service/firefox-accounts/src/main/java/mozilla/components/service/fxa/AccountStorage.kt
@@ -11,7 +11,6 @@ import mozilla.appservices.fxaclient.FxaRustAuthState
import mozilla.components.concept.base.crash.CrashReporting
import mozilla.components.concept.sync.AccountEvent
import mozilla.components.concept.sync.AccountEventsObserver
-import mozilla.components.concept.sync.OAuthAccount
import mozilla.components.concept.sync.StatePersistenceCallback
import mozilla.components.lib.dataprotect.SecureAbove22Preferences
import mozilla.components.service.fxa.manager.FxaAccountManager
@@ -26,16 +25,16 @@ const val FXA_STATE_KEY = "fxaState"
* Represents state of our account on disk - is it new, or restored?
*/
internal sealed class AccountOnDisk : WithAccount {
- data class Restored(val account: OAuthAccount) : AccountOnDisk() {
+ data class Restored(val account: FirefoxAccount) : AccountOnDisk() {
override fun account() = account
}
- data class New(val account: OAuthAccount) : AccountOnDisk() {
+ data class New(val account: FirefoxAccount) : AccountOnDisk() {
override fun account() = account
}
}
internal interface WithAccount {
- fun account(): OAuthAccount
+ fun account(): FirefoxAccount
}
/**
@@ -80,16 +79,16 @@ open class StorageWrapper(
}
}
- private fun watchAccount(account: OAuthAccount) {
+ private fun watchAccount(account: FirefoxAccount) {
account.registerPersistenceCallback(statePersistenceCallback)
account.deviceConstellation().register(accountEventsIntegration)
}
/**
- * Exists strictly for testing purposes, allowing tests to specify their own implementation of [OAuthAccount].
+ * Exists strictly for testing purposes, allowing tests to specify their own implementation of [FirefoxAccount].
*/
@VisibleForTesting
- open fun obtainAccount(): OAuthAccount = FirefoxAccount(serverConfig, crashReporter)
+ open fun obtainAccount(): FirefoxAccount = FirefoxAccount(serverConfig, crashReporter)
}
/**
@@ -110,7 +109,7 @@ internal class AccountEventsIntegration(
internal interface AccountStorage {
@Throws(Exception::class)
- fun read(): OAuthAccount?
+ fun read(): FirefoxAccount?
fun write(accountState: String)
fun clear()
}
@@ -156,7 +155,7 @@ internal class SharedPrefAccountStorage(
* @throws FxaException if JSON failed to parse into a [FirefoxAccount].
*/
@Throws(FxaException::class)
- override fun read(): OAuthAccount? {
+ override fun read(): FirefoxAccount? {
val savedJSON = accountPreferences().getString(FXA_STATE_KEY, null)
?: return null
@@ -244,7 +243,7 @@ internal class SecureAbove22AccountStorage(
* @throws FxaException if JSON failed to parse into a [FirefoxAccount].
*/
@Throws(FxaException::class)
- override fun read(): OAuthAccount? {
+ override fun read(): FirefoxAccount? {
return store.getString(KEY_ACCOUNT_STATE).also {
// If account state is missing, but we expected it to be present, report an exception.
if (it == null && prefs.getBoolean(PREF_KEY_HAS_STATE, false)) {
diff --git a/mobile/android/android-components/components/service/firefox-accounts/src/main/java/mozilla/components/service/fxa/FirefoxAccount.kt b/mobile/android/android-components/components/service/firefox-accounts/src/main/java/mozilla/components/service/fxa/FirefoxAccount.kt
index 7fc31785e3..14e3e7d105 100644
--- a/mobile/android/android-components/components/service/firefox-accounts/src/main/java/mozilla/components/service/fxa/FirefoxAccount.kt
+++ b/mobile/android/android-components/components/service/firefox-accounts/src/main/java/mozilla/components/service/fxa/FirefoxAccount.kt
@@ -17,6 +17,7 @@ import mozilla.components.concept.sync.DeviceConstellation
import mozilla.components.concept.sync.FxAEntryPoint
import mozilla.components.concept.sync.OAuthAccount
import mozilla.components.concept.sync.StatePersistenceCallback
+import mozilla.components.concept.sync.UserData
import mozilla.components.support.base.log.logger.Logger
typealias PersistCallback = mozilla.appservices.fxaclient.FxaClient.PersistCallback
@@ -96,6 +97,10 @@ class FirefoxAccount internal constructor(
internal fun getAuthState() = inner.getAuthState()
+ internal fun simulateNetworkError() = inner.simulateNetworkError()
+ internal fun simulateTemporaryAuthTokenIssue() = inner.simulateTemporaryAuthTokenIssue()
+ internal fun simulatePermanentAuthTokenIssue() = inner.simulatePermanentAuthTokenIssue()
+
override suspend fun beginOAuthFlow(
scopes: Set<String>,
entryPoint: FxAEntryPoint,
@@ -128,6 +133,12 @@ class FirefoxAccount internal constructor(
}
}
+ override suspend fun setUserData(userData: UserData) {
+ handleFxaExceptions(logger, "setUserData", { null }) {
+ inner.setUserData(userData.into())
+ }
+ }
+
override fun getCurrentDeviceId(): String? {
// This is awkward, yes. Underlying method simply reads some data from in-memory state, and yet it throws
// in case that data isn't there. See https://github.com/mozilla/application-services/issues/2202.
diff --git a/mobile/android/android-components/components/service/firefox-accounts/src/main/java/mozilla/components/service/fxa/FxaDeviceConstellation.kt b/mobile/android/android-components/components/service/firefox-accounts/src/main/java/mozilla/components/service/fxa/FxaDeviceConstellation.kt
index 99c4fb196f..88e4eebd4c 100644
--- a/mobile/android/android-components/components/service/firefox-accounts/src/main/java/mozilla/components/service/fxa/FxaDeviceConstellation.kt
+++ b/mobile/android/android-components/components/service/firefox-accounts/src/main/java/mozilla/components/service/fxa/FxaDeviceConstellation.kt
@@ -191,6 +191,9 @@ class FxaDeviceConstellation(
crashReporter?.submitCaughtException(error)
}
}
+ is DeviceCommandOutgoing.CloseTab -> {
+ account.closeTabs(targetDeviceId, outgoingCommand.urls)
+ }
else -> logger.debug("Skipped sending unsupported command type: $outgoingCommand")
}
null
diff --git a/mobile/android/android-components/components/service/firefox-accounts/src/main/java/mozilla/components/service/fxa/Types.kt b/mobile/android/android-components/components/service/firefox-accounts/src/main/java/mozilla/components/service/fxa/Types.kt
index 737ff3c273..d489686cdd 100644
--- a/mobile/android/android-components/components/service/firefox-accounts/src/main/java/mozilla/components/service/fxa/Types.kt
+++ b/mobile/android/android-components/components/service/firefox-accounts/src/main/java/mozilla/components/service/fxa/Types.kt
@@ -18,6 +18,7 @@ import mozilla.components.concept.sync.DeviceCapability
import mozilla.components.concept.sync.DeviceType
import mozilla.components.concept.sync.OAuthScopedKey
import mozilla.components.concept.sync.SyncAuthInfo
+import mozilla.components.concept.sync.UserData
import mozilla.appservices.fxaclient.DeviceCapability as RustDeviceCapability
import mozilla.appservices.fxaclient.DevicePushSubscription as RustDevicePushSubscription
import mozilla.appservices.sync15.DeviceType as RustDeviceType
@@ -106,6 +107,20 @@ fun Profile.into(): mozilla.components.concept.sync.Profile {
)
}
+/**
+ * Converts the android-components defined [UserData] type into
+ * the application-services one, so consumers of android-components
+ * do not have to know about application services.
+ */
+fun UserData.into(): mozilla.appservices.fxaclient.UserData {
+ return mozilla.appservices.fxaclient.UserData(
+ sessionToken,
+ uid,
+ email,
+ verified,
+ )
+}
+
internal fun RustDeviceType.into(): DeviceType {
return when (this) {
RustDeviceType.DESKTOP -> DeviceType.DESKTOP
@@ -139,6 +154,7 @@ fun DeviceType.into(): RustDeviceType {
fun DeviceCapability.into(): RustDeviceCapability {
return when (this) {
DeviceCapability.SEND_TAB -> RustDeviceCapability.SEND_TAB
+ DeviceCapability.CLOSE_TABS -> RustDeviceCapability.CLOSE_TABS
}
}
@@ -149,6 +165,7 @@ fun DeviceCapability.into(): RustDeviceCapability {
fun RustDeviceCapability.into(): DeviceCapability {
return when (this) {
RustDeviceCapability.SEND_TAB -> DeviceCapability.SEND_TAB
+ RustDeviceCapability.CLOSE_TABS -> DeviceCapability.CLOSE_TABS
}
}
@@ -240,6 +257,7 @@ fun AccountEvent.into(): mozilla.components.concept.sync.AccountEvent {
fun IncomingDeviceCommand.into(): mozilla.components.concept.sync.DeviceCommandIncoming {
return when (this) {
is IncomingDeviceCommand.TabReceived -> this.into()
+ is IncomingDeviceCommand.TabsClosed -> this.into()
}
}
@@ -249,3 +267,10 @@ fun IncomingDeviceCommand.TabReceived.into(): mozilla.components.concept.sync.De
entries = this.payload.entries.map { it.into() },
)
}
+
+fun IncomingDeviceCommand.TabsClosed.into(): mozilla.components.concept.sync.DeviceCommandIncoming.TabsClosed {
+ return mozilla.components.concept.sync.DeviceCommandIncoming.TabsClosed(
+ from = this.sender?.into(),
+ urls = this.payload.urls,
+ )
+}
diff --git a/mobile/android/android-components/components/service/firefox-accounts/src/main/java/mozilla/components/service/fxa/manager/FxaAccountManager.kt b/mobile/android/android-components/components/service/firefox-accounts/src/main/java/mozilla/components/service/fxa/manager/FxaAccountManager.kt
index 03a7d25635..71232c0815 100644
--- a/mobile/android/android-components/components/service/firefox-accounts/src/main/java/mozilla/components/service/fxa/manager/FxaAccountManager.kt
+++ b/mobile/android/android-components/components/service/firefox-accounts/src/main/java/mozilla/components/service/fxa/manager/FxaAccountManager.kt
@@ -8,9 +8,11 @@ import android.content.Context
import androidx.annotation.GuardedBy
import androidx.annotation.VisibleForTesting
import androidx.lifecycle.LifecycleOwner
+import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.SupervisorJob
import kotlinx.coroutines.asCoroutineDispatcher
import kotlinx.coroutines.cancel
+import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import mozilla.appservices.fxaclient.FxaStateCheckerEvent
import mozilla.appservices.fxaclient.FxaStateCheckerState
@@ -26,6 +28,7 @@ import mozilla.components.concept.sync.FxAEntryPoint
import mozilla.components.concept.sync.OAuthAccount
import mozilla.components.concept.sync.Profile
import mozilla.components.concept.sync.ServiceResult
+import mozilla.components.concept.sync.UserData
import mozilla.components.service.fxa.AccessTokenUnexpectedlyWithoutKey
import mozilla.components.service.fxa.AccountManagerException
import mozilla.components.service.fxa.AccountOnDisk
@@ -344,11 +347,14 @@ open class FxaAccountManager(
* @param pairingUrl Optional pairing URL in case a pairing flow is being initiated.
* @param entrypoint an enum representing the feature entrypoint requesting the URL.
* the entrypoint is used in telemetry.
+ * @param authScopes The oAuth scopes being requested, if none are provided
+ * we default to the scopes provided when constructing [FxaAccountManager]
* @return An authentication url which is to be presented to the user.
*/
suspend fun beginAuthentication(
pairingUrl: String? = null,
entrypoint: FxAEntryPoint,
+ authScopes: Set<String> = scopes,
): String? = withContext(coroutineContext) {
// It's possible that at this point authentication is considered to be "in-progress".
// For example, if user started authentication flow, but cancelled it (closing a custom tab)
@@ -357,9 +363,9 @@ open class FxaAccountManager(
processQueue(Event.Progress.CancelAuth)
val event = if (pairingUrl != null) {
- Event.Account.BeginPairingFlow(pairingUrl, entrypoint)
+ Event.Account.BeginPairingFlow(pairingUrl, entrypoint, authScopes)
} else {
- Event.Account.BeginEmailFlow(entrypoint)
+ Event.Account.BeginEmailFlow(entrypoint, authScopes)
}
// Process the event, then use the new state to check the result of the operation
@@ -375,6 +381,16 @@ open class FxaAccountManager(
}
/**
+ * Sets the user's data received from the web content.
+ * **NOTE**: This is only useful for applications that are user agents, that
+ * require the user's session token, and thus isn't a part of the state machine
+ * @param userData: The user's data as given by the web channel, including the session token
+ */
+ suspend fun setUserData(userData: UserData) = withContext(coroutineContext) {
+ account.setUserData(userData)
+ }
+
+ /**
* Finalize authentication that was started via [beginAuthentication].
*
* If authentication wasn't started via this manager we won't accept this authentication attempt,
@@ -590,10 +606,10 @@ open class FxaAccountManager(
} else {
null
}
- val entrypoint = if (via is Event.Account.BeginEmailFlow) {
- via.entrypoint
+ val (entrypoint, authScopes) = if (via is Event.Account.BeginEmailFlow) {
+ Pair(via.entrypoint, via.scopes)
} else if (via is Event.Account.BeginPairingFlow) {
- via.entrypoint
+ Pair(via.entrypoint, via.scopes)
} else {
// This should be impossible, both `BeginPairingFlow` and `BeginEmailFlow`
// have a required `entrypoint` and we are matching against only instances
@@ -601,7 +617,7 @@ open class FxaAccountManager(
throw IllegalStateException("BeginningAuthentication with a flow that is neither email nor pairing")
}
val result = withRetries(logger, MAX_NETWORK_RETRIES) {
- pairingUrl.asAuthFlowUrl(account, scopes, entrypoint = entrypoint)
+ pairingUrl.asAuthFlowUrl(account, authScopes, entrypoint = entrypoint)
}
when (result) {
is Result.Success -> {
@@ -935,4 +951,60 @@ open class FxaAccountManager(
accountManager.syncStatusObserverRegistry.notifyObservers { onError(error) }
}
}
+
+ /**
+ * Hook this up to the secret debug menu to simulate a network error
+ *
+ * Typical usage is:
+ * - `adb logcat | grep fxa_client`
+ * - Trigger this via the secret debug menu item.
+ * - Watch the logs. You should see the client perform a call to `get_profile', see a
+ * network error, then recover.
+ * - Note: the logs will be more clear once we switch the code to using the app-services state
+ * machine.
+ * - Check the UI, it should be in an authenticated state.
+ */
+ public fun simulateNetworkError() {
+ account.simulateNetworkError()
+ CoroutineScope(coroutineContext).launch {
+ refreshProfile(true)
+ }
+ }
+
+ /**
+ * Hook this up to the secret debug menu to simulate a temporary auth error
+ *
+ * Typical usage is:
+ * - `adb logcat | grep fxa_client`
+ * - Trigger this via the secret debug menu item.
+ * - Watch the logs. You should see the client perform a call to `get_profile', see an
+ * auth error, then recover.
+ * - Check the UI, it should be in an authenticated state.
+ */
+ public fun simulateTemporaryAuthTokenIssue() {
+ account.simulateTemporaryAuthTokenIssue()
+ SyncAuthInfoCache(context).clear()
+ CoroutineScope(coroutineContext).launch {
+ refreshProfile(true)
+ }
+ }
+
+ /**
+ * Hook this up to the secret debug menu to simulate an unrecoverable auth error
+ *
+ * Typical usage is:
+ * - `adb logcat | grep fxa_client`
+ * - Trigger this via the secret debug menu item.
+ * - Initiaite a sync, or perform some other action that requires authentication.
+ * - Watch the logs. You should see the client perform a call to `get_profile', see an
+ * auth error, then fail to recover.
+ * - Check the UI, it should be in an authentication problems state.
+ */
+ public fun simulatePermanentAuthTokenIssue() {
+ account.simulatePermanentAuthTokenIssue()
+ SyncAuthInfoCache(context).clear()
+ CoroutineScope(coroutineContext).launch {
+ refreshProfile(true)
+ }
+ }
}
diff --git a/mobile/android/android-components/components/service/firefox-accounts/src/main/java/mozilla/components/service/fxa/manager/State.kt b/mobile/android/android-components/components/service/firefox-accounts/src/main/java/mozilla/components/service/fxa/manager/State.kt
index 111715703a..50858c2bbe 100644
--- a/mobile/android/android-components/components/service/firefox-accounts/src/main/java/mozilla/components/service/fxa/manager/State.kt
+++ b/mobile/android/android-components/components/service/firefox-accounts/src/main/java/mozilla/components/service/fxa/manager/State.kt
@@ -52,10 +52,31 @@ import mozilla.components.service.fxa.FxaAuthData
* State transitions are described by a transition matrix, which is described in [State.next].
*/
-internal sealed class AccountState {
+/**
+ * Represents a [State.Idle] in the accounts state machine detailing the state of the account
+ * lifecycle.
+ */
+sealed class AccountState {
+ /**
+ * Account is logged in and authenticated.
+ */
object Authenticated : AccountState()
+
+ /**
+ * Account is authenticating.
+ *
+ * @property oAuthUrl OAuth URL to be loaded to go through the authentication flow.
+ */
data class Authenticating(val oAuthUrl: String) : AccountState()
+
+ /**
+ * Account needs to be re-authenticated (e.g. due to a password change).
+ */
object AuthenticationProblem : AccountState()
+
+ /**
+ * No authenticated account is available (e.g. account is logged out).
+ */
object NotAuthenticated : AccountState()
}
@@ -70,8 +91,12 @@ internal enum class ProgressState {
internal sealed class Event {
internal sealed class Account : Event() {
internal object Start : Account()
- data class BeginEmailFlow(val entrypoint: FxAEntryPoint) : Account()
- data class BeginPairingFlow(val pairingUrl: String?, val entrypoint: FxAEntryPoint) : Account()
+ data class BeginEmailFlow(val entrypoint: FxAEntryPoint, val scopes: Set<String>) : Account()
+ data class BeginPairingFlow(
+ val pairingUrl: String?,
+ val entrypoint: FxAEntryPoint,
+ val scopes: Set<String>,
+ ) : Account()
data class AuthenticationError(val operation: String, val errorCountWithinTheTimeWindow: Int = 1) : Account() {
override fun toString(): String {
return "${this.javaClass.simpleName} - $operation"
diff --git a/mobile/android/android-components/components/service/firefox-accounts/src/main/java/mozilla/components/service/fxa/store/SyncAction.kt b/mobile/android/android-components/components/service/firefox-accounts/src/main/java/mozilla/components/service/fxa/store/SyncAction.kt
index b09e7f3dcc..eb2d7960cf 100644
--- a/mobile/android/android-components/components/service/firefox-accounts/src/main/java/mozilla/components/service/fxa/store/SyncAction.kt
+++ b/mobile/android/android-components/components/service/firefox-accounts/src/main/java/mozilla/components/service/fxa/store/SyncAction.kt
@@ -6,6 +6,7 @@ package mozilla.components.service.fxa.store
import mozilla.components.concept.sync.ConstellationState
import mozilla.components.lib.state.Action
+import mozilla.components.service.fxa.manager.AccountState
/**
* Actions for updating the global [SyncState] via [SyncStore].
@@ -22,6 +23,11 @@ sealed class SyncAction : Action {
data class UpdateAccount(val account: Account?) : SyncAction()
/**
+ * Update the [SyncState.accountState] of the [SyncStore].
+ */
+ data class UpdateAccountState(val accountState: AccountState) : SyncAction()
+
+ /**
* Update the [SyncState.constellationState] of the [SyncStore].
*/
data class UpdateDeviceConstellation(val deviceConstellation: ConstellationState) : SyncAction()
diff --git a/mobile/android/android-components/components/service/firefox-accounts/src/main/java/mozilla/components/service/fxa/store/SyncState.kt b/mobile/android/android-components/components/service/firefox-accounts/src/main/java/mozilla/components/service/fxa/store/SyncState.kt
index 86c9d05d2a..91e3870251 100644
--- a/mobile/android/android-components/components/service/firefox-accounts/src/main/java/mozilla/components/service/fxa/store/SyncState.kt
+++ b/mobile/android/android-components/components/service/firefox-accounts/src/main/java/mozilla/components/service/fxa/store/SyncState.kt
@@ -9,18 +9,21 @@ import mozilla.components.concept.sync.ConstellationState
import mozilla.components.concept.sync.OAuthAccount
import mozilla.components.concept.sync.Profile
import mozilla.components.lib.state.State
+import mozilla.components.service.fxa.manager.AccountState
import mozilla.components.service.fxa.sync.WorkManagerSyncManager
/**
* Global state of Sync.
*
* @property status The current status of Sync.
- * @property account The current Sync account, if any.
+ * @property account The current Sync [Account], if any.
+ * @property accountState The current [AccountState] of Sync.
* @property constellationState The current constellation state, if any.
*/
data class SyncState(
val status: SyncStatus = SyncStatus.NotInitialized,
val account: Account? = null,
+ val accountState: AccountState = AccountState.NotAuthenticated,
val constellationState: ConstellationState? = null,
) : State
diff --git a/mobile/android/android-components/components/service/firefox-accounts/src/main/java/mozilla/components/service/fxa/store/SyncStore.kt b/mobile/android/android-components/components/service/firefox-accounts/src/main/java/mozilla/components/service/fxa/store/SyncStore.kt
index 50f4b6747e..487d9bd1ea 100644
--- a/mobile/android/android-components/components/service/firefox-accounts/src/main/java/mozilla/components/service/fxa/store/SyncStore.kt
+++ b/mobile/android/android-components/components/service/firefox-accounts/src/main/java/mozilla/components/service/fxa/store/SyncStore.kt
@@ -22,6 +22,7 @@ private fun reduce(syncState: SyncState, syncAction: SyncAction): SyncState {
return when (syncAction) {
is SyncAction.UpdateSyncStatus -> syncState.copy(status = syncAction.status)
is SyncAction.UpdateAccount -> syncState.copy(account = syncAction.account)
+ is SyncAction.UpdateAccountState -> syncState.copy(accountState = syncAction.accountState)
is SyncAction.UpdateDeviceConstellation ->
syncState.copy(constellationState = syncAction.deviceConstellation)
}
diff --git a/mobile/android/android-components/components/service/firefox-accounts/src/main/java/mozilla/components/service/fxa/store/SyncStoreSupport.kt b/mobile/android/android-components/components/service/firefox-accounts/src/main/java/mozilla/components/service/fxa/store/SyncStoreSupport.kt
index 4feda96e60..7674d8a8fc 100644
--- a/mobile/android/android-components/components/service/firefox-accounts/src/main/java/mozilla/components/service/fxa/store/SyncStoreSupport.kt
+++ b/mobile/android/android-components/components/service/firefox-accounts/src/main/java/mozilla/components/service/fxa/store/SyncStoreSupport.kt
@@ -10,12 +10,15 @@ import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import mozilla.components.concept.sync.AccountObserver
+import mozilla.components.concept.sync.AuthFlowError
import mozilla.components.concept.sync.AuthType
import mozilla.components.concept.sync.ConstellationState
import mozilla.components.concept.sync.DeviceConstellationObserver
import mozilla.components.concept.sync.OAuthAccount
import mozilla.components.concept.sync.Profile
+import mozilla.components.service.fxa.manager.AccountState
import mozilla.components.service.fxa.manager.FxaAccountManager
+import mozilla.components.service.fxa.manager.SCOPE_PROFILE
import mozilla.components.service.fxa.sync.SyncStatusObserver
import java.lang.Exception
@@ -95,6 +98,24 @@ internal class FxaAccountObserver(
private val autoPause: Boolean,
private val coroutineScope: CoroutineScope,
) : AccountObserver {
+ override fun onReady(authenticatedAccount: OAuthAccount?) {
+ coroutineScope.launch {
+ if (authenticatedAccount == null) {
+ return@launch
+ }
+
+ val syncAccount =
+ authenticatedAccount.getProfile()?.toAccount(authenticatedAccount) ?: return@launch
+ store.dispatch(SyncAction.UpdateAccount(account = syncAccount))
+
+ val accountState = when (authenticatedAccount.checkAuthorizationStatus(SCOPE_PROFILE)) {
+ true -> AccountState.Authenticated
+ null, false -> AccountState.AuthenticationProblem
+ }
+ store.dispatch(SyncAction.UpdateAccountState(accountState = accountState))
+ }
+ }
+
override fun onAuthenticated(account: OAuthAccount, authType: AuthType) {
coroutineScope.launch(Dispatchers.Main) {
account.deviceConstellation().registerDeviceObserver(
@@ -106,12 +127,23 @@ internal class FxaAccountObserver(
coroutineScope.launch {
val syncAccount = account.getProfile()?.toAccount(account) ?: return@launch
store.dispatch(SyncAction.UpdateAccount(syncAccount))
+ store.dispatch(SyncAction.UpdateAccountState(AccountState.Authenticated))
}
}
+ override fun onAuthenticationProblems() {
+ store.dispatch(SyncAction.UpdateAccountState(accountState = AccountState.AuthenticationProblem))
+ }
+
override fun onLoggedOut() {
store.dispatch(SyncAction.UpdateSyncStatus(SyncStatus.LoggedOut))
store.dispatch(SyncAction.UpdateAccount(null))
+ store.dispatch(SyncAction.UpdateAccountState(accountState = AccountState.NotAuthenticated))
+ }
+
+ override fun onFlowError(error: AuthFlowError) {
+ store.dispatch(SyncAction.UpdateAccount(account = null))
+ store.dispatch(SyncAction.UpdateAccountState(accountState = AccountState.NotAuthenticated))
}
}
diff --git a/mobile/android/android-components/components/service/firefox-accounts/src/test/java/mozilla/components/service/fxa/FxaAccountManagerTest.kt b/mobile/android/android-components/components/service/firefox-accounts/src/test/java/mozilla/components/service/fxa/FxaAccountManagerTest.kt
index afc2fc3ee9..3c6a3421f2 100644
--- a/mobile/android/android-components/components/service/firefox-accounts/src/test/java/mozilla/components/service/fxa/FxaAccountManagerTest.kt
+++ b/mobile/android/android-components/components/service/firefox-accounts/src/test/java/mozilla/components/service/fxa/FxaAccountManagerTest.kt
@@ -74,13 +74,13 @@ internal class TestableStorageWrapper(
manager: FxaAccountManager,
accountEventObserverRegistry: ObserverRegistry<AccountEventsObserver>,
serverConfig: FxaConfig,
- private val block: () -> OAuthAccount = {
- val account: OAuthAccount = mock()
+ private val block: () -> FirefoxAccount = {
+ val account: FirefoxAccount = mock()
`when`(account.deviceConstellation()).thenReturn(mock())
account
},
) : StorageWrapper(manager, accountEventObserverRegistry, serverConfig) {
- override fun obtainAccount(): OAuthAccount = block()
+ override fun obtainAccount(): FirefoxAccount = block()
}
// Same as the actual account manager, except we get to control how FirefoxAccountShaped instances
@@ -95,8 +95,8 @@ internal open class TestableFxaAccountManager(
syncConfig: SyncConfig? = null,
coroutineContext: CoroutineContext,
crashReporter: CrashReporting? = null,
- block: () -> OAuthAccount = {
- val account: OAuthAccount = mock()
+ block: () -> FirefoxAccount = {
+ val account: FirefoxAccount = mock()
`when`(account.deviceConstellation()).thenReturn(mock())
account
},
@@ -201,7 +201,7 @@ class FxaAccountManagerTest {
val accountStorage: AccountStorage = mock()
val profile = Profile("testUid", "test@example.com", null, "Test Profile")
val constellation: DeviceConstellation = mockDeviceConstellation()
- val account = StatePersistenceTestableAccount(profile, constellation)
+ val account = statePersistenceTestableAccount(profile, constellation)
val manager = TestableFxaAccountManager(
testContext,
@@ -218,17 +218,18 @@ class FxaAccountManagerTest {
// We have an account at the start.
`when`(accountStorage.read()).thenReturn(account)
- assertNull(account.persistenceCallback)
+ verify(account, never()).registerPersistenceCallback(any())
manager.start()
// Assert that persistence callback is set.
- assertNotNull(account.persistenceCallback)
+ val captor = argumentCaptor<StatePersistenceCallback>()
+ verify(account).registerPersistenceCallback(captor.capture())
// Assert that ensureCapabilities fired, but not the device initialization (since we're restoring).
verify(constellation).finalizeDevice(eq(AuthType.Existing), any())
// Assert that persistence callback is interacting with the storage layer.
- account.persistenceCallback!!.persist("test")
+ captor.value.persist("test")
verify(accountStorage).write("test")
}
@@ -237,7 +238,7 @@ class FxaAccountManagerTest {
val accountStorage: AccountStorage = mock()
val profile = Profile("testUid", "test@example.com", null, "Test Profile")
val constellation: DeviceConstellation = mockDeviceConstellation()
- val account = StatePersistenceTestableAccount(profile, constellation)
+ val account = statePersistenceTestableAccount(profile, constellation)
val manager = TestableFxaAccountManager(
testContext,
@@ -254,17 +255,18 @@ class FxaAccountManagerTest {
// We have an account at the start.
`when`(accountStorage.read()).thenReturn(account)
- assertNull(account.persistenceCallback)
+ verify(account, never()).registerPersistenceCallback(any())
manager.start()
// Assert that persistence callback is set.
- assertNotNull(account.persistenceCallback)
+ val captor = argumentCaptor<StatePersistenceCallback>()
+ verify(account).registerPersistenceCallback(captor.capture())
// Assert that finalizeDevice fired with a correct auth type. 3 times since we re-try.
verify(constellation, times(3)).finalizeDevice(eq(AuthType.Existing), any())
// Assert that persistence callback is interacting with the storage layer.
- account.persistenceCallback!!.persist("test")
+ captor.value.persist("test")
verify(accountStorage).write("test")
// Since we weren't able to finalize the account state, we're no longer authenticated.
@@ -276,7 +278,7 @@ class FxaAccountManagerTest {
val accountStorage: AccountStorage = mock()
val profile = Profile("testUid", "test@example.com", null, "Test Profile")
val constellation: DeviceConstellation = mockDeviceConstellation()
- val account = StatePersistenceTestableAccount(profile, constellation, ableToRecoverFromAuthError = false)
+ val account = statePersistenceTestableAccount(profile, constellation, ableToRecoverFromAuthError = false)
val accountObserver: AccountObserver = mock()
val manager = TestableFxaAccountManager(
@@ -295,19 +297,19 @@ class FxaAccountManagerTest {
// We have an account at the start.
`when`(accountStorage.read()).thenReturn(account)
- assertNull(account.persistenceCallback)
+ verify(account, never()).registerPersistenceCallback(any())
assertFalse(manager.accountNeedsReauth())
- assertFalse(account.authErrorDetectedCalled)
- assertFalse(account.checkAuthorizationStatusCalled)
+ verify(account, never()).authErrorDetected()
+ verify(account, never()).checkAuthorizationStatus(any())
verify(accountObserver, never()).onAuthenticationProblems()
manager.start()
assertTrue(manager.accountNeedsReauth())
verify(accountObserver, times(1)).onAuthenticationProblems()
- assertTrue(account.authErrorDetectedCalled)
- assertTrue(account.checkAuthorizationStatusCalled)
+ verify(account).authErrorDetected()
+ verify(account).checkAuthorizationStatus(any())
}
@Test(expected = FxaPanicException::class)
@@ -315,7 +317,7 @@ class FxaAccountManagerTest {
val accountStorage: AccountStorage = mock()
val profile = Profile("testUid", "test@example.com", null, "Test Profile")
val constellation: DeviceConstellation = mock()
- val account = StatePersistenceTestableAccount(profile, constellation)
+ val account = statePersistenceTestableAccount(profile, constellation)
val accountObserver: AccountObserver = mock()
val manager = TestableFxaAccountManager(
@@ -339,7 +341,7 @@ class FxaAccountManagerTest {
// We have an account at the start.
`when`(accountStorage.read()).thenReturn(account)
- assertNull(account.persistenceCallback)
+ verify(account, never()).registerPersistenceCallback(any())
assertFalse(manager.accountNeedsReauth())
verify(accountObserver, never()).onAuthenticationProblems()
@@ -352,7 +354,7 @@ class FxaAccountManagerTest {
val accountStorage: AccountStorage = mock()
val profile = Profile(uid = "testUID", avatar = null, email = "test@example.com", displayName = "test profile")
val constellation: DeviceConstellation = mockDeviceConstellation()
- val account = StatePersistenceTestableAccount(profile, constellation)
+ val account = statePersistenceTestableAccount(profile, constellation)
val accountObserver: AccountObserver = mock()
// We are not using the "prepareHappy..." helper method here, because our account isn't a mock,
// but an actual implementation of the interface.
@@ -388,7 +390,9 @@ class FxaAccountManagerTest {
verify(constellation).finalizeDevice(eq(AuthType.Signin), any())
// Assert that persistence callback is interacting with the storage layer.
- account.persistenceCallback!!.persist("test")
+ val captor = argumentCaptor<StatePersistenceCallback>()
+ verify(account).registerPersistenceCallback(captor.capture())
+ captor.value.persist("test")
verify(accountStorage).write("test")
}
@@ -397,7 +401,7 @@ class FxaAccountManagerTest {
val accountStorage: AccountStorage = mock()
val profile = Profile(uid = "testUID", avatar = null, email = "test@example.com", displayName = "test profile")
val constellation: DeviceConstellation = mockDeviceConstellation()
- val account = StatePersistenceTestableAccount(profile, constellation)
+ val account = statePersistenceTestableAccount(profile, constellation)
val accountObserver: AccountObserver = mock()
// We are not using the "prepareHappy..." helper method here, because our account isn't a mock,
// but an actual implementation of the interface.
@@ -423,7 +427,7 @@ class FxaAccountManagerTest {
manager.finishAuthentication(FxaAuthData(AuthType.Signin, "dummyCode", UNEXPECTED_AUTH_STATE))
assertTrue(manager.authenticatedAccount() == null)
- // Start authentication. StatePersistenceTestableAccount will produce state=EXPECTED_AUTH_STATE.
+ // Start authentication. statePersistenceTestableAccount will produce state=EXPECTED_AUTH_STATE.
assertEquals(testAuthFlowUrl(entrypoint = "home-menu").url, manager.beginAuthentication(entrypoint = entryPoint))
// Now attempt to finish it with a correct state.
@@ -435,97 +439,17 @@ class FxaAccountManagerTest {
assertEquals(account, manager.authenticatedAccount())
}
- class StatePersistenceTestableAccount(
- private val profile: Profile,
- private val constellation: DeviceConstellation,
- val ableToRecoverFromAuthError: Boolean = false,
- val tokenServerEndpointUrl: String? = null,
- val accessToken: (() -> AccessTokenInfo)? = null,
- ) : OAuthAccount {
-
- var persistenceCallback: StatePersistenceCallback? = null
- var checkAuthorizationStatusCalled = false
- var authErrorDetectedCalled = false
-
- override suspend fun beginOAuthFlow(scopes: Set<String>, entryPoint: FxAEntryPoint): AuthFlowUrl? {
- return AuthFlowUrl(EXPECTED_AUTH_STATE, testAuthFlowUrl(entrypoint = entryPoint.entryName).url)
- }
-
- override suspend fun beginPairingFlow(pairingUrl: String, scopes: Set<String>, entryPoint: FxAEntryPoint): AuthFlowUrl? {
- return AuthFlowUrl(EXPECTED_AUTH_STATE, testAuthFlowUrl(entrypoint = entryPoint.entryName).url)
- }
-
- override suspend fun getProfile(ignoreCache: Boolean): Profile? {
- return profile
- }
-
- override fun getCurrentDeviceId(): String? {
- return "testFxaDeviceId"
- }
-
- override fun getSessionToken(): String? {
- return null
- }
-
- override suspend fun completeOAuthFlow(code: String, state: String): Boolean {
- return true
- }
-
- override suspend fun getAccessToken(singleScope: String): AccessTokenInfo? {
- val token = accessToken?.invoke()
- if (token != null) return token
-
- fail()
- return null
- }
-
- override fun authErrorDetected() {
- authErrorDetectedCalled = true
- }
-
- override suspend fun checkAuthorizationStatus(singleScope: String): Boolean? {
- checkAuthorizationStatusCalled = true
- return ableToRecoverFromAuthError
- }
-
- override suspend fun getTokenServerEndpointURL(): String? {
- if (tokenServerEndpointUrl != null) return tokenServerEndpointUrl
-
- fail()
- return ""
- }
-
- override suspend fun getManageAccountURL(entryPoint: FxAEntryPoint): String? {
- return "https://firefox.com/settings"
- }
-
- override fun getPairingAuthorityURL(): String {
- return "https://firefox.com/pair"
- }
-
- override fun registerPersistenceCallback(callback: StatePersistenceCallback) {
- persistenceCallback = callback
- }
-
- override fun deviceConstellation(): DeviceConstellation {
- return constellation
- }
-
- override suspend fun disconnect(): Boolean {
- return true
- }
-
- override fun toJSONString(): String {
- fail()
- return ""
- }
-
- override fun close() {
- // Only expect 'close' to be called if we can't recover from an auth error.
- if (ableToRecoverFromAuthError) {
- fail()
- }
- }
+ suspend fun statePersistenceTestableAccount(profile: Profile, constellation: DeviceConstellation, ableToRecoverFromAuthError: Boolean = false): FirefoxAccount {
+ val account = mock<FirefoxAccount>()
+ `when`(account.getProfile(anyBoolean())).thenReturn(profile)
+ `when`(account.deviceConstellation()).thenReturn(constellation)
+ `when`(account.checkAuthorizationStatus(any())).thenReturn(ableToRecoverFromAuthError)
+ `when`(account.beginOAuthFlow(any(), any())).thenReturn(testAuthFlowUrl(entrypoint = "home-menu"))
+ `when`(account.beginPairingFlow(any(), any(), any())).thenReturn(testAuthFlowUrl(entrypoint = "home-menu"))
+ `when`(account.completeOAuthFlow(anyString(), anyString())).thenReturn(true)
+ `when`(account.getCurrentDeviceId()).thenReturn("testFxaDeviceId")
+
+ return account
}
@Test
@@ -596,7 +520,7 @@ class FxaAccountManagerTest {
@Test
fun `with persisted account and profile`() = runTest {
val accountStorage = mock<AccountStorage>()
- val mockAccount: OAuthAccount = mock()
+ val mockAccount: FirefoxAccount = mock()
val constellation: DeviceConstellation = mock()
val profile = Profile(
"testUid",
@@ -667,7 +591,7 @@ class FxaAccountManagerTest {
@Test
fun `happy authentication and profile flow`() = runTest {
- val mockAccount: OAuthAccount = mock()
+ val mockAccount: FirefoxAccount = mock()
val constellation: DeviceConstellation = mock()
`when`(mockAccount.deviceConstellation()).thenReturn(constellation)
val profile = Profile(uid = "testUID", avatar = null, email = "test@example.com", displayName = "test profile")
@@ -712,7 +636,7 @@ class FxaAccountManagerTest {
@Test(expected = FxaPanicException::class)
fun `fxa panic during initDevice flow`() = runTest {
- val mockAccount: OAuthAccount = mock()
+ val mockAccount: FirefoxAccount = mock()
val constellation: DeviceConstellation = mock()
`when`(mockAccount.deviceConstellation()).thenReturn(constellation)
val profile = Profile(uid = "testUID", avatar = null, email = "test@example.com", displayName = "test profile")
@@ -740,7 +664,7 @@ class FxaAccountManagerTest {
@Test(expected = FxaPanicException::class)
fun `fxa panic during pairing flow`() = runTest {
- val mockAccount: OAuthAccount = mock()
+ val mockAccount: FirefoxAccount = mock()
`when`(mockAccount.deviceConstellation()).thenReturn(mock())
val profile = Profile(uid = "testUID", avatar = null, email = "test@example.com", displayName = "test profile")
val accountStorage = mock<AccountStorage>()
@@ -769,7 +693,7 @@ class FxaAccountManagerTest {
@Test
fun `happy pairing authentication and profile flow`() = runTest {
- val mockAccount: OAuthAccount = mock()
+ val mockAccount: FirefoxAccount = mock()
val constellation: DeviceConstellation = mock()
`when`(mockAccount.deviceConstellation()).thenReturn(constellation)
val profile = Profile(uid = "testUID", avatar = null, email = "test@example.com", displayName = "test profile")
@@ -806,7 +730,7 @@ class FxaAccountManagerTest {
@Test
fun `repeated unfinished authentication attempts succeed`() = runTest {
- val mockAccount: OAuthAccount = mock()
+ val mockAccount: FirefoxAccount = mock()
val constellation: DeviceConstellation = mock()
`when`(mockAccount.deviceConstellation()).thenReturn(constellation)
val profile = Profile(uid = "testUID", avatar = null, email = "test@example.com", displayName = "test profile")
@@ -863,7 +787,7 @@ class FxaAccountManagerTest {
@Test
fun `unhappy authentication flow`() = runTest {
val accountStorage = mock<AccountStorage>()
- val mockAccount: OAuthAccount = mock()
+ val mockAccount: FirefoxAccount = mock()
val constellation: DeviceConstellation = mock()
val profile = Profile(uid = "testUID", avatar = null, email = "test@example.com", displayName = "test profile")
val accountObserver: AccountObserver = mock()
@@ -911,7 +835,7 @@ class FxaAccountManagerTest {
@Test
fun `unhappy pairing authentication flow`() = runTest {
val accountStorage = mock<AccountStorage>()
- val mockAccount: OAuthAccount = mock()
+ val mockAccount: FirefoxAccount = mock()
val constellation: DeviceConstellation = mock()
val profile = Profile(uid = "testUID", avatar = null, email = "test@example.com", displayName = "test profile")
val accountObserver: AccountObserver = mock()
@@ -970,7 +894,7 @@ class FxaAccountManagerTest {
@Test
fun `authentication issues are propagated via AccountObserver`() = runTest {
- val mockAccount: OAuthAccount = mock()
+ val mockAccount: FirefoxAccount = mock()
val constellation: DeviceConstellation = mock()
`when`(mockAccount.deviceConstellation()).thenReturn(constellation)
val profile = Profile(uid = "testUID", avatar = null, email = "test@example.com", displayName = "test profile")
@@ -1025,7 +949,7 @@ class FxaAccountManagerTest {
@Test
fun `authentication issues are recoverable via checkAuthorizationState`() = runTest {
- val mockAccount: OAuthAccount = mock()
+ val mockAccount: FirefoxAccount = mock()
val constellation: DeviceConstellation = mock()
`when`(mockAccount.deviceConstellation()).thenReturn(constellation)
val profile = Profile(uid = "testUID", avatar = null, email = "test@example.com", displayName = "test profile")
@@ -1072,7 +996,7 @@ class FxaAccountManagerTest {
@Test
fun `authentication recovery flow has a circuit breaker`() = runTest {
- val mockAccount: OAuthAccount = mock()
+ val mockAccount: FirefoxAccount = mock()
val constellation: DeviceConstellation = mock()
`when`(mockAccount.deviceConstellation()).thenReturn(constellation)
val profile = Profile(uid = "testUID", avatar = null, email = "test@example.com", displayName = "test profile")
@@ -1163,7 +1087,7 @@ class FxaAccountManagerTest {
@Test
fun `unhappy profile fetching flow`() = runTest {
val accountStorage = mock<AccountStorage>()
- val mockAccount: OAuthAccount = mock()
+ val mockAccount: FirefoxAccount = mock()
val constellation: DeviceConstellation = mock()
`when`(mockAccount.deviceConstellation()).thenReturn(constellation)
@@ -1232,7 +1156,7 @@ class FxaAccountManagerTest {
@Test
fun `profile fetching flow hit an unrecoverable auth problem`() = runTest {
val accountStorage = mock<AccountStorage>()
- val mockAccount: OAuthAccount = mock()
+ val mockAccount: FirefoxAccount = mock()
val constellation: DeviceConstellation = mock()
`when`(mockAccount.getCurrentDeviceId()).thenReturn("testDeviceId")
@@ -1292,7 +1216,7 @@ class FxaAccountManagerTest {
@Test
fun `profile fetching flow hit an unrecoverable auth problem for which we can't determine a recovery state`() = runTest {
val accountStorage = mock<AccountStorage>()
- val mockAccount: OAuthAccount = mock()
+ val mockAccount: FirefoxAccount = mock()
val constellation: DeviceConstellation = mock()
`when`(mockAccount.deviceConstellation()).thenReturn(constellation)
@@ -1353,7 +1277,7 @@ class FxaAccountManagerTest {
@Test
fun `profile fetching flow hit a recoverable auth problem`() = runTest {
val accountStorage = mock<AccountStorage>()
- val mockAccount: OAuthAccount = mock()
+ val mockAccount: FirefoxAccount = mock()
val constellation: DeviceConstellation = mock()
val captor = argumentCaptor<AuthType>()
@@ -1437,7 +1361,7 @@ class FxaAccountManagerTest {
@Test(expected = FxaPanicException::class)
fun `profile fetching flow hit an fxa panic, which is re-thrown`() = runTest {
val accountStorage = mock<AccountStorage>()
- val mockAccount: OAuthAccount = mock()
+ val mockAccount: FirefoxAccount = mock()
val constellation: DeviceConstellation = mock()
`when`(mockAccount.getCurrentDeviceId()).thenReturn("testDeviceId")
@@ -1564,7 +1488,7 @@ class FxaAccountManagerTest {
}
private suspend fun prepareHappyAuthenticationFlow(
- mockAccount: OAuthAccount,
+ mockAccount: FirefoxAccount,
profile: Profile,
accountStorage: AccountStorage,
accountObserver: AccountObserver,
@@ -1608,7 +1532,7 @@ class FxaAccountManagerTest {
}
private suspend fun prepareUnhappyAuthenticationFlow(
- mockAccount: OAuthAccount,
+ mockAccount: FirefoxAccount,
profile: Profile,
accountStorage: AccountStorage,
accountObserver: AccountObserver,
diff --git a/mobile/android/android-components/components/service/firefox-accounts/src/test/java/mozilla/components/service/fxa/manager/StateKtTest.kt b/mobile/android/android-components/components/service/firefox-accounts/src/test/java/mozilla/components/service/fxa/manager/StateKtTest.kt
index 6323861f0e..df37088ca7 100644
--- a/mobile/android/android-components/components/service/firefox-accounts/src/test/java/mozilla/components/service/fxa/manager/StateKtTest.kt
+++ b/mobile/android/android-components/components/service/firefox-accounts/src/test/java/mozilla/components/service/fxa/manager/StateKtTest.kt
@@ -83,8 +83,8 @@ class StateKtTest {
private fun instantiateEvent(eventClassSimpleName: String): Event {
return when (eventClassSimpleName) {
"Start" -> Event.Account.Start
- "BeginPairingFlow" -> Event.Account.BeginPairingFlow("http://some.pairing.url.com", mock())
- "BeginEmailFlow" -> Event.Account.BeginEmailFlow(mock())
+ "BeginPairingFlow" -> Event.Account.BeginPairingFlow("http://some.pairing.url.com", mock(), mock())
+ "BeginEmailFlow" -> Event.Account.BeginEmailFlow(mock(), mock())
"CancelAuth" -> Event.Progress.CancelAuth
"StartedOAuthFlow" -> Event.Progress.StartedOAuthFlow("https://example.com/oauth-start")
"AuthenticationError" -> Event.Account.AuthenticationError("fxa op")
diff --git a/mobile/android/android-components/components/service/firefox-accounts/src/test/java/mozilla/components/service/fxa/store/SyncStoreSupportTest.kt b/mobile/android/android-components/components/service/firefox-accounts/src/test/java/mozilla/components/service/fxa/store/SyncStoreSupportTest.kt
index e0d90118fa..975fd6a481 100644
--- a/mobile/android/android-components/components/service/firefox-accounts/src/test/java/mozilla/components/service/fxa/store/SyncStoreSupportTest.kt
+++ b/mobile/android/android-components/components/service/firefox-accounts/src/test/java/mozilla/components/service/fxa/store/SyncStoreSupportTest.kt
@@ -12,13 +12,16 @@ import kotlinx.coroutines.test.TestScope
import kotlinx.coroutines.test.runCurrent
import kotlinx.coroutines.test.runTest
import kotlinx.coroutines.test.setMain
+import mozilla.components.concept.sync.AuthFlowError
import mozilla.components.concept.sync.AuthType
import mozilla.components.concept.sync.Avatar
import mozilla.components.concept.sync.ConstellationState
import mozilla.components.concept.sync.DeviceConstellation
import mozilla.components.concept.sync.OAuthAccount
import mozilla.components.concept.sync.Profile
+import mozilla.components.service.fxa.manager.AccountState
import mozilla.components.service.fxa.manager.FxaAccountManager
+import mozilla.components.service.fxa.manager.SCOPE_PROFILE
import mozilla.components.support.test.any
import mozilla.components.support.test.coMock
import mozilla.components.support.test.eq
@@ -26,9 +29,11 @@ import mozilla.components.support.test.libstate.ext.waitUntilIdle
import mozilla.components.support.test.mock
import mozilla.components.support.test.whenever
import org.junit.Assert.assertEquals
+import org.junit.Assert.assertNull
import org.junit.Before
import org.junit.Test
import org.mockito.Mockito.verify
+import org.mockito.Mockito.`when`
import java.lang.Exception
@OptIn(ExperimentalCoroutinesApi::class)
@@ -115,7 +120,7 @@ class SyncStoreSupportTest {
}
@Test
- fun `GIVEN account observer WHEN onAuthenticated observed with profile THEN account state updated`() = coroutineScope.runTest {
+ fun `GIVEN account observer WHEN onAuthenticated observed with profile THEN account and account state are updated`() = coroutineScope.runTest {
val profile = generateProfile()
val constellation = mock<DeviceConstellation>()
val account = coMock<OAuthAccount> {
@@ -125,6 +130,8 @@ class SyncStoreSupportTest {
whenever(getProfile()).thenReturn(profile)
}
+ assertEquals(AccountState.NotAuthenticated, store.state.accountState)
+
accountObserver.onAuthenticated(account, mock<AuthType.Existing>())
runCurrent()
@@ -138,10 +145,11 @@ class SyncStoreSupportTest {
)
store.waitUntilIdle()
assertEquals(expected, store.state.account)
+ assertEquals(AccountState.Authenticated, store.state.accountState)
}
@Test
- fun `GIVEN account observer WHEN onAuthenticated observed without profile THEN account not updated`() = coroutineScope.runTest {
+ fun `GIVEN account observer WHEN onAuthenticated observed without profile THEN account and account state are not updated`() = coroutineScope.runTest {
val constellation = mock<DeviceConstellation>()
val account = coMock<OAuthAccount> {
whenever(deviceConstellation()).thenReturn(constellation)
@@ -152,11 +160,12 @@ class SyncStoreSupportTest {
runCurrent()
store.waitUntilIdle()
- assertEquals(null, store.state.account)
+ assertNull(store.state.account)
+ assertEquals(AccountState.NotAuthenticated, store.state.accountState)
}
@Test
- fun `GIVEN user is logged in WHEN onLoggedOut observed THEN sync status and account updated`() = coroutineScope.runTest {
+ fun `GIVEN user is logged in WHEN onLoggedOut observed THEN sync status and account states are updated`() = coroutineScope.runTest {
val account = coMock<OAuthAccount> {
whenever(deviceConstellation()).thenReturn(mock())
whenever(getProfile()).thenReturn(null)
@@ -169,7 +178,94 @@ class SyncStoreSupportTest {
store.waitUntilIdle()
assertEquals(SyncStatus.LoggedOut, store.state.status)
- assertEquals(null, store.state.account)
+ assertNull(store.state.account)
+ assertEquals(AccountState.NotAuthenticated, store.state.accountState)
+ }
+
+ @Test
+ fun `GIVEN account observer WHEN onAuthenticationProblems observed THEN account state is updated`() = coroutineScope.runTest {
+ assertEquals(AccountState.NotAuthenticated, store.state.accountState)
+
+ accountObserver.onAuthenticationProblems()
+ runCurrent()
+
+ store.waitUntilIdle()
+ assertEquals(AccountState.AuthenticationProblem, store.state.accountState)
+ }
+
+ @Test
+ fun `GIVEN account observer WHEN onFlowError observed THEN account state is updated`() = coroutineScope.runTest {
+ assertNull(store.state.account)
+ assertEquals(AccountState.NotAuthenticated, store.state.accountState)
+
+ accountObserver.onFlowError(mock<AuthFlowError>())
+ runCurrent()
+
+ store.waitUntilIdle()
+ assertNull(store.state.account)
+ assertEquals(AccountState.NotAuthenticated, store.state.accountState)
+ }
+
+ @Test
+ fun `GIVEN account observer WHEN onReady observed with profile THEN account states are updated`() = coroutineScope.runTest {
+ val profile = generateProfile()
+ val currentDeviceId = "id"
+ val sessionToken = "token"
+ val constellation = mock<DeviceConstellation>()
+ val authenticatedAccount = coMock<OAuthAccount> {
+ whenever(deviceConstellation()).thenReturn(constellation)
+ whenever(getCurrentDeviceId()).thenReturn(currentDeviceId)
+ whenever(getSessionToken()).thenReturn(sessionToken)
+ whenever(getProfile()).thenReturn(profile)
+ }
+ val account = Account(
+ uid = profile.uid,
+ email = profile.email,
+ avatar = profile.avatar,
+ displayName = profile.displayName,
+ currentDeviceId = currentDeviceId,
+ sessionToken = sessionToken,
+ )
+
+ assertNull(store.state.account)
+ assertEquals(AccountState.NotAuthenticated, store.state.accountState)
+
+ `when`(authenticatedAccount.checkAuthorizationStatus(eq(SCOPE_PROFILE))).thenReturn(false)
+
+ accountObserver.onReady(authenticatedAccount = authenticatedAccount)
+ runCurrent()
+
+ store.waitUntilIdle()
+ assertEquals(account, store.state.account)
+ assertEquals(AccountState.AuthenticationProblem, store.state.accountState)
+
+ `when`(authenticatedAccount.checkAuthorizationStatus(eq(SCOPE_PROFILE))).thenReturn(true)
+
+ accountObserver.onReady(authenticatedAccount = authenticatedAccount)
+ runCurrent()
+
+ store.waitUntilIdle()
+ assertEquals(account, store.state.account)
+ assertEquals(AccountState.Authenticated, store.state.accountState)
+ }
+
+ @Test
+ fun `GIVEN account observer WHEN onReady observed without profile THEN account states are not updated`() = coroutineScope.runTest {
+ val constellation = mock<DeviceConstellation>()
+ val account = coMock<OAuthAccount> {
+ whenever(deviceConstellation()).thenReturn(constellation)
+ whenever(getProfile()).thenReturn(null)
+ }
+
+ assertNull(store.state.account)
+ assertEquals(AccountState.NotAuthenticated, store.state.accountState)
+
+ accountObserver.onReady(account)
+ runCurrent()
+
+ store.waitUntilIdle()
+ assertNull(store.state.account)
+ assertEquals(AccountState.NotAuthenticated, store.state.accountState)
}
@Test
diff --git a/mobile/android/android-components/components/service/glean/src/main/java/mozilla/components/service/glean/Glean.kt b/mobile/android/android-components/components/service/glean/src/main/java/mozilla/components/service/glean/Glean.kt
index 232ac1b83f..2990220b31 100644
--- a/mobile/android/android-components/components/service/glean/src/main/java/mozilla/components/service/glean/Glean.kt
+++ b/mobile/android/android-components/components/service/glean/src/main/java/mozilla/components/service/glean/Glean.kt
@@ -116,8 +116,8 @@ object Glean {
*
* @param enabled Map of metrics' enabled state.
*/
- fun setMetricsEnabledConfig(enabled: Map<String, Boolean>) {
- GleanCore.setMetricsEnabledConfig(JSONObject(enabled).toString())
+ fun applyServerKnobsConfig(enabled: Map<String, Boolean>) {
+ GleanCore.applyServerKnobsConfig(JSONObject(enabled).toString())
}
/**
diff --git a/mobile/android/android-components/components/service/glean/src/main/java/mozilla/components/service/glean/config/Configuration.kt b/mobile/android/android-components/components/service/glean/src/main/java/mozilla/components/service/glean/config/Configuration.kt
index 11911c7046..382078d3c9 100644
--- a/mobile/android/android-components/components/service/glean/src/main/java/mozilla/components/service/glean/config/Configuration.kt
+++ b/mobile/android/android-components/components/service/glean/src/main/java/mozilla/components/service/glean/config/Configuration.kt
@@ -19,6 +19,8 @@ import mozilla.telemetry.glean.config.Configuration as GleanCoreConfiguration
* @property channel (optional )the release channel the application is on, if known. This will be
* sent along with all the pings, in the `client_info` section.
* @property maxEvents (optional) the number of events to store before the events ping is sent
+ * @property enableEventTimestamps (Experimental) Whether to add a wallclock timestamp to all events.
+ * @property delayPingLifetimeIo Whether Glean should delay persistence of data from metrics with ping lifetime.
*/
data class Configuration @JvmOverloads constructor(
val httpClient: PingUploader,
@@ -26,6 +28,7 @@ data class Configuration @JvmOverloads constructor(
val channel: String? = null,
val maxEvents: Int? = null,
val enableEventTimestamps: Boolean = false,
+ val delayPingLifetimeIo: Boolean = false,
) {
// The following is required to support calling our API from Java.
companion object {
@@ -45,6 +48,7 @@ data class Configuration @JvmOverloads constructor(
maxEvents = maxEvents,
httpClient = httpClient,
enableEventTimestamps = enableEventTimestamps,
+ delayPingLifetimeIo = delayPingLifetimeIo,
)
}
}
diff --git a/mobile/android/android-components/components/service/glean/src/main/java/mozilla/components/service/glean/private/MetricAliases.kt b/mobile/android/android-components/components/service/glean/src/main/java/mozilla/components/service/glean/private/MetricAliases.kt
index e6e0be9424..b98af6a480 100644
--- a/mobile/android/android-components/components/service/glean/src/main/java/mozilla/components/service/glean/private/MetricAliases.kt
+++ b/mobile/android/android-components/components/service/glean/src/main/java/mozilla/components/service/glean/private/MetricAliases.kt
@@ -4,8 +4,6 @@
package mozilla.components.service.glean.private
-import androidx.annotation.VisibleForTesting
-
typealias CommonMetricData = mozilla.telemetry.glean.private.CommonMetricData
typealias EventExtras = mozilla.telemetry.glean.private.EventExtras
typealias Lifetime = mozilla.telemetry.glean.private.Lifetime
@@ -18,12 +16,14 @@ typealias CounterMetricType = mozilla.telemetry.glean.private.CounterMetricType
typealias CustomDistributionMetricType = mozilla.telemetry.glean.private.CustomDistributionMetricType
typealias DatetimeMetricType = mozilla.telemetry.glean.private.DatetimeMetricType
typealias DenominatorMetricType = mozilla.telemetry.glean.private.DenominatorMetricType
+typealias EventMetricType<T> = mozilla.telemetry.glean.private.EventMetricType<T>
typealias HistogramMetricBase = mozilla.telemetry.glean.private.HistogramBase
typealias HistogramType = mozilla.telemetry.glean.private.HistogramType
typealias LabeledMetricType<T> = mozilla.telemetry.glean.private.LabeledMetricType<T>
typealias MemoryDistributionMetricType = mozilla.telemetry.glean.private.MemoryDistributionMetricType
typealias MemoryUnit = mozilla.telemetry.glean.private.MemoryUnit
typealias NumeratorMetricType = mozilla.telemetry.glean.private.NumeratorMetricType
+typealias ObjectSerialize = mozilla.telemetry.glean.private.ObjectSerialize
typealias PingType<T> = mozilla.telemetry.glean.private.PingType<T>
typealias QuantityMetricType = mozilla.telemetry.glean.private.QuantityMetricType
typealias RateMetricType = mozilla.telemetry.glean.private.RateMetricType
@@ -31,89 +31,8 @@ typealias RecordedExperiment = mozilla.telemetry.glean.private.RecordedExperimen
typealias StringListMetricType = mozilla.telemetry.glean.private.StringListMetricType
typealias StringMetricType = mozilla.telemetry.glean.private.StringMetricType
typealias TextMetricType = mozilla.telemetry.glean.private.TextMetricType
-typealias TimeUnit = mozilla.telemetry.glean.private.TimeUnit
typealias TimespanMetricType = mozilla.telemetry.glean.private.TimespanMetricType
+typealias TimeUnit = mozilla.telemetry.glean.private.TimeUnit
typealias TimingDistributionMetricType = mozilla.telemetry.glean.private.TimingDistributionMetricType
typealias UrlMetricType = mozilla.telemetry.glean.private.UrlMetricType
typealias UuidMetricType = mozilla.telemetry.glean.private.UuidMetricType
-
-// FIXME(bug 1885170): Wrap the Glean SDK `EventMetricType` to overwrite the `testGetValue` function.
-/**
- * This implements the developer facing API for recording events.
- *
- * Instances of this class type are automatically generated by the parsers at built time,
- * allowing developers to record events that were previously registered in the metrics.yaml file.
- *
- * The Events API only exposes the [record] method, which takes care of validating the input
- * data and making sure that limits are enforced.
- */
-class EventMetricType<ExtraObject> internal constructor(
- private var inner: mozilla.telemetry.glean.private.EventMetricType<ExtraObject>,
-) where ExtraObject : EventExtras {
- /**
- * The public constructor used by automatically generated metrics.
- */
- constructor(meta: CommonMetricData, allowedExtraKeys: List<String>) :
- this(inner = mozilla.telemetry.glean.private.EventMetricType(meta, allowedExtraKeys))
-
- /**
- * Record an event by using the information provided by the instance of this class.
- *
- * @param extra The event extra properties.
- * Values are converted to strings automatically
- * This is used for events where additional richer context is needed.
- * The maximum length for values is 100 bytes.
- *
- * Note: `extra` is not optional here to avoid overlapping with the above definition of `record`.
- * If no `extra` data is passed the above function will be invoked correctly.
- */
- fun record(extra: ExtraObject? = null) {
- inner.record(extra)
- }
-
- /**
- * Returns the stored value for testing purposes only. This function will attempt to await the
- * last task (if any) writing to the the metric's storage engine before returning a value.
- *
- * @param pingName represents the name of the ping to retrieve the metric for.
- * Defaults to the first value in `sendInPings`.
- * @return value of the stored events
- */
- @VisibleForTesting(otherwise = VisibleForTesting.NONE)
- @JvmOverloads
- fun testGetValue(pingName: String? = null): List<mozilla.telemetry.glean.private.RecordedEvent>? {
- var events = inner.testGetValue(pingName)
- if (events == null) {
- return events
- }
-
- // Remove the `glean_timestamp` extra.
- // This is added by Glean and does not need to be exposed to testing.
- for (event in events) {
- if (event.extra == null) {
- continue
- }
-
- // We know it's not null
- var map = event.extra!!.toMutableMap()
- map.remove("glean_timestamp")
- if (map.isEmpty()) {
- event.extra = null
- } else {
- event.extra = map
- }
- }
-
- return events
- }
-
- /**
- * Returns the number of errors recorded for the given metric.
- *
- * @param errorType The type of the error recorded.
- * @return the number of errors recorded for the metric.
- */
- @VisibleForTesting(otherwise = VisibleForTesting.NONE)
- fun testGetNumRecordedErrors(errorType: mozilla.components.service.glean.testing.ErrorType) =
- inner.testGetNumRecordedErrors(errorType)
-}
diff --git a/mobile/android/android-components/components/service/nimbus/messaging.fml.yaml b/mobile/android/android-components/components/service/nimbus/messaging.fml.yaml
index c53456e31e..a37818f8e8 100644
--- a/mobile/android/android-components/components/service/nimbus/messaging.fml.yaml
+++ b/mobile/android/android-components/components/service/nimbus/messaging.fml.yaml
@@ -111,16 +111,20 @@ objects:
default: {}
title:
type: Option<Text>
- description: "The title text displayed to the user"
+ description: The title text displayed to the user
default: null
text:
type: Text
- description: "The message text displayed to the user"
+ description: The message text displayed to the user
# This should never be defaulted.
default: ""
+ microsurveyConfig:
+ type: Option<MicrosurveyConfig>
+ description: Optional configuration data for a microsurvey.
+ default: null
is-control:
type: Boolean
- description: "Indicates if this message is the control message, if true shouldn't be displayed"
+ description: Indicates if this message is the control message, if true shouldn't be displayed
default: false
experiment:
type: Option<ExperimentSlug>
@@ -183,6 +187,17 @@ objects:
How often, in minutes, the notification message worker will wake up and check for new
messages.
default: 240 # 4 hours
+ MicrosurveyConfig:
+ description: Attributes relating to microsurvey content.
+ fields:
+ target-feature:
+ type: MicrosurveyTargetFeature
+ description: The type of feature the microsurvey is for e.g. Printing.
+ default: unknown # Should not be defaulted
+ options:
+ description: The list of options to present to the user e.g. "Satisfied, Dissatisfied...".
+ type: List<Text>
+ default: [] # Should not be defaulted
enums:
ControlMessageBehavior:
@@ -192,3 +207,11 @@ enums:
description: The next eligible message should be shown.
show-none:
description: The surface should show no message.
+
+ MicrosurveyTargetFeature:
+ description: The specific feature the microsurvey is for e.g Printing.
+ variants:
+ printing:
+ description: The printing feature.
+ unknown:
+ description: No target feature set. Only used in an invalid experiment configuration.
diff --git a/mobile/android/android-components/components/service/pocket/src/test/resources/pocket/stories_recommendations_response.json b/mobile/android/android-components/components/service/pocket/src/test/resources/pocket/stories_recommendations_response.json
index da2b9a2953..f410fd7d3d 100644
--- a/mobile/android/android-components/components/service/pocket/src/test/resources/pocket/stories_recommendations_response.json
+++ b/mobile/android/android-components/components/service/pocket/src/test/resources/pocket/stories_recommendations_response.json
@@ -1,44 +1,44 @@
{
- "recommendations": [
- {
- "category": "general",
- "url": "https://getpocket.com/explore/item/how-to-remember-anything-you-really-want-to-remember-backed-by-science",
- "title": "How to Remember Anything You Really Want to Remember, Backed by Science",
- "imageUrl": "https://img-getpocket.cdn.mozilla.net/{wh}/filters:format(jpeg):quality(60):no_upscale():strip_exif()/https%3A%2F%2Fpocket-image-cache.com%2F1200x%2Ffilters%3Aformat(jpg)%3Aextract_focal()%2Fhttps%253A%252F%252Fwww.incimages.com%252Fuploaded_files%252Fimage%252F1920x1080%252Fgetty-862457080_394628.jpg",
- "publisher": "Pocket",
- "timeToRead": 3
- },
- {
- "category": "general",
- "url": "https://www.thecut.com/article/i-dont-want-to-be-like-a-family-with-my-co-workers.html",
- "title": "‘I Don’t Want to Be Like a Family With My Co-Workers’",
- "imageUrl": "https://img-getpocket.cdn.mozilla.net/{wh}/filters:format(jpeg):quality(60):no_upscale():strip_exif()/https%3A%2F%2Fpyxis.nymag.com%2Fv1%2Fimgs%2Fac8%2Fd22%2F315cd0cf1e3a43edfe0e0548f2edbcb1a1-ask-a-boss.1x.rsocial.w1200.jpg",
- "publisher": "The Cut",
- "timeToRead": 5
- },
- {
- "category": "general",
- "url": "https://www.newyorker.com/news/q-and-a/how-america-failed-in-afghanistan",
- "title": "How America Failed in Afghanistan",
- "imageUrl": "https://img-getpocket.cdn.mozilla.net/{wh}/filters:format(jpeg):quality(60):no_upscale():strip_exif()/https%3A%2F%2Fmedia.newyorker.com%2Fphotos%2F6119484157b611aec9c99b43%2F16%3A9%2Fw_1280%2Cc_limit%2FChotiner-Afghanistan01.jpg",
- "publisher": "The New Yorker",
- "timeToRead": 14
- },
- {
- "category": "general",
- "url": "https://www.technologyreview.com/2021/08/15/1031804/digital-beauty-filters-photoshop-photo-editing-colorism-racism/",
- "title": "How digital beauty filters perpetuate colorism",
- "imageUrl": "https://img-getpocket.cdn.mozilla.net/{wh}/filters:format(jpeg):quality(60):no_upscale():strip_exif()/https%3A%2F%2Fwp.technologyreview.com%2Fwp-content%2Fuploads%2F2021%2F08%2FBeautyScoreColorism.jpg%3Fresize%3D1200%2C600",
- "publisher": "MIT Technology Review",
- "timeToRead": 11
- },
- {
- "category": "general",
- "url": "https://getpocket.com/explore/item/how-to-get-rid-of-black-mold-naturally",
- "title": "How to Get Rid of Black Mold Naturally",
- "imageUrl": "https://img-getpocket.cdn.mozilla.net/{wh}/filters:format(jpeg):quality(60):no_upscale():strip_exif()/https%3A%2F%2Fpocket-image-cache.com%2F1200x%2Ffilters%3Aformat(jpg)%3Aextract_focal()%2Fhttps%253A%252F%252Fpocket-syndicated-images.s3.amazonaws.com%252Farticles%252F6757%252F1628024495_6109ae86db6cc.png",
- "publisher": "Pocket",
- "timeToRead": 4
- }
- ]
+ "recommendations": [
+ {
+ "category": "general",
+ "url": "https://getpocket.com/explore/item/how-to-remember-anything-you-really-want-to-remember-backed-by-science",
+ "title": "How to Remember Anything You Really Want to Remember, Backed by Science",
+ "imageUrl": "https://img-getpocket.cdn.mozilla.net/{wh}/filters:format(jpeg):quality(60):no_upscale():strip_exif()/https%3A%2F%2Fpocket-image-cache.com%2F1200x%2Ffilters%3Aformat(jpg)%3Aextract_focal()%2Fhttps%253A%252F%252Fwww.incimages.com%252Fuploaded_files%252Fimage%252F1920x1080%252Fgetty-862457080_394628.jpg",
+ "publisher": "Pocket",
+ "timeToRead": 3
+ },
+ {
+ "category": "general",
+ "url": "https://www.thecut.com/article/i-dont-want-to-be-like-a-family-with-my-co-workers.html",
+ "title": "‘I Don’t Want to Be Like a Family With My Co-Workers’",
+ "imageUrl": "https://img-getpocket.cdn.mozilla.net/{wh}/filters:format(jpeg):quality(60):no_upscale():strip_exif()/https%3A%2F%2Fpyxis.nymag.com%2Fv1%2Fimgs%2Fac8%2Fd22%2F315cd0cf1e3a43edfe0e0548f2edbcb1a1-ask-a-boss.1x.rsocial.w1200.jpg",
+ "publisher": "The Cut",
+ "timeToRead": 5
+ },
+ {
+ "category": "general",
+ "url": "https://www.newyorker.com/news/q-and-a/how-america-failed-in-afghanistan",
+ "title": "How America Failed in Afghanistan",
+ "imageUrl": "https://img-getpocket.cdn.mozilla.net/{wh}/filters:format(jpeg):quality(60):no_upscale():strip_exif()/https%3A%2F%2Fmedia.newyorker.com%2Fphotos%2F6119484157b611aec9c99b43%2F16%3A9%2Fw_1280%2Cc_limit%2FChotiner-Afghanistan01.jpg",
+ "publisher": "The New Yorker",
+ "timeToRead": 14
+ },
+ {
+ "category": "general",
+ "url": "https://www.technologyreview.com/2021/08/15/1031804/digital-beauty-filters-photoshop-photo-editing-colorism-racism/",
+ "title": "How digital beauty filters perpetuate colorism",
+ "imageUrl": "https://img-getpocket.cdn.mozilla.net/{wh}/filters:format(jpeg):quality(60):no_upscale():strip_exif()/https%3A%2F%2Fwp.technologyreview.com%2Fwp-content%2Fuploads%2F2021%2F08%2FBeautyScoreColorism.jpg%3Fresize%3D1200%2C600",
+ "publisher": "MIT Technology Review",
+ "timeToRead": 11
+ },
+ {
+ "category": "general",
+ "url": "https://getpocket.com/explore/item/how-to-get-rid-of-black-mold-naturally",
+ "title": "How to Get Rid of Black Mold Naturally",
+ "imageUrl": "https://img-getpocket.cdn.mozilla.net/{wh}/filters:format(jpeg):quality(60):no_upscale():strip_exif()/https%3A%2F%2Fpocket-image-cache.com%2F1200x%2Ffilters%3Aformat(jpg)%3Aextract_focal()%2Fhttps%253A%252F%252Fpocket-syndicated-images.s3.amazonaws.com%252Farticles%252F6757%252F1628024495_6109ae86db6cc.png",
+ "publisher": "Pocket",
+ "timeToRead": 4
+ }
+ ]
}
diff --git a/mobile/android/android-components/components/service/pocket/src/test/resources/pocket/story_recommendation_response.json b/mobile/android/android-components/components/service/pocket/src/test/resources/pocket/story_recommendation_response.json
index 8fa6e33ad7..99b6ef44d0 100644
--- a/mobile/android/android-components/components/service/pocket/src/test/resources/pocket/story_recommendation_response.json
+++ b/mobile/android/android-components/components/service/pocket/src/test/resources/pocket/story_recommendation_response.json
@@ -1,12 +1,12 @@
{
- "recommendations": [
- {
- "category": "science",
- "url": "https://getpocket.com/explore/item/you-think-you-know-what-blue-is-but-you-have-no-idea",
- "title": "You Think You Know What Blue Is, But You Have No Idea",
- "imageUrl": "https://img-getpocket.cdn.mozilla.net/{wh}/filters:format(jpeg):quality(60):no_upscale():strip_exif()/https%3A%2F%2Fpocket-image-cache.com%2F1200x%2Ffilters%3Aformat(jpg)%3Aextract_focal()%2Fhttps%253A%252F%252Fpocket-syndicated-images.s3.amazonaws.com%252Farticles%252F3713%252F1584373694_GettyImages-83522858.jpg",
- "publisher": "Pocket",
- "timeToRead": 3
- }
- ]
+ "recommendations": [
+ {
+ "category": "science",
+ "url": "https://getpocket.com/explore/item/you-think-you-know-what-blue-is-but-you-have-no-idea",
+ "title": "You Think You Know What Blue Is, But You Have No Idea",
+ "imageUrl": "https://img-getpocket.cdn.mozilla.net/{wh}/filters:format(jpeg):quality(60):no_upscale():strip_exif()/https%3A%2F%2Fpocket-image-cache.com%2F1200x%2Ffilters%3Aformat(jpg)%3Aextract_focal()%2Fhttps%253A%252F%252Fpocket-syndicated-images.s3.amazonaws.com%252Farticles%252F3713%252F1584373694_GettyImages-83522858.jpg",
+ "publisher": "Pocket",
+ "timeToRead": 3
+ }
+ ]
}
diff --git a/mobile/android/android-components/components/service/sync-logins/src/main/java/mozilla/components/service/sync/logins/GeckoLoginStorageDelegate.kt b/mobile/android/android-components/components/service/sync-logins/src/main/java/mozilla/components/service/sync/logins/GeckoLoginStorageDelegate.kt
index 892930e28d..f66b727cf1 100644
--- a/mobile/android/android-components/components/service/sync-logins/src/main/java/mozilla/components/service/sync/logins/GeckoLoginStorageDelegate.kt
+++ b/mobile/android/android-components/components/service/sync-logins/src/main/java/mozilla/components/service/sync/logins/GeckoLoginStorageDelegate.kt
@@ -4,6 +4,7 @@
package mozilla.components.service.sync.logins
+import kotlinx.coroutines.CompletableDeferred
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Deferred
import kotlinx.coroutines.Dispatchers
@@ -42,10 +43,15 @@ import mozilla.components.concept.storage.LoginsStorage
* what the result of the operation will be: saving a new login,
* updating an existing login, or filling in a blank username.
* - If the user accepts: GV calls [onLoginSave] with the [LoginEntry]
+ *
+ * @param loginStorage The [LoginsStorage] used for looking up saved credentials to autofill.
+ * @param scope [CoroutineScope] for long running operations. Defaults to using the [Dispatchers.IO].
+ * @param isLoginAutofillEnabled callback allowing to limit [loginStorage] operations if autofill is disabled.
*/
class GeckoLoginStorageDelegate(
private val loginStorage: Lazy<LoginsStorage>,
private val scope: CoroutineScope = CoroutineScope(Dispatchers.IO),
+ private val isLoginAutofillEnabled: () -> Boolean = { false },
) : LoginStorageDelegate {
override fun onLoginUsed(login: Login) {
@@ -55,6 +61,9 @@ class GeckoLoginStorageDelegate(
}
override fun onLoginFetch(domain: String): Deferred<List<Login>> {
+ if (!isLoginAutofillEnabled()) {
+ return CompletableDeferred(listOf())
+ }
return scope.async {
loginStorage.value.getByBaseDomain(domain)
}
diff --git a/mobile/android/android-components/components/support/base/build.gradle b/mobile/android/android-components/components/support/base/build.gradle
index 76918b4c21..bc7bffa7e7 100644
--- a/mobile/android/android-components/components/support/base/build.gradle
+++ b/mobile/android/android-components/components/support/base/build.gradle
@@ -74,6 +74,7 @@ android {
dependencies {
implementation ComponentsDependencies.kotlin_coroutines
+ implementation ComponentsDependencies.androidx_core_ktx
implementation ComponentsDependencies.androidx_lifecycle_viewmodel
api project(":concept-base")
diff --git a/mobile/android/android-components/components/support/base/src/main/java/mozilla/components/support/base/android/BuildVersionProvider.kt b/mobile/android/android-components/components/support/base/src/main/java/mozilla/components/support/base/android/BuildVersionProvider.kt
new file mode 100644
index 0000000000..406e851049
--- /dev/null
+++ b/mobile/android/android-components/components/support/base/src/main/java/mozilla/components/support/base/android/BuildVersionProvider.kt
@@ -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/. */
+
+package mozilla.components.support.base.android
+
+import android.os.Build
+
+/**
+ * This class provides information about the build version without exposing the android framework
+ * APIs directly, making it easier to test the code that depends on it.
+ */
+interface BuildVersionProvider {
+
+ /**
+ * Returns the SDK_INT of the current build version.
+ */
+ fun sdkInt(): Int
+
+ companion object {
+ const val FOREGROUND_SERVICE_RESTRICTIONS_STARTING_VERSION = Build.VERSION_CODES.S
+ }
+}
+
+/**
+ * @see BuildVersionProvider
+ */
+class DefaultBuildVersionProvider : BuildVersionProvider {
+
+ override fun sdkInt(): Int = Build.VERSION.SDK_INT
+}
diff --git a/mobile/android/android-components/components/support/base/src/main/java/mozilla/components/support/base/android/PowerManagerInfoProvider.kt b/mobile/android/android-components/components/support/base/src/main/java/mozilla/components/support/base/android/PowerManagerInfoProvider.kt
new file mode 100644
index 0000000000..0d8a78efb3
--- /dev/null
+++ b/mobile/android/android-components/components/support/base/src/main/java/mozilla/components/support/base/android/PowerManagerInfoProvider.kt
@@ -0,0 +1,39 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+package mozilla.components.support.base.android
+
+import android.content.Context
+import android.os.Build
+import android.os.PowerManager
+import androidx.core.content.ContextCompat
+
+/**
+ * This class provides information about battery optimisations without exposing the android
+ * framework APIs directly, making it easier to test the code that depends on it.
+ */
+interface PowerManagerInfoProvider {
+
+ /**
+ * Returns true if the user has disabled battery optimisations for the app.
+ */
+ fun isIgnoringBatteryOptimizations(): Boolean
+}
+
+/**
+ * @see PowerManagerInfoProvider
+ */
+class DefaultPowerManagerInfoProvider(private val context: Context) : PowerManagerInfoProvider {
+
+ private val powerManager by lazy {
+ ContextCompat.getSystemService(context, PowerManager::class.java)
+ }
+
+ override fun isIgnoringBatteryOptimizations(): Boolean =
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
+ powerManager?.isIgnoringBatteryOptimizations(context.packageName) ?: false
+ } else {
+ true
+ }
+}
diff --git a/mobile/android/android-components/components/support/base/src/main/java/mozilla/components/support/base/android/ProcessInfoProvider.kt b/mobile/android/android-components/components/support/base/src/main/java/mozilla/components/support/base/android/ProcessInfoProvider.kt
new file mode 100644
index 0000000000..2890b8c4c4
--- /dev/null
+++ b/mobile/android/android-components/components/support/base/src/main/java/mozilla/components/support/base/android/ProcessInfoProvider.kt
@@ -0,0 +1,32 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+package mozilla.components.support.base.android
+
+import android.app.ActivityManager
+
+/**
+ * This class provides information the running app process without exposing the android framework
+ * APIs directly, making easier to test the code that depends on it.
+ */
+interface ProcessInfoProvider {
+
+ /**
+ * Returns true if the current app process is in the foreground.
+ */
+ fun isForegroundImportance(): Boolean
+}
+
+/**
+ * @see ProcessInfoProvider
+ */
+class DefaultProcessInfoProvider : ProcessInfoProvider {
+
+ override fun isForegroundImportance(): Boolean {
+ val appProcessInfo = ActivityManager.RunningAppProcessInfo()
+ ActivityManager.getMyMemoryState(appProcessInfo)
+
+ return appProcessInfo.importance == ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND
+ }
+}
diff --git a/mobile/android/android-components/components/support/base/src/main/java/mozilla/components/support/base/android/StartForegroundService.kt b/mobile/android/android-components/components/support/base/src/main/java/mozilla/components/support/base/android/StartForegroundService.kt
new file mode 100644
index 0000000000..9bfa946205
--- /dev/null
+++ b/mobile/android/android-components/components/support/base/src/main/java/mozilla/components/support/base/android/StartForegroundService.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.support.base.android
+
+/**
+ * This class is used to start a foreground service safely. For api levels >= 31. It will only
+ * start the service if the app is in the foreground to prevent throwing the
+ * ForegroundServiceStartNotAllowedException.
+ *
+ * @param processInfoProvider The provider to check if the app is in the foreground.
+ * @param buildVersionProvider The provider to get the sdk version.
+ */
+class StartForegroundService(
+ private val processInfoProvider: ProcessInfoProvider = DefaultProcessInfoProvider(),
+ private val buildVersionProvider: BuildVersionProvider = DefaultBuildVersionProvider(),
+ private val powerManagerInfoProvider: PowerManagerInfoProvider,
+) {
+
+ /**
+ * @see StartForegroundService
+ *
+ * @param func The function to run if the app is in the foreground to follow the foreground
+ * service restrictions for sdk version >= 31. For lower versions, the function will always run.
+ */
+ operator fun invoke(func: () -> Unit): Boolean =
+ if (buildVersionProvider.sdkInt() >= BuildVersionProvider.FOREGROUND_SERVICE_RESTRICTIONS_STARTING_VERSION) {
+ if (powerManagerInfoProvider.isIgnoringBatteryOptimizations() ||
+ processInfoProvider.isForegroundImportance()
+ ) {
+ func()
+ true
+ } else {
+ false
+ }
+ } else {
+ func()
+ true
+ }
+}
diff --git a/mobile/android/android-components/components/support/base/src/main/java/mozilla/components/support/base/feature/UserInteractionHandler.kt b/mobile/android/android-components/components/support/base/src/main/java/mozilla/components/support/base/feature/UserInteractionHandler.kt
index 25e16ffcce..f52b19b93c 100644
--- a/mobile/android/android-components/components/support/base/src/main/java/mozilla/components/support/base/feature/UserInteractionHandler.kt
+++ b/mobile/android/android-components/components/support/base/src/main/java/mozilla/components/support/base/feature/UserInteractionHandler.kt
@@ -19,6 +19,13 @@ interface UserInteractionHandler {
fun onBackPressed(): Boolean
/**
+ * Called when this [UserInteractionHandler] gets the option to handle the user pressing the forward key.
+ *
+ * Returns true if this [UserInteractionHandler] consumed the event and no other components need to be notified.
+ */
+ fun onForwardPressed(): Boolean = false
+
+ /**
* In most cases, when the home button is pressed, we invoke this callback to inform the app that the user
* is going to leave the app.
*
diff --git a/mobile/android/android-components/components/support/base/src/main/java/mozilla/components/support/base/feature/ViewBoundFeatureWrapper.kt b/mobile/android/android-components/components/support/base/src/main/java/mozilla/components/support/base/feature/ViewBoundFeatureWrapper.kt
index a6d1e8709c..02a48abdab 100644
--- a/mobile/android/android-components/components/support/base/src/main/java/mozilla/components/support/base/feature/ViewBoundFeatureWrapper.kt
+++ b/mobile/android/android-components/components/support/base/src/main/java/mozilla/components/support/base/feature/ViewBoundFeatureWrapper.kt
@@ -157,6 +157,24 @@ class ViewBoundFeatureWrapper<T : LifecycleAwareFeature>() {
}
/**
+ * Convenience method for invoking [UserInteractionHandler.onForwardPressed] on a wrapped
+ * [LifecycleAwareFeature] that implements [UserInteractionHandler]. Returns false if
+ * the [LifecycleAwareFeature] was cleared already.
+ */
+ @Synchronized
+ fun onForwardPressed(): Boolean {
+ val feature = feature ?: return false
+
+ if (feature !is UserInteractionHandler) {
+ throw IllegalAccessError(
+ "Feature does not implement ${UserInteractionHandler::class.java.simpleName} interface",
+ )
+ }
+
+ return feature.onForwardPressed()
+ }
+
+ /**
* Convenience method for invoking [ActivityResultHandler.onActivityResult] on a wrapped
* [LifecycleAwareFeature] that implements [ActivityResultHandler]. Returns false if
* the [LifecycleAwareFeature] was cleared already.
diff --git a/mobile/android/android-components/components/support/base/src/test/java/mozilla/components/support/base/android/StartForegroundServiceTest.kt b/mobile/android/android-components/components/support/base/src/test/java/mozilla/components/support/base/android/StartForegroundServiceTest.kt
new file mode 100644
index 0000000000..b583ed055c
--- /dev/null
+++ b/mobile/android/android-components/components/support/base/src/test/java/mozilla/components/support/base/android/StartForegroundServiceTest.kt
@@ -0,0 +1,98 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.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.support.base.android
+
+import android.os.Build
+import org.junit.Assert.assertEquals
+import org.junit.Assert.assertFalse
+import org.junit.Assert.assertTrue
+import org.junit.Test
+
+class StartForegroundServiceTest {
+
+ @Test
+ fun `WHEN build version below S THEN start foreground service should return true regardless of foreground importance`() {
+ val tested = StartForegroundService(
+ FakeProcessInfoProvider(false),
+ FakeBuildVersionProvider(Build.VERSION_CODES.P),
+ FakePowerManagerInfoProvider(false),
+ )
+
+ var isInvoked = false
+ val actual = tested.invoke {
+ isInvoked = true
+ }
+ val expected = true
+
+ assertEquals(expected, actual)
+ assertTrue(isInvoked)
+ }
+
+ @Test
+ fun `WHEN build version is S and above and foreground importance is false THEN start foreground service should return false`() {
+ val tested = StartForegroundService(
+ FakeProcessInfoProvider(false),
+ FakeBuildVersionProvider(Build.VERSION_CODES.S),
+ FakePowerManagerInfoProvider(false),
+ )
+
+ var isInvoked = false
+ val actual = tested.invoke {
+ isInvoked = true
+ }
+
+ assertFalse(actual)
+ assertFalse(isInvoked)
+ }
+
+ @Test
+ fun `WHEN build version is S and above and foreground importance is true THEN start foreground service should return true`() {
+ val tested = StartForegroundService(
+ FakeProcessInfoProvider(true),
+ FakeBuildVersionProvider(Build.VERSION_CODES.S),
+ FakePowerManagerInfoProvider(false),
+ )
+
+ var isInvoked = false
+ val actual = tested.invoke {
+ isInvoked = true
+ }
+
+ assertTrue(actual)
+ assertTrue(isInvoked)
+ }
+
+ @Test
+ fun `WHEN build version is S, foreground importance is false and battery optimisations are disabled THEN start foreground service should return true`() {
+ val tested = StartForegroundService(
+ FakeProcessInfoProvider(false),
+ FakeBuildVersionProvider(Build.VERSION_CODES.S),
+ FakePowerManagerInfoProvider(true),
+ )
+
+ var isInvoked = true
+ val actual = tested.invoke {
+ isInvoked = true
+ }
+
+ assertTrue(actual)
+ assertTrue(isInvoked)
+ }
+
+ class FakeProcessInfoProvider(private val isForegroundImportance: Boolean) :
+ ProcessInfoProvider {
+ override fun isForegroundImportance(): Boolean = isForegroundImportance
+ }
+
+ class FakeBuildVersionProvider(private val sdkInt: Int) : BuildVersionProvider {
+ override fun sdkInt(): Int = sdkInt
+ }
+
+ class FakePowerManagerInfoProvider(
+ private val isIgnoringBatteryOptimizations: Boolean,
+ ) : PowerManagerInfoProvider {
+ override fun isIgnoringBatteryOptimizations(): Boolean = isIgnoringBatteryOptimizations
+ }
+}
diff --git a/mobile/android/android-components/components/support/base/src/test/java/mozilla/components/support/base/feature/ViewBoundFeatureWrapperTest.kt b/mobile/android/android-components/components/support/base/src/test/java/mozilla/components/support/base/feature/ViewBoundFeatureWrapperTest.kt
index a07364acc2..73c71caec8 100644
--- a/mobile/android/android-components/components/support/base/src/test/java/mozilla/components/support/base/feature/ViewBoundFeatureWrapperTest.kt
+++ b/mobile/android/android-components/components/support/base/src/test/java/mozilla/components/support/base/feature/ViewBoundFeatureWrapperTest.kt
@@ -61,6 +61,34 @@ class ViewBoundFeatureWrapperTest {
}
@Test
+ fun `Calling onForwardPressed on an empty wrapper returns false`() {
+ val wrapper = ViewBoundFeatureWrapper<MockFeature>()
+ assertFalse(wrapper.onForwardPressed())
+ }
+
+ @Test
+ fun `onForwardPressed is forwarded to feature`() {
+ val feature = MockFeatureWithUserInteractionHandler(onForwardPressed = true)
+
+ val wrapper = ViewBoundFeatureWrapper(
+ feature = feature,
+ owner = MockedLifecycleOwner(MockedLifecycle(Lifecycle.State.CREATED)),
+ view = mock(),
+ )
+
+ assertTrue(wrapper.onForwardPressed())
+ assertTrue(feature.onForwardPressedInvoked)
+
+ assertFalse(
+ ViewBoundFeatureWrapper(
+ feature = MockFeatureWithUserInteractionHandler(onForwardPressed = false),
+ owner = MockedLifecycleOwner(MockedLifecycle(Lifecycle.State.CREATED)),
+ view = mock(),
+ ).onForwardPressed(),
+ )
+ }
+
+ @Test
fun `Calling onActivityResult on an empty wrapper returns false`() {
val wrapper = ViewBoundFeatureWrapper<MockFeature>()
assertFalse(wrapper.onActivityResult(0, mock(), RESULT_OK))
@@ -350,6 +378,19 @@ class ViewBoundFeatureWrapperTest {
wrapper.onBackPressed()
}
+ @Test(expected = IllegalAccessError::class)
+ fun `onForwardPressed throws if feature does not implement ForwardHandler`() {
+ val feature = MockFeature()
+
+ val wrapper = ViewBoundFeatureWrapper(
+ feature = feature,
+ owner = MockedLifecycleOwner(MockedLifecycle(Lifecycle.State.CREATED)),
+ view = mock(),
+ )
+
+ wrapper.onForwardPressed()
+ }
+
@Test
fun `Setting a feature clears a previously existing feature`() {
val feature = MockFeature()
@@ -434,6 +475,7 @@ private open class MockFeature : LifecycleAwareFeature {
private class MockFeatureWithUserInteractionHandler(
private val onBackPressed: Boolean = false,
+ private val onForwardPressed: Boolean = false,
) : MockFeature(), UserInteractionHandler {
var onBackPressedInvoked = false
private set
@@ -442,6 +484,14 @@ private class MockFeatureWithUserInteractionHandler(
onBackPressedInvoked = true
return onBackPressed
}
+
+ var onForwardPressedInvoked = false
+ private set
+
+ override fun onForwardPressed(): Boolean {
+ onForwardPressedInvoked = true
+ return onForwardPressed
+ }
}
private class MockFeatureWithActivityResultHandler(
diff --git a/mobile/android/android-components/components/support/ktx/src/main/java/mozilla/components/support/ktx/android/view/View.kt b/mobile/android/android-components/components/support/ktx/src/main/java/mozilla/components/support/ktx/android/view/View.kt
index 625eae2c96..1efbb4db83 100644
--- a/mobile/android/android-components/components/support/ktx/src/main/java/mozilla/components/support/ktx/android/view/View.kt
+++ b/mobile/android/android-components/components/support/ktx/src/main/java/mozilla/components/support/ktx/android/view/View.kt
@@ -13,7 +13,6 @@ import android.view.ViewTreeObserver
import android.view.inputmethod.InputMethodManager
import androidx.annotation.MainThread
import androidx.core.content.getSystemService
-import androidx.core.view.ViewCompat
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.MainScope
import kotlinx.coroutines.cancel
@@ -25,13 +24,13 @@ import java.lang.ref.WeakReference
* Is the horizontal layout direction of this view from Right to Left?
*/
val View.isRTL: Boolean
- get() = layoutDirection == ViewCompat.LAYOUT_DIRECTION_RTL
+ get() = layoutDirection == View.LAYOUT_DIRECTION_RTL
/**
* Is the horizontal layout direction of this view from Left to Right?
*/
val View.isLTR: Boolean
- get() = layoutDirection == ViewCompat.LAYOUT_DIRECTION_LTR
+ get() = layoutDirection == View.LAYOUT_DIRECTION_LTR
/**
* Tries to focus this view and show the soft input window for it.
diff --git a/mobile/android/android-components/components/support/ktx/src/main/java/mozilla/components/support/ktx/kotlin/String.kt b/mobile/android/android-components/components/support/ktx/src/main/java/mozilla/components/support/ktx/kotlin/String.kt
index abcd1a741c..8b20bfd1e5 100644
--- a/mobile/android/android-components/components/support/ktx/src/main/java/mozilla/components/support/ktx/kotlin/String.kt
+++ b/mobile/android/android-components/components/support/ktx/src/main/java/mozilla/components/support/ktx/kotlin/String.kt
@@ -307,7 +307,16 @@ fun String.sanitizeFileName(): String {
file.name.replace("\\.\\.+".toRegex(), ".")
} else {
file.name.replace(".", "")
- }
+ }.replaceEscapedCharacters()
+}
+
+/**
+ * Replaces control characters from ASCII 0 to ASCII 19 with '_' so the file name is valid
+ * and is correctly displayed.
+ */
+private fun String.replaceEscapedCharacters(): String {
+ val controlCharactersRegex = "[\\x00-\\x13]".toRegex()
+ return replace(controlCharactersRegex, "_")
}
/**
@@ -330,6 +339,15 @@ fun String.urlEncode(): String {
}
/**
+ * Decodes '%'-escaped octets in the given string using the UTF-8 scheme.
+ * Replaces invalid octets with the unicode replacement character
+ * ("\\uFFFD").
+ *
+ * @see [Uri.decode]
+ */
+fun String.decode(): String = Uri.decode(this)
+
+/**
* Returns the string if it's length is not higher than @param[maximumLength] or
* a @param[replacement] string if String length is higher than @param[maximumLength]
*/
diff --git a/mobile/android/android-components/components/support/ktx/src/test/java/mozilla/components/support/ktx/kotlin/StringTest.kt b/mobile/android/android-components/components/support/ktx/src/test/java/mozilla/components/support/ktx/kotlin/StringTest.kt
index 89ade2aace..eaa9e78c9a 100644
--- a/mobile/android/android-components/components/support/ktx/src/test/java/mozilla/components/support/ktx/kotlin/StringTest.kt
+++ b/mobile/android/android-components/components/support/ktx/src/test/java/mozilla/components/support/ktx/kotlin/StringTest.kt
@@ -181,24 +181,80 @@ class StringTest {
@Test
fun sanitizeFileName() {
- var file = "/../../../../../../../../../../directory/file.......txt"
- val fileName = "file.txt"
-
- assertEquals(fileName, file.sanitizeFileName())
-
- file = "/root/directory/file.txt"
-
- assertEquals(fileName, file.sanitizeFileName())
-
- assertEquals("file", "file".sanitizeFileName())
-
- assertEquals("file", "file..".sanitizeFileName())
-
- assertEquals("file", "file.".sanitizeFileName())
+ val testCases = listOf(
+ "/../../../../../../../../../../directory/file.......txt" to "file.txt",
+ "/root/directory/file.txt" to "file.txt",
+ "file" to "file",
+ "file.." to "file",
+ "file." to "file",
+ ".file" to "file",
+ "test.2020.12.01.txt" to "test.2020.12.01.txt",
+ "\u0000filename" to "_filename",
+ "file\u0001name" to "file_name",
+ "data\u0002stream" to "data_stream",
+ "end\u0003text" to "end_text",
+ "trans\u0004mission" to "trans_mission",
+ "query\u0005result" to "query_result",
+ "acknowledge\u0006signal" to "acknowledge_signal",
+ "bell\u0007sound" to "bell_sound",
+ "back\u0008space" to "back_space",
+ "horizontal\u0009tab" to "horizontal_tab",
+ "new\u000Aline" to "new_line",
+ "vertical\u000Btab" to "vertical_tab",
+ "form\u000Cfeed" to "form_feed",
+ "return\u000Dcarriage" to "return_carriage",
+ "shift\u000Eout" to "shift_out",
+ "shift\u000Fin" to "shift_in",
+ "escape\u0010data" to "escape_data",
+ "device\u0011control1" to "device_control1",
+ "device\u0012control2" to "device_control2",
+ "device\u0013control3" to "device_control3",
+ )
- assertEquals("file", ".file".sanitizeFileName())
+ testCases.forEach { (raw, escaped) ->
+ assertEquals(escaped, raw.sanitizeFileName())
+ }
+ }
+
+ @Test
+ fun `WHEN a string contains utf 8 encoded characters decode decodes it`() {
+ // List of pairs of encoded strings and their expected decoded results
+ val testCases = listOf(
+ "hello%20world" to "hello world",
+ "wow%21amazing" to "wow!amazing",
+ "quote%22here%22" to "quote\"here\"",
+ "hash%23tag" to "hash#tag",
+ "save%24money" to "save\$money",
+ "100%25complete" to "100%complete",
+ "you%26me" to "you&me",
+ "it%27s%20easy" to "it's easy",
+ "open%28now%29" to "open(now)",
+ "star%2Ashine" to "star*shine",
+ "add%2Bmore" to "add+more",
+ "comma%2Cseparated" to "comma,separated",
+ "dash%2Dbetween" to "dash-between",
+ "end%2Eperiod" to "end.period",
+ "path%2Fto%2Ffile" to "path/to/file",
+ "time%3A12%3A00" to "time:12:00",
+ "wait%3Bplease" to "wait;please",
+ "less%3Cthan" to "less<than",
+ "equals%3Dsign" to "equals=sign",
+ "greater%3Ethan" to "greater>than",
+ "what%3Fwhere" to "what?where",
+ "email%40domain.com" to "email@domain.com",
+ "bracket%5Bopen%5D" to "bracket[open]",
+ "escape%5Cbackslash" to "escape\\backslash",
+ "bracket%5Dclose%5D" to "bracket]close]",
+ "high%5Efive" to "high^five",
+ "accent%60grave" to "accent`grave",
+ "brace%7Bopenclose%7D" to "brace{openclose}",
+ "pipe%7Csymbol" to "pipe|symbol",
+ "tilde%7Ewave" to "tilde~wave",
+ )
- assertEquals("test.2020.12.01.txt", "test.2020.12.01.txt".sanitizeFileName())
+ testCases.forEach { (encoded, decoded) ->
+ assertEquals(decoded, encoded.decode())
+ }
}
@Test
diff --git a/mobile/android/android-components/components/support/webextensions/src/main/java/mozilla/components/support/webextensions/WebExtensionSupport.kt b/mobile/android/android-components/components/support/webextensions/src/main/java/mozilla/components/support/webextensions/WebExtensionSupport.kt
index b4b78d6272..3945a2fd06 100644
--- a/mobile/android/android-components/components/support/webextensions/src/main/java/mozilla/components/support/webextensions/WebExtensionSupport.kt
+++ b/mobile/android/android-components/components/support/webextensions/src/main/java/mozilla/components/support/webextensions/WebExtensionSupport.kt
@@ -269,6 +269,10 @@ object WebExtensionSupport {
store.dispatch(WebExtensionAction.UpdateWebExtensionEnabledAction(extension.id, true))
}
+ override fun onOptionalPermissionsChanged(extension: WebExtension) {
+ installedExtensions[extension.id] = extension
+ }
+
override fun onDisabled(extension: WebExtension) {
installedExtensions[extension.id] = extension
store.dispatch(WebExtensionAction.UpdateWebExtensionEnabledAction(extension.id, false))
diff --git a/mobile/android/android-components/components/support/webextensions/src/test/java/mozilla/components/support/webextensions/WebExtensionSupportTest.kt b/mobile/android/android-components/components/support/webextensions/src/test/java/mozilla/components/support/webextensions/WebExtensionSupportTest.kt
index b4e45b3f55..ec61832cef 100644
--- a/mobile/android/android-components/components/support/webextensions/src/test/java/mozilla/components/support/webextensions/WebExtensionSupportTest.kt
+++ b/mobile/android/android-components/components/support/webextensions/src/test/java/mozilla/components/support/webextensions/WebExtensionSupportTest.kt
@@ -598,6 +598,25 @@ class WebExtensionSupportTest {
}
@Test
+ fun `reacts to optional permissions for an extension being changed`() {
+ val store = spy(BrowserStore())
+ val engine: Engine = mock()
+ val ext: WebExtension = mock()
+ whenever(ext.id).thenReturn("extensionId")
+ whenever(ext.url).thenReturn("url")
+
+ val delegateCaptor = argumentCaptor<WebExtensionDelegate>()
+ WebExtensionSupport.initialize(engine, store)
+ verify(engine).registerWebExtensionDelegate(delegateCaptor.capture())
+
+ assertNull(WebExtensionSupport.installedExtensions[ext.id])
+
+ delegateCaptor.value.onOptionalPermissionsChanged(ext)
+
+ assertEquals(ext, WebExtensionSupport.installedExtensions[ext.id])
+ }
+
+ @Test
fun `observes store and registers handlers on new engine sessions`() {
val tab = createTab(id = "1", url = "https://www.mozilla.org")
val customTab = createCustomTab(id = "2", url = "https://www.mozilla.org", source = SessionState.Source.Internal.CustomTab)
diff --git a/mobile/android/android-components/components/ui/autocomplete/src/main/java/mozilla/components/ui/autocomplete/InlineAutocompleteEditText.kt b/mobile/android/android-components/components/ui/autocomplete/src/main/java/mozilla/components/ui/autocomplete/InlineAutocompleteEditText.kt
index c029f226eb..1ae1fe739a 100644
--- a/mobile/android/android-components/components/ui/autocomplete/src/main/java/mozilla/components/ui/autocomplete/InlineAutocompleteEditText.kt
+++ b/mobile/android/android-components/components/ui/autocomplete/src/main/java/mozilla/components/ui/autocomplete/InlineAutocompleteEditText.kt
@@ -182,7 +182,7 @@ open class InlineAutocompleteEditText @JvmOverloads constructor(
return false
}
- if (keyCode == KeyEvent.KEYCODE_ENTER) {
+ if (keyCode == KeyEvent.KEYCODE_ENTER || keyCode == KeyEvent.KEYCODE_NUMPAD_ENTER) {
// If the edit text has a composition string, don't submit the text yet.
// ENTER is needed to commit the composition string.
val content = text
@@ -201,7 +201,7 @@ open class InlineAutocompleteEditText @JvmOverloads constructor(
}
private val onKey = fun (_: View, keyCode: Int, event: KeyEvent): Boolean {
- if (keyCode == KeyEvent.KEYCODE_ENTER) {
+ if (keyCode == KeyEvent.KEYCODE_ENTER || keyCode == KeyEvent.KEYCODE_NUMPAD_ENTER) {
if (event.action != KeyEvent.ACTION_DOWN) {
return true
}
diff --git a/mobile/android/android-components/components/ui/autocomplete/src/test/java/mozilla/components/ui/autocomplete/InlineAutocompleteEditTextTest.kt b/mobile/android/android-components/components/ui/autocomplete/src/test/java/mozilla/components/ui/autocomplete/InlineAutocompleteEditTextTest.kt
index d455b0a28e..bf519e81a1 100644
--- a/mobile/android/android-components/components/ui/autocomplete/src/test/java/mozilla/components/ui/autocomplete/InlineAutocompleteEditTextTest.kt
+++ b/mobile/android/android-components/components/ui/autocomplete/src/test/java/mozilla/components/ui/autocomplete/InlineAutocompleteEditTextTest.kt
@@ -101,8 +101,8 @@ class InlineAutocompleteEditTextTest {
doReturn(false).`when`(et).isShown
doReturn(mock(ViewParent::class.java)).`when`(et).parent
- val event = AccessibilityEvent()
- event.eventType = AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED
+ val event = mock<AccessibilityEvent>()
+ doReturn(AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED).`when`(event).eventType
et.sendAccessibilityEventUnchecked(event)
verify(et).onInitializeAccessibilityEvent(event)
@@ -227,6 +227,17 @@ class InlineAutocompleteEditTextTest {
}
@Test
+ fun `onCommitListenerInvocation with Numpad ENTER`() {
+ val et = InlineAutocompleteEditText(testContext, attributes)
+ var invoked = false
+ et.setOnCommitListener { invoked = true }
+ et.onAttachedToWindow()
+
+ et.dispatchKeyEvent(KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_NUMPAD_ENTER))
+ assertTrue(invoked)
+ }
+
+ @Test
fun onTextChangeListenerInvocation() {
val et = InlineAutocompleteEditText(testContext, attributes)
var invokedWithParams: List<Any>? = null
diff --git a/mobile/android/android-components/components/ui/icons/src/main/res/drawable/mozac_ic_private_mode_circle_fill_20.xml b/mobile/android/android-components/components/ui/icons/src/main/res/drawable/mozac_ic_private_mode_circle_fill_20.xml
index b6ce9a33e8..8c6fc9b212 100644
--- a/mobile/android/android-components/components/ui/icons/src/main/res/drawable/mozac_ic_private_mode_circle_fill_20.xml
+++ b/mobile/android/android-components/components/ui/icons/src/main/res/drawable/mozac_ic_private_mode_circle_fill_20.xml
@@ -2,16 +2,14 @@
- License, v. 2.0. If a copy of the MPL was not distributed with this
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:tools="http://schemas.android.com/tools"
android:width="20dp"
android:height="20dp"
android:viewportWidth="20"
android:viewportHeight="20">
<path
- android:fillColor="?mozac_ic_private_mode_circle_fill_background_color"
- android:pathData="M10,18c-4.411,0 -8,-3.589 -8,-8s3.589,-8 8,-8 8,3.589 8,8 -3.589,8 -8,8z" />
+ android:fillColor="@color/mozac_ui_icons_fill"
+ android:pathData="M7.5,11.148c0.558,0 1.054,-0.25 1.374,-0.637a0.586,0.586 0,0 0,0 -0.726A1.775,1.775 0,0 0,7.5 9.148c-0.558,0 -1.054,0.249 -1.374,0.636a0.587,0.587 0,0 0,0 0.727c0.32,0.388 0.816,0.637 1.374,0.637zM12.5,11.148c0.558,0 1.054,-0.25 1.374,-0.637a0.587,0.587 0,0 0,0 -0.727,1.775 1.775,0 0,0 -1.374,-0.637c-0.558,0 -1.054,0.25 -1.374,0.637a0.587,0.587 0,0 0,0 0.727c0.32,0.388 0.816,0.637 1.374,0.637z" />
<path
- android:fillColor="?mozac_ic_private_mode_circle_fill_icon_color"
- android:pathData="M14.957,8.51a1.02,1.02 0,0 0,-0.793 -1.046,3.714 3.714,0 0,0 -3.351,0.902l-0.154,0.143a0.968,0.968 0,0 1,-1.321 0l-0.15,-0.14a3.712,3.712 0,0 0,-3.354 -0.905c-0.482,0.11 -0.817,0.549 -0.794,1.043v0.003c-0.123,0.488 0.067,2.287 0.175,2.571 0.217,1.144 1.152,2.004 2.272,2.004 0.56,0 1.066,-0.223 1.467,-0.581l0.244,-0.209a1.219,1.219 0,0 1,1.57 -0.012l0.366,0.303v-0.002c0.386,0.31 0.859,0.5 1.377,0.5 1.12,0 2.055,-0.86 2.272,-2.004 0.107,-0.283 0.304,-2.075 0.174,-2.57zM8.874,10.511c-0.32,0.387 -0.816,0.637 -1.374,0.637a1.775,1.775 0,0 1,-1.374 -0.637,0.587 0.587,0 0,1 0,-0.727c0.32,-0.387 0.816,-0.636 1.374,-0.636 0.558,0 1.054,0.249 1.374,0.637a0.586,0.586 0,0 1,0 0.726zM13.874,10.511c-0.32,0.387 -0.816,0.637 -1.374,0.637a1.775,1.775 0,0 1,-1.374 -0.637,0.587 0.587,0 0,1 0,-0.727c0.32,-0.387 0.816,-0.637 1.374,-0.637 0.558,0 1.054,0.249 1.374,0.637a0.587,0.587 0,0 1,0 0.727z"
- tools:ignore="VectorPath" />
+ android:fillColor="@color/mozac_ui_icons_fill"
+ android:pathData="M2,10c0,4.411 3.589,8 8,8s8,-3.589 8,-8 -3.589,-8 -8,-8 -8,3.589 -8,8zM14.164,7.464c0.483,0.109 0.818,0.551 0.793,1.046 0.13,0.495 -0.067,2.287 -0.174,2.57 -0.217,1.144 -1.152,2.004 -2.272,2.004a2.19,2.19 0,0 1,-1.377 -0.5v0.002l-0.366,-0.303a1.219,1.219 0,0 0,-1.57 0.012l-0.244,0.209a2.194,2.194 0,0 1,-1.467 0.58c-1.12,0 -2.055,-0.86 -2.272,-2.003 -0.108,-0.284 -0.298,-2.083 -0.175,-2.571v-0.003a1.022,1.022 0,0 1,0.794 -1.043,3.712 3.712,0 0,1 3.354,0.905l0.15,0.14a0.972,0.972 0,0 0,1.321 0l0.154,-0.143a3.714,3.714 0,0 1,3.351 -0.902z" />
</vector>
diff --git a/mobile/android/android-components/components/ui/icons/src/main/res/drawable/mozac_ic_private_mode_circle_fill_24.xml b/mobile/android/android-components/components/ui/icons/src/main/res/drawable/mozac_ic_private_mode_circle_fill_24.xml
index bcb350e8fd..995a646e66 100644
--- a/mobile/android/android-components/components/ui/icons/src/main/res/drawable/mozac_ic_private_mode_circle_fill_24.xml
+++ b/mobile/android/android-components/components/ui/icons/src/main/res/drawable/mozac_ic_private_mode_circle_fill_24.xml
@@ -2,16 +2,14 @@
- License, v. 2.0. If a copy of the MPL was not distributed with this
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:tools="http://schemas.android.com/tools"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
- android:fillColor="?mozac_ic_private_mode_circle_fill_background_color"
- android:pathData="M12,22C6.486,22 2,17.514 2,12S6.486,2 12,2s10,4.486 10,10 -4.486,10 -10,10z" />
+ android:fillColor="@color/mozac_ui_icons_fill"
+ android:pathData="M9,13.267c0.65,0 1.23,-0.291 1.603,-0.743a0.685,0.685 0,0 0,0 -0.848A2.072,2.072 0,0 0,9 10.933c-0.651,0 -1.23,0.291 -1.603,0.743a0.685,0.685 0,0 0,0 0.848c0.373,0.452 0.952,0.743 1.603,0.743zM15,13.267c0.651,0 1.23,-0.291 1.603,-0.743a0.685,0.685 0,0 0,0 -0.848A2.072,2.072 0,0 0,15 10.933c-0.651,0 -1.23,0.291 -1.603,0.743a0.685,0.685 0,0 0,0 0.848c0.373,0.452 0.952,0.743 1.603,0.743z" />
<path
- android:fillColor="?mozac_ic_private_mode_circle_fill_icon_color"
- android:pathData="M18.196,10.053a1.275,1.275 0,0 0,-0.992 -1.308,4.642 4.642,0 0,0 -4.189,1.127l-0.192,0.179a1.208,1.208 0,0 1,-1.651 -0.001l-0.188,-0.175a4.643,4.643 0,0 0,-4.192 -1.13,1.277 1.277,0 0,0 -0.992,1.304v0.004c-0.154,0.609 0.084,2.859 0.219,3.213 0.271,1.429 1.439,2.505 2.84,2.505 0.699,0 1.332,-0.279 1.833,-0.726l0.305,-0.261a1.524,1.524 0,0 1,1.962 -0.016l0.458,0.379v-0.002a2.734,2.734 0,0 0,1.72 0.626c1.4,0 2.569,-1.075 2.841,-2.505 0.134,-0.354 0.38,-2.594 0.218,-3.213zM10.603,12.524A2.072,2.072 0,0 1,9 13.267c-0.651,0 -1.23,-0.291 -1.603,-0.743a0.685,0.685 0,0 1,0 -0.848A2.072,2.072 0,0 1,9 10.933c0.65,0 1.23,0.291 1.603,0.743a0.685,0.685 0,0 1,0 0.848zM16.603,12.524a2.072,2.072 0,0 1,-1.603 0.743c-0.651,0 -1.23,-0.291 -1.603,-0.743a0.685,0.685 0,0 1,0 -0.848A2.072,2.072 0,0 1,15 10.933c0.651,0 1.23,0.291 1.603,0.743a0.685,0.685 0,0 1,0 0.848z"
- tools:ignore="VectorPath" />
+ android:fillColor="@color/mozac_ui_icons_fill"
+ android:pathData="M2,12c0,5.514 4.486,10 10,10s10,-4.486 10,-10S17.514,2 12,2 2,6.486 2,12zM17.204,8.745c0.605,0.137 1.023,0.689 0.992,1.308 0.163,0.619 -0.084,2.859 -0.218,3.213 -0.272,1.43 -1.44,2.505 -2.84,2.505a2.733,2.733 0,0 1,-1.721 -0.626v0.002l-0.458,-0.379a1.524,1.524 0,0 0,-1.962 0.016l-0.305,0.261c-0.501,0.447 -1.134,0.726 -1.833,0.726 -1.401,0 -2.569,-1.076 -2.84,-2.505 -0.135,-0.354 -0.373,-2.604 -0.22,-3.213v-0.004a1.277,1.277 0,0 1,0.993 -1.304,4.643 4.643,0 0,1 4.192,1.13l0.188,0.175a1.21,1.21 0,0 0,1.651 0.001l0.192,-0.179a4.642,4.642 0,0 1,4.189 -1.127z" />
</vector>
diff --git a/mobile/android/android-components/components/ui/icons/src/main/res/values/attrs.xml b/mobile/android/android-components/components/ui/icons/src/main/res/values/attrs.xml
index c41244c9c1..3fa2851901 100644
--- a/mobile/android/android-components/components/ui/icons/src/main/res/values/attrs.xml
+++ b/mobile/android/android-components/components/ui/icons/src/main/res/values/attrs.xml
@@ -3,10 +3,8 @@
- License, v. 2.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>
- <!-- Background color for mozac_ic_private_mode_circle_fill_20,
- mozac_ic_private_mode_circle_fill_24 and mozac_ic_private_mode_circle_fill_48 -->
+ <!-- Background color for mozac_ic_private_mode_circle_fill_48 -->
<attr name="mozac_ic_private_mode_circle_fill_background_color" format="reference" />
- <!-- Icon color for mozac_ic_private_mode_circle_fill_20,
- mozac_ic_private_mode_circle_fill_24 and mozac_ic_private_mode_circle_fill_48 -->
+ <!-- Icon color for mozac_ic_private_mode_circle_fill_48 -->
<attr name="mozac_ic_private_mode_circle_fill_icon_color" format="reference" />
</resources>
diff --git a/mobile/android/android-components/components/ui/widgets/src/test/java/mozilla/components/ui/widgets/behavior/EngineViewScrollingBehaviorTest.kt b/mobile/android/android-components/components/ui/widgets/src/test/java/mozilla/components/ui/widgets/behavior/EngineViewScrollingBehaviorTest.kt
index 0f0c10b71a..d00b657f10 100644
--- a/mobile/android/android-components/components/ui/widgets/src/test/java/mozilla/components/ui/widgets/behavior/EngineViewScrollingBehaviorTest.kt
+++ b/mobile/android/android-components/components/ui/widgets/src/test/java/mozilla/components/ui/widgets/behavior/EngineViewScrollingBehaviorTest.kt
@@ -534,7 +534,7 @@ class EngineViewScrollingBehaviorTest {
}
val behavior = spy(EngineViewScrollingBehavior(testContext, null, ViewPosition.BOTTOM))
- behavior.onLayoutChild(container, view, ViewCompat.LAYOUT_DIRECTION_LTR)
+ behavior.onLayoutChild(container, view, View.LAYOUT_DIRECTION_LTR)
assertEquals(view, behavior.dynamicScrollView)
assertEquals(engineView, behavior.engineView)
diff --git a/mobile/android/android-components/config/detekt-baseline.xml b/mobile/android/android-components/config/detekt-baseline.xml
index e779572390..1e583de30b 100644
--- a/mobile/android/android-components/config/detekt-baseline.xml
+++ b/mobile/android/android-components/config/detekt-baseline.xml
@@ -307,6 +307,7 @@
<ID>UndocumentedPublicFunction:Types.kt$fun AccountEvent.into(): mozilla.components.concept.sync.AccountEvent</ID>
<ID>UndocumentedPublicFunction:Types.kt$fun Device.into(): mozilla.components.concept.sync.Device</ID>
<ID>UndocumentedPublicFunction:Types.kt$fun IncomingDeviceCommand.TabReceived.into(): mozilla.components.concept.sync.DeviceCommandIncoming.TabReceived</ID>
+ <ID>UndocumentedPublicFunction:Types.kt$fun IncomingDeviceCommand.TabsClosed.into(): mozilla.components.concept.sync.DeviceCommandIncoming.TabsClosed</ID>
<ID>UndocumentedPublicFunction:Types.kt$fun IncomingDeviceCommand.into(): mozilla.components.concept.sync.DeviceCommandIncoming</ID>
<ID>UndocumentedPublicFunction:Types.kt$fun Profile.into(): mozilla.components.concept.sync.Profile</ID>
<ID>UndocumentedPublicFunction:Types.kt$fun ScopedKey.into(): OAuthScopedKey</ID>
diff --git a/mobile/android/android-components/docs/_includes/header.html b/mobile/android/android-components/docs/_includes/header.html
index 7a989f7de9..b32fc0298d 100644
--- a/mobile/android/android-components/docs/_includes/header.html
+++ b/mobile/android/android-components/docs/_includes/header.html
@@ -2,22 +2,24 @@
<div class="wrapper">
<a class="site-title" rel="author" href="/">Mozilla Android Components</a>
- <nav class="site-nav">
- <input type="checkbox" id="nav-trigger" class="nav-trigger" />
- <label for="nav-trigger">
- <span class="menu-icon">
- <svg viewBox="0 0 18 15" width="18px" height="15px">
- <path d="M18,1.484c0,0.82-0.665,1.484-1.484,1.484H1.484C0.665,2.969,0,2.304,0,1.484l0,0C0,0.665,0.665,0,1.484,0 h15.032C17.335,0,18,0.665,18,1.484L18,1.484z M18,7.516C18,8.335,17.335,9,16.516,9H1.484C0.665,9,0,8.335,0,7.516l0,0 c0-0.82,0.665-1.484,1.484-1.484h15.032C17.335,6.031,18,6.696,18,7.516L18,7.516z M18,13.516C18,14.335,17.335,15,16.516,15H1.484 C0.665,15,0,14.335,0,13.516l0,0c0-0.82,0.665-1.483,1.484-1.483h15.032C17.335,12.031,18,12.695,18,13.516L18,13.516z"/>
- </svg>
- </span>
- </label>
+ <nav class="site-nav">
+ <input type="checkbox" id="nav-trigger" class="nav-trigger" />
+ <label for="nav-trigger">
+ <span class="menu-icon">
+ <svg viewBox="0 0 18 15" width="18px" height="15px">
+ <path
+ d="M18,1.484c0,0.82-0.665,1.484-1.484,1.484H1.484C0.665,2.969,0,2.304,0,1.484l0,0C0,0.665,0.665,0,1.484,0 h15.032C17.335,0,18,0.665,18,1.484L18,1.484z M18,7.516C18,8.335,17.335,9,16.516,9H1.484C0.665,9,0,8.335,0,7.516l0,0 c0-0.82,0.665-1.484,1.484-1.484h15.032C17.335,6.031,18,6.696,18,7.516L18,7.516z M18,13.516C18,14.335,17.335,15,16.516,15H1.484 C0.665,15,0,14.335,0,13.516l0,0c0-0.82,0.665-1.483,1.484-1.483h15.032C17.335,12.031,18,12.695,18,13.516L18,13.516z"
+ />
+ </svg>
+ </span>
+ </label>
- <div class="trigger">
- <a class="page-link" href="/components/">Components</a>
- <a class="page-link" href="/changelog/">Changelog</a>
- <a class="page-link" href="/blog/">Blog</a>
- <a class="page-link" href="/contributing/">Contributing</a>
- </div>
- </nav>
+ <div class="trigger">
+ <a class="page-link" href="/components/">Components</a>
+ <a class="page-link" href="/changelog/">Changelog</a>
+ <a class="page-link" href="/blog/">Blog</a>
+ <a class="page-link" href="/contributing/">Contributing</a>
+ </div>
+ </nav>
</div>
</header>
diff --git a/mobile/android/android-components/docs/_includes/post_detail.html b/mobile/android/android-components/docs/_includes/post_detail.html
index bceb37d5bc..2cb5a8a9cd 100644
--- a/mobile/android/android-components/docs/_includes/post_detail.html
+++ b/mobile/android/android-components/docs/_includes/post_detail.html
@@ -1,16 +1,16 @@
<h1 class="entry-title">
- <!--<a href="{{ root_url }}{{ page.url }}">{{ page.title }}</a>-->
+ <!--<a href="{{ root_url }}{{ page.url }}">{{ page.title }}</a>-->
</h1>
<ul>
- {% if post.title %}
- <li>
- {{ post.date | date: '%B %d, %Y' }}
- <br/>
- {% if post.external_url %}
- <a href="{{ post.external_url }}">{{ post.title | escape }}</a>
- {% else %}
- <a href="{{ post.url | relative_url }}">{{ post.title | escape }}</a>
- {% endif %}
- </li>
+ {% if post.title %}
+ <li>
+ {{ post.date | date: '%B %d, %Y' }}
+ <br />
+ {% if post.external_url %}
+ <a href="{{ post.external_url }}">{{ post.title | escape }}</a>
+ {% else %}
+ <a href="{{ post.url | relative_url }}">{{ post.title | escape }}</a>
{% endif %}
+ </li>
+ {% endif %}
</ul>
diff --git a/mobile/android/android-components/docs/_layouts/post.html b/mobile/android/android-components/docs/_layouts/post.html
index 29f841f336..cf3d23a3c5 100644
--- a/mobile/android/android-components/docs/_layouts/post.html
+++ b/mobile/android/android-components/docs/_layouts/post.html
@@ -1,38 +1,53 @@
---
layout: default
---
-<article class="post h-entry" itemscope itemtype="http://schema.org/BlogPosting">
+<article
+ class="post h-entry"
+ itemscope
+ itemtype="http://schema.org/BlogPosting"
+>
<header class="post-header">
- <h1 class="post-title p-name" itemprop="name headline">{{ page.title | escape }}</h1>
+ <h1 class="post-title p-name" itemprop="name headline">
+ {{ page.title | escape }}
+ </h1>
<p class="post-meta">
- <time class="dt-published" datetime="{{ page.date | date_to_xmlschema }}" itemprop="datePublished">
- {%- assign date_format = site.minima.date_format | default: "%b %-d, %Y" -%}
- {{ page.date | date: date_format }}
+ <time
+ class="dt-published"
+ datetime="{{ page.date | date_to_xmlschema }}"
+ itemprop="datePublished"
+ >
+ {%- assign date_format = site.minima.date_format | default: "%b %-d, %Y"
+ -%} {{ page.date | date: date_format }}
</time>
- {%- if page.author -%}
- -
- {% assign author = site.data.authors[page.author] %}
- <span itemprop="author" itemscope itemtype="http://schema.org/Person">
- <span class="p-author h-card" itemprop="name">
- <img src="{{ author.image }}" width="20" height="20" style="margin:5px;" />
- {{ author.name }}
- {%- if author.twitter -%}
- <a href="{{ author.twitter }}"><svg class="svg-icon" style="margin-left:10px;"><use xlink:href="{{ '/assets/minima-social-icons.svg#twitter' | relative_url }}"></use></svg></a>
- {%- endif -%}
- </span>
- </span>
+ {%- if page.author -%} - {% assign author = site.data.authors[page.author]
+ %}
+ <span itemprop="author" itemscope itemtype="http://schema.org/Person">
+ <span class="p-author h-card" itemprop="name">
+ <img
+ src="{{ author.image }}"
+ width="20"
+ height="20"
+ style="margin: 5px"
+ />
+ {{ author.name }} {%- if author.twitter -%}
+ <a href="{{ author.twitter }}"
+ ><svg class="svg-icon" style="margin-left: 10px">
+ <use
+ xlink:href="{{ '/assets/minima-social-icons.svg#twitter' | relative_url }}"
+ ></use></svg
+ ></a>
+ {%- endif -%}
+ </span>
+ </span>
{%- endif -%}
</p>
</header>
- <div class="post-content e-content" itemprop="articleBody">
- {{ content }}
- </div>
+ <div class="post-content e-content" itemprop="articleBody">{{ content }}</div>
- {%- if site.disqus.shortname -%}
- {%- include disqus_comments.html -%}
- {%- endif -%}
+ {%- if site.disqus.shortname -%} {%- include disqus_comments.html -%} {%-
+ endif -%}
<a class="u-url" href="{{ page.url | relative_url }}" hidden></a>
</article>
diff --git a/mobile/android/android-components/docs/assets/js/icon-js.js b/mobile/android/android-components/docs/assets/js/icon-js.js
index 6c5ca1a226..41ace3daf7 100644
--- a/mobile/android/android-components/docs/assets/js/icon-js.js
+++ b/mobile/android/android-components/docs/assets/js/icon-js.js
@@ -3,11 +3,11 @@
* @return {Element}
*/
function htmlToElement(html) {
- let template = document.createElement('template');
- html = html.trim(); // Never return a text node of whitespace as the result
- template.innerHTML = html;
- //firstChild may be a comment so we must use firstElementChild to avoid picking it
- return template.content.firstElementChild;
+ let template = document.createElement("template");
+ html = html.trim(); // Never return a text node of whitespace as the result
+ template.innerHTML = html;
+ //firstChild may be a comment so we must use firstElementChild to avoid picking it
+ return template.content.firstElementChild;
}
/**
@@ -17,81 +17,90 @@ function htmlToElement(html) {
* @returns {String} The same string but in the standard SVG representation
*/
function androidSVGtoNormalSVG(s) {
- s = s.replace(/<\?xml version="1\.0" encoding="utf-8"\?>/g, '');
- s = s.replace(/<vector xmlns:android="http:\/\/schemas.android.com\/apk\/res\/android"/g, '<svg xmlns="http://www.w3.org/2000/svg"');
- s = s.replace(/<\/vector>/g, '</svg>');
- s = s.replace(/android:(height|width)="(\d+)dp"/g, '');
- s = s.replace(/android:viewportHeight="(\d+\.?\d+)"/g, 'height="$1"');
- s = s.replace(/android:viewportWidth="(\d+\.?\d+)"/g, 'width="$1"');
- s = s.replace(/android:fillColor=/g, 'fill=');
- s = s.replace(/android:pathData=/g, 'd=');
- //s = s.replace(/android:/g, '');
- return s;
+ s = s.replace(/<\?xml version="1\.0" encoding="utf-8"\?>/g, "");
+ s = s.replace(
+ /<vector xmlns:android="http:\/\/schemas.android.com\/apk\/res\/android"/g,
+ '<svg xmlns="http://www.w3.org/2000/svg"'
+ );
+ s = s.replace(/<\/vector>/g, "</svg>");
+ s = s.replace(/android:(height|width)="(\d+)dp"/g, "");
+ s = s.replace(/android:viewportHeight="(\d+\.?\d+)"/g, 'height="$1"');
+ s = s.replace(/android:viewportWidth="(\d+\.?\d+)"/g, 'width="$1"');
+ s = s.replace(/android:fillColor=/g, "fill=");
+ s = s.replace(/android:pathData=/g, "d=");
+ //s = s.replace(/android:/g, '');
+ return s;
}
function addToTable(name, svg) {
- let table = document.querySelector("#preview_table > tbody");
- let row = htmlToElement("<tr></tr>");
- row.appendChild(htmlToElement("<td>" + name + "</td>"));
- let td = htmlToElement("<td></td>");
- td.appendChild(svg);
- row.appendChild(td);
- table.appendChild(row);
+ let table = document.querySelector("#preview_table > tbody");
+ let row = htmlToElement("<tr></tr>");
+ row.appendChild(htmlToElement("<td>" + name + "</td>"));
+ let td = htmlToElement("<td></td>");
+ td.appendChild(svg);
+ row.appendChild(td);
+ table.appendChild(row);
}
function addSingleItemToTable(str) {
- let table = document.querySelector("#preview_table > tbody");
- table.append(htmlToElement("<tr><td colspan='2'>" + str + "</td></tr>"))
+ let table = document.querySelector("#preview_table > tbody");
+ table.append(htmlToElement("<tr><td colspan='2'>" + str + "</td></tr>"));
}
function getFile(iconName, downloadUrl) {
- return new Promise((resolve, reject) => {
- let request = new XMLHttpRequest();
- request.open('GET', downloadUrl, true);
- request.onreadystatechange = function () {
- if (request.readyState === 4 && request.status === 200) {
- let androidXmlText = request.responseText;
- androidXmlText = androidSVGtoNormalSVG(androidXmlText);
- resolve([iconName, androidXmlText]);
- } else if (request.readyState === 4) {
- //Request completed with an error
- resolve([iconName, "<span>Error during download</span>"]);
- }
- };
- request.send(null);
- });
-
+ return new Promise((resolve, reject) => {
+ let request = new XMLHttpRequest();
+ request.open("GET", downloadUrl, true);
+ request.onreadystatechange = function () {
+ if (request.readyState === 4 && request.status === 200) {
+ let androidXmlText = request.responseText;
+ androidXmlText = androidSVGtoNormalSVG(androidXmlText);
+ resolve([iconName, androidXmlText]);
+ } else if (request.readyState === 4) {
+ //Request completed with an error
+ resolve([iconName, "<span>Error during download</span>"]);
+ }
+ };
+ request.send(null);
+ });
}
// This function recovers all icons inside the drawable folder via github API
(function getIcons() {
- let request = new XMLHttpRequest();
- request.open("GET", "https://api.github.com/repos/mozilla-mobile/android-components/contents/components/ui/icons/src/main/res/drawable", true);
- //Explicit request of the V3 version of the API
- request.setRequestHeader("Accept", "application/vnd.github.v3+json");
- request.onreadystatechange = function () {
- if (request.readyState === XMLHttpRequest.DONE && request.status === 200) {
- let response = JSON.parse(request.response);
- if (response.message) {
- //Something went wrong
- addSingleItemToTable("Error: " + response.message);
- return;
- }
- addSingleItemToTable("Loading");
- let promises = [];
- for (let i = 0; i < response.length; i++) {
- let iconName = response[i]['name'].substr(0, response[i]['name'].length - 4);
- promises.push(getFile(iconName, response[i]['download_url']));
- }
- Promise.all(promises).then((values) => {
- document.querySelector("#preview_table > tbody").innerHTML = "";
- for (let i = 0; i < values.length; i++) {
- let name = values[i][0], svg = values[i][1];
- addToTable(name, htmlToElement(svg));
- }
- });
+ let request = new XMLHttpRequest();
+ request.open(
+ "GET",
+ "https://api.github.com/repos/mozilla-mobile/android-components/contents/components/ui/icons/src/main/res/drawable",
+ true
+ );
+ //Explicit request of the V3 version of the API
+ request.setRequestHeader("Accept", "application/vnd.github.v3+json");
+ request.onreadystatechange = function () {
+ if (request.readyState === XMLHttpRequest.DONE && request.status === 200) {
+ let response = JSON.parse(request.response);
+ if (response.message) {
+ //Something went wrong
+ addSingleItemToTable("Error: " + response.message);
+ return;
+ }
+ addSingleItemToTable("Loading");
+ let promises = [];
+ for (let i = 0; i < response.length; i++) {
+ let iconName = response[i]["name"].substr(
+ 0,
+ response[i]["name"].length - 4
+ );
+ promises.push(getFile(iconName, response[i]["download_url"]));
+ }
+ Promise.all(promises).then(values => {
+ document.querySelector("#preview_table > tbody").innerHTML = "";
+ for (let i = 0; i < values.length; i++) {
+ let name = values[i][0],
+ svg = values[i][1];
+ addToTable(name, htmlToElement(svg));
}
- };
- request.send(null);
+ });
+ }
+ };
+ request.send(null);
})();
-
diff --git a/mobile/android/android-components/docs/changelog.md b/mobile/android/android-components/docs/changelog.md
index 6dce7f4966..d14bbca8c8 100644
--- a/mobile/android/android-components/docs/changelog.md
+++ b/mobile/android/android-components/docs/changelog.md
@@ -4,7 +4,32 @@ title: Changelog
permalink: /changelog/
---
-# 126.0 (In Development)
+# 127.0 (In Development)
+
+* **feature-prompts** **browser-storage-sync**
+ * A new `isLoginAutofillEnabled` callback is available in `PromptFeature` and `GeckoLoginStorageDelegate` to allow clients controlling whether saved logins should be autofilled or not. Default is false
+
+* **browser-state**
+ * Added `TabSessionState.getUrl()` extension function that will return the URL that could be
+ used for various features such as bookmarks or share regardless of the mode the browser is in (e.g. Reader mode). [Bug 1885628](https://bugzilla.mozilla.org/show_bug.cgi?id=1885628).
+
+* **support-base**
+ * Added `StartForegroundService` to safely start a foreground service, see [Bug 1839039](https://bugzilla.mozilla.org/show_bug.cgi?id=1839039) for crash reference.
+ * Added `ProcessInfoProvider` and `BuildVersionProvider` to get information about the app process and the build version.
+
+* **browser-engine-gecko**
+ * For screenshot capture, include exception in failure result rather than throwing.
+
+* **feature-accounts-push**
+ * 🆕 New `CloseTabsFeature` for closing tabs on this device from other devices that are signed to the same Mozilla account.
+ * 🆕 New `CloseTabsUseCase` for closing tabs on other devices from this device.
+
+* **concept-sync**
+ * 🆕 New `DeviceCapability.CLOSE_TABS` variant to indicate that a device supports closing synced tabs.
+ * 🆕 New `DeviceCommandIncoming.TabsClosed` variant to represent a "close synced tabs" command received from another device.
+ * 🆕 New `DeviceCommandOutgoing.CloseTab` variant to represent a "close synced tabs" sent to another device.
+
+# 126.0
* **browser-menu**
* Added enabled state to `BrowserMenuImageText`, see [Bug 1884769](https://bugzilla.mozilla.org/show_bug.cgi?id=1884769).
diff --git a/mobile/android/android-components/gradle/wrapper/gradle-wrapper.properties b/mobile/android/android-components/gradle/wrapper/gradle-wrapper.properties
index b82aa23a4f..23e87f9b0b 100644
--- a/mobile/android/android-components/gradle/wrapper/gradle-wrapper.properties
+++ b/mobile/android/android-components/gradle/wrapper/gradle-wrapper.properties
@@ -1,3 +1,7 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-bin.zip
diff --git a/mobile/android/android-components/plugins/dependencies/src/main/java/ApplicationServices.kt b/mobile/android/android-components/plugins/dependencies/src/main/java/ApplicationServices.kt
index 5476c263fe..bcac9abb74 100644
--- a/mobile/android/android-components/plugins/dependencies/src/main/java/ApplicationServices.kt
+++ b/mobile/android/android-components/plugins/dependencies/src/main/java/ApplicationServices.kt
@@ -3,7 +3,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
// These lines are generated by android-components/automation/application-services-nightly-bump.py
-val VERSION = "126.0"
+val VERSION = "127.0"
val CHANNEL = ApplicationServicesChannel.RELEASE
object ApplicationServicesConfig {
diff --git a/mobile/android/android-components/plugins/dependencies/src/main/java/DependenciesPlugin.kt b/mobile/android/android-components/plugins/dependencies/src/main/java/DependenciesPlugin.kt
index 0dbc6cf837..17fe0dbeaf 100644
--- a/mobile/android/android-components/plugins/dependencies/src/main/java/DependenciesPlugin.kt
+++ b/mobile/android/android-components/plugins/dependencies/src/main/java/DependenciesPlugin.kt
@@ -6,7 +6,7 @@ import org.gradle.api.Plugin
import org.gradle.api.initialization.Settings
// If you ever need to force a toolchain rebuild (taskcluster) then edit the following comment.
-// FORCE REBUILD 2023-05-24
+// FORCE REBUILD 2024-05-02
class DependenciesPlugin : Plugin<Settings> {
override fun apply(settings: Settings) = Unit
@@ -19,10 +19,10 @@ object Versions {
const val serialization = "1.6.3"
const val python_envs_plugin = "0.0.31"
- const val mozilla_glean = "59.0.0"
+ const val mozilla_glean = "60.0.1"
const val junit = "4.13.2"
- const val robolectric = "4.11.1"
+ const val robolectric = "4.12.1"
const val mockito = "5.11.0"
const val maven_ant_tasks = "2.1.3"
const val jacoco = "0.8.11"
@@ -38,20 +38,20 @@ object Versions {
const val detekt = "1.23.6"
const val ktlint = "0.49.1"
- const val sentry = "7.5.0"
+ const val sentry = "7.8.0"
const val zxing = "3.5.3"
const val disklrucache = "2.0.2"
- const val leakcanary = "2.13"
+ const val leakcanary = "2.14"
const val material = "1.9.0"
- const val ksp = "1.0.19"
+ const val ksp = "1.0.20"
val ksp_plugin = "$kotlin-$ksp"
// see https://android-developers.googleblog.com/2022/06/independent-versioning-of-Jetpack-Compose-libraries.html
// for Jetpack Compose libraries versioning
- const val compose_compiler = "1.5.11"
+ const val compose_compiler = "1.5.13"
object AndroidX {
const val activityCompose = "1.7.2"
@@ -61,10 +61,11 @@ object Versions {
const val browser = "1.8.0"
const val biometric = "1.1.0"
const val cardview = "1.0.0"
- const val compose_bom = "2024.04.01"
+ const val collection = "1.4.0"
+ const val compose_bom = "2024.05.00"
const val constraintlayout = "2.1.4"
const val coordinatorlayout = "1.2.0"
- const val core = "1.12.0"
+ const val core = "1.13.1"
const val drawerlayout = "1.2.0"
const val fragment = "1.6.2"
const val recyclerview = "1.3.2"
@@ -85,12 +86,14 @@ object Versions {
const val uiautomator = "2.3.0"
const val localbroadcastmanager = "1.0.0"
const val swiperefreshlayout = "1.1.0"
- const val data_store_preferences="1.0.0"
+ const val datastore="1.1.1"
}
object Firebase {
- const val messaging = "23.4.1"
+ const val messaging = "24.0.0"
}
+
+ const val play_services = "18.4.0"
}
// Synchronized dependencies used by (some) modules
@@ -117,6 +120,7 @@ object ComponentsDependencies {
const val androidx_biometric = "androidx.biometric:biometric:${Versions.AndroidX.biometric}"
const val androidx_browser = "androidx.browser:browser:${Versions.AndroidX.browser}"
const val androidx_cardview = "androidx.cardview:cardview:${Versions.AndroidX.cardview}"
+ const val androidx_collection = "androidx.collection:collection:${Versions.AndroidX.collection}"
const val androidx_compose_bom = "androidx.compose:compose-bom:${Versions.AndroidX.compose_bom}"
const val androidx_compose_animation = "androidx.compose.animation:animation"
@@ -165,7 +169,8 @@ object ComponentsDependencies {
const val androidx_espresso_core = "androidx.test.espresso:espresso-core:${Versions.AndroidX.espresso}"
const val androidx_localbroadcastmanager = "androidx.localbroadcastmanager:localbroadcastmanager:${Versions.AndroidX.localbroadcastmanager}"
const val androidx_swiperefreshlayout = "androidx.swiperefreshlayout:swiperefreshlayout:${Versions.AndroidX.swiperefreshlayout}"
- const val androidx_data_store_preferences = "androidx.datastore:datastore-preferences:${Versions.AndroidX.data_store_preferences}"
+ const val androidx_datastore = "androidx.datastore:datastore:${Versions.AndroidX.datastore}"
+ const val androidx_datastore_preferences = "androidx.datastore:datastore-preferences:${Versions.AndroidX.datastore}"
const val google_material = "com.google.android.material:material:${Versions.material}"
@@ -212,4 +217,6 @@ object ComponentsDependencies {
const val thirdparty_androidsvg = "com.caverock:androidsvg-aar:${Versions.androidsvg}"
const val firebase_messaging = "com.google.firebase:firebase-messaging:${Versions.Firebase.messaging}"
+
+ const val play_services_base = "com.google.android.gms:play-services-base:${Versions.play_services}"
}
diff --git a/mobile/android/android-components/plugins/dependencies/src/main/java/moz.yaml b/mobile/android/android-components/plugins/dependencies/src/main/java/moz.yaml
index c0d1433487..d493398ae3 100644
--- a/mobile/android/android-components/plugins/dependencies/src/main/java/moz.yaml
+++ b/mobile/android/android-components/plugins/dependencies/src/main/java/moz.yaml
@@ -31,11 +31,11 @@ origin:
# Human-readable identifier for this version/release
# Generally "version NNN", "tag SSS", "bookmark SSS"
- release: 2550d98ec22599dd1b1d45915ad5b119d1b7d64c (2024-04-10T05:03:14).
+ release: 74b4b850d93c1ec7b305042fb6c3f44712767f3d (2024-05-11T05:02:41).
# Revision to pull in
# Must be a long or short commit SHA (long preferred)
- revision: 2550d98ec22599dd1b1d45915ad5b119d1b7d64c
+ revision: 74b4b850d93c1ec7b305042fb6c3f44712767f3d
# The package's license, where possible using the mnemonic from
# https://spdx.org/licenses/
diff --git a/mobile/android/android-components/samples/browser/src/androidTest/assets/index.html b/mobile/android/android-components/samples/browser/src/androidTest/assets/index.html
index 9f5632c044..1b7817eef2 100644
--- a/mobile/android/android-components/samples/browser/src/androidTest/assets/index.html
+++ b/mobile/android/android-components/samples/browser/src/androidTest/assets/index.html
@@ -1,5 +1,5 @@
<html>
-<body>
-<h1 id="website_title">Hello World!</h1>
-</body>
+ <body>
+ <h1 id="website_title">Hello World!</h1>
+ </body>
</html>
diff --git a/mobile/android/android-components/samples/browser/src/main/assets/extensions/borderify/borderify.js b/mobile/android/android-components/samples/browser/src/main/assets/extensions/borderify/borderify.js
index af58957d88..b9a5d6bc18 100644
--- a/mobile/android/android-components/samples/browser/src/main/assets/extensions/borderify/borderify.js
+++ b/mobile/android/android-components/samples/browser/src/main/assets/extensions/borderify/borderify.js
@@ -2,4 +2,4 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-document.body.style.border = "5px solid red"; \ No newline at end of file
+document.body.style.border = "5px solid red";
diff --git a/mobile/android/android-components/samples/browser/src/main/assets/extensions/test/background.js b/mobile/android/android-components/samples/browser/src/main/assets/extensions/test/background.js
index 950936be4c..f3ee460d9b 100644
--- a/mobile/android/android-components/samples/browser/src/main/assets/extensions/test/background.js
+++ b/mobile/android/android-components/samples/browser/src/main/assets/extensions/test/background.js
@@ -6,7 +6,7 @@
* inadvertently match elements in the article content. */
// Counts to three and sends a greeting via the browser action of a newly created tab.
-browser.tabs.onCreated.addListener((tab) => {
+browser.tabs.onCreated.addListener(tab => {
let counter = 0;
let intervalId = setInterval(() => {
var message;
@@ -16,9 +16,12 @@ browser.tabs.onCreated.addListener((tab) => {
message = "Hi!";
clearInterval(intervalId);
}
- browser.browserAction.setBadgeTextColor({tabId: tab.id, color: "#FFFFFF"});
- browser.browserAction.setBadgeText({tabId: tab.id, text: message});
+ browser.browserAction.setBadgeTextColor({
+ tabId: tab.id,
+ color: "#FFFFFF",
+ });
+ browser.browserAction.setBadgeText({ tabId: tab.id, text: message });
}, 1000);
});
-browser.browserAction.setBadgeBackgroundColor({color: "#AAAAAA"}); \ No newline at end of file
+browser.browserAction.setBadgeBackgroundColor({ color: "#AAAAAA" });
diff --git a/mobile/android/android-components/samples/browser/src/main/assets/extensions/test/manifest.template.json b/mobile/android/android-components/samples/browser/src/main/assets/extensions/test/manifest.template.json
index 04dc17aa2f..57e0949ec0 100644
--- a/mobile/android/android-components/samples/browser/src/main/assets/extensions/test/manifest.template.json
+++ b/mobile/android/android-components/samples/browser/src/main/assets/extensions/test/manifest.template.json
@@ -16,7 +16,5 @@
"default_title": "Test",
"default_popup": "popup.html"
},
- "permissions": [
- "tabs"
- ]
+ "permissions": ["tabs"]
}
diff --git a/mobile/android/android-components/samples/browser/src/main/java/org/mozilla/samples/browser/BaseBrowserFragment.kt b/mobile/android/android-components/samples/browser/src/main/java/org/mozilla/samples/browser/BaseBrowserFragment.kt
index 7cef15d75f..bf5efccc2b 100644
--- a/mobile/android/android-components/samples/browser/src/main/java/org/mozilla/samples/browser/BaseBrowserFragment.kt
+++ b/mobile/android/android-components/samples/browser/src/main/java/org/mozilla/samples/browser/BaseBrowserFragment.kt
@@ -82,6 +82,7 @@ abstract class BaseBrowserFragment : Fragment(), UserInteractionHandler, Activit
feature = SessionFeature(
components.store,
components.sessionUseCases.goBack,
+ components.sessionUseCases.goForward,
binding.engineView,
sessionId,
),
diff --git a/mobile/android/android-components/samples/crash/build.gradle b/mobile/android/android-components/samples/crash/build.gradle
index 9ea07c4d9f..776cb2d8f4 100644
--- a/mobile/android/android-components/samples/crash/build.gradle
+++ b/mobile/android/android-components/samples/crash/build.gradle
@@ -42,6 +42,7 @@ dependencies {
implementation ComponentsDependencies.kotlin_coroutines
implementation ComponentsDependencies.androidx_appcompat
+ implementation ComponentsDependencies.androidx_core_ktx
implementation ComponentsDependencies.google_material
implementation ComponentsDependencies.androidx_recyclerview
}
diff --git a/mobile/android/android-components/samples/firefox-accounts/build.gradle b/mobile/android/android-components/samples/firefox-accounts/build.gradle
index c6a7d616e9..cade498470 100644
--- a/mobile/android/android-components/samples/firefox-accounts/build.gradle
+++ b/mobile/android/android-components/samples/firefox-accounts/build.gradle
@@ -45,6 +45,7 @@ dependencies {
implementation project(':lib-fetch-httpurlconnection')
implementation ComponentsDependencies.androidx_constraintlayout
+ implementation ComponentsDependencies.androidx_core_ktx
implementation ComponentsDependencies.kotlin_coroutines
diff --git a/mobile/android/android-components/samples/sync/src/main/java/org/mozilla/samples/sync/MainActivity.kt b/mobile/android/android-components/samples/sync/src/main/java/org/mozilla/samples/sync/MainActivity.kt
index 06f889d441..55d243d4cd 100644
--- a/mobile/android/android-components/samples/sync/src/main/java/org/mozilla/samples/sync/MainActivity.kt
+++ b/mobile/android/android-components/samples/sync/src/main/java/org/mozilla/samples/sync/MainActivity.kt
@@ -278,15 +278,20 @@ class MainActivity :
events.forEach {
when (it) {
is AccountEvent.DeviceCommandIncoming -> {
- when (it.command) {
+ val cmd = it.command
+ when (cmd) {
is DeviceCommandIncoming.TabReceived -> {
- val cmd = it.command as DeviceCommandIncoming.TabReceived
var tabsStringified = "Tab(s) from: ${cmd.from?.displayName}\n"
cmd.entries.forEach { tab ->
tabsStringified += "${tab.title}: ${tab.url}\n"
}
txtView.text = tabsStringified
}
+ is DeviceCommandIncoming.TabsClosed -> {
+ var urlsStringified = "Tabs closed from: ${cmd.from?.displayName}\n"
+ cmd.urls.forEach { url -> urlsStringified += "${url}\n" }
+ txtView.text = urlsStringified
+ }
}
}
is AccountEvent.ProfileUpdated -> {
diff --git a/mobile/android/android-components/samples/toolbar/build.gradle b/mobile/android/android-components/samples/toolbar/build.gradle
index 896f3c77f1..80c58683dc 100644
--- a/mobile/android/android-components/samples/toolbar/build.gradle
+++ b/mobile/android/android-components/samples/toolbar/build.gradle
@@ -53,5 +53,6 @@ dependencies {
implementation ComponentsDependencies.kotlin_coroutines
implementation ComponentsDependencies.androidx_appcompat
+ implementation ComponentsDependencies.androidx_core_ktx
implementation ComponentsDependencies.androidx_recyclerview
}
diff --git a/mobile/android/android-components/settings.gradle b/mobile/android/android-components/settings.gradle
index 50c58ed003..75297593e1 100644
--- a/mobile/android/android-components/settings.gradle
+++ b/mobile/android/android-components/settings.gradle
@@ -27,6 +27,7 @@ plugins {
ext.topsrcdir = rootProject.projectDir.absolutePath.minus("mobile/android/android-components")
apply from: file('../shared-settings.gradle')
+apply from: file('../autopublish-settings.gradle')
buildCache {
local {
@@ -35,67 +36,13 @@ buildCache {
}
}
-def runCmd(cmd, workingDir, successMessage) {
- def proc = cmd.execute(null, new File(workingDir))
- proc.consumeProcessOutput(System.out, System.err)
- proc.waitFor()
- if (proc.exitValue() != 0) {
- throw new GradleException("Process '${cmd}' finished with non-zero exit value ${proc.exitValue()}")
- } else {
- logger.lifecycle(successMessage)
+def projectLocalProperties = file("local.properties").with { localPropertiesFile ->
+ def localProperties = new Properties()
+ if (localPropertiesFile.canRead()) {
+ localPropertiesFile.withInputStream { localProperties.load(it) }
}
+ localProperties
}
-
-//////////////////////////////////////////////////////////////////////////
-// Local Development overrides
-//////////////////////////////////////////////////////////////////////////
-
-Properties localProperties = null;
-String settingAppServicesPath = "autoPublish.application-services.dir"
-String settingGleanPath = "autoPublish.glean.dir";
-
-if (file('local.properties').canRead()) {
- localProperties = new Properties()
- localProperties.load(file('local.properties').newDataInputStream())
- logger.lifecycle('Local configuration: loaded local.properties')
-} else {
- logger.lifecycle('Local configuration: absent local.properties; proceeding as normal.')
-}
-
-if (localProperties != null) {
- localProperties.each { prop ->
- gradle.ext.set("localProperties.${prop.key}", prop.value)
- }
-
- String appServicesLocalPath = localProperties.getProperty(settingAppServicesPath);
-
- if (appServicesLocalPath != null) {
- logger.lifecycle("Enabling automatic publication of application-services from: $appServicesLocalPath")
- // Windows can't execute .py files directly, so we assume a "manually installed" python,
- // which comes with a "py" launcher and respects the shebang line to specify the version.
- def publishAppServicesCmd = [];
- if (System.properties['os.name'].toLowerCase().contains('windows')) {
- publishAppServicesCmd << "py";
- }
- publishAppServicesCmd << "./automation/publish_to_maven_local_if_modified.py";
- runCmd(publishAppServicesCmd, appServicesLocalPath, "Published application-services for local development.")
- } else {
- logger.lifecycle("Disabled auto-publication of application-services. Enable it by settings '$settingAppServicesPath' in local.properties")
- }
-
- String gleanLocalPath = localProperties.getProperty(settingGleanPath);
-
- if (gleanLocalPath != null) {
- logger.lifecycle("Enabling automatic publication of Glean from: $gleanLocalPath")
- // Windows can't execute .py files directly, so we assume a "manually installed" python,
- // which comes with a "py" launcher and respects the shebang line to specify the version.
- def publishGleanCmd = [];
- if (System.properties['os.name'].toLowerCase().contains('windows')) {
- publishGleanCmd << "py";
- }
- publishGleanCmd << "./build-scripts/publish_to_maven_local_if_modified.py";
- runCmd(publishGleanCmd, gleanLocalPath, "Published Glean for local development.")
- } else {
- logger.lifecycle("Disabled auto-publication of Glean. Enable it by settings '$settingGleanPath' in local.properties")
- }
+projectLocalProperties.each { prop ->
+ gradle.ext."localProperties.${prop.key}" = prop.value
}